├── .all-contributorsrc
├── .editorconfig
├── .github
├── renovate.json
├── stale.yml
└── workflows
│ ├── release.yml
│ ├── test.yml
│ └── update-prettier.yml
├── .gitignore
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── script
├── make-executable.js
├── setup.sh
├── test-all-templates.sh
└── test-template.sh
├── src
├── create-probot-app.ts
├── helpers
│ ├── filesystem.ts
│ ├── init-git.ts
│ ├── run-npm.ts
│ ├── user-interaction.ts
│ └── write-help.ts
├── run-tests.ts
└── types
│ ├── conjecture.d.ts
│ ├── egad.d.ts
│ └── stringify-author.d.ts
├── templates
├── __common__
│ ├── .dockerignore
│ ├── .env.example
│ ├── CODE_OF_CONDUCT.md
│ ├── CONTRIBUTING.md
│ ├── Dockerfile
│ ├── LICENSE
│ ├── README.md
│ ├── gitignore
│ └── test
│ │ └── fixtures
│ │ └── mock-cert.pem
├── basic-js
│ ├── __description__.txt
│ ├── app.yml
│ ├── index.js
│ ├── package.json
│ └── test
│ │ ├── fixtures
│ │ └── issues.opened.json
│ │ └── index.test.js
├── basic-ts
│ ├── __description__.txt
│ ├── app.yml
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ ├── test
│ │ ├── fixtures
│ │ │ └── issues.opened.json
│ │ └── index.test.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── checks-js
│ ├── __description__.txt
│ ├── app.yml
│ ├── index.js
│ ├── package.json
│ └── test
│ │ ├── fixtures
│ │ ├── check_run.created.json
│ │ └── check_suite.requested.json
│ │ └── index.test.js
├── deploy-js
│ ├── __description__.txt
│ ├── app.yml
│ ├── index.js
│ ├── package.json
│ └── test
│ │ ├── fixtures
│ │ └── pull_request.opened.json
│ │ └── index.test.js
└── git-data-js
│ ├── __description__.txt
│ ├── app.yml
│ ├── index.js
│ ├── package.json
│ └── test
│ ├── fixtures
│ └── installation.created.json
│ └── index.test.js
├── tsconfig.all.json
└── tsconfig.json
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "contributors": [
8 | {
9 | "login": "MaximDevoir",
10 | "name": "Maxim Devoir",
11 | "avatar_url": "https://avatars3.githubusercontent.com/u/10104630?v=4",
12 | "profile": "https://create-nom.app",
13 | "contributions": [
14 | "code",
15 | "review"
16 | ]
17 | },
18 | {
19 | "login": "shaftoe",
20 | "name": "Alexander Fortin",
21 | "avatar_url": "https://avatars1.githubusercontent.com/u/281389?v=4",
22 | "profile": "https://a.l3x.in/",
23 | "contributions": [
24 | "code"
25 | ]
26 | },
27 | {
28 | "login": "hiimbex",
29 | "name": "Bex Warner",
30 | "avatar_url": "https://avatars1.githubusercontent.com/u/13410355?v=4",
31 | "profile": "http://hiimbex.com",
32 | "contributions": [
33 | "code",
34 | "review"
35 | ]
36 | },
37 | {
38 | "login": "tcbyrd",
39 | "name": "Tommy Byrd",
40 | "avatar_url": "https://avatars0.githubusercontent.com/u/13207348?v=4",
41 | "profile": "https://github.com/tcbyrd",
42 | "contributions": [
43 | "code"
44 | ]
45 | },
46 | {
47 | "login": "JasonEtco",
48 | "name": "Jason Etcovitch",
49 | "avatar_url": "https://avatars1.githubusercontent.com/u/10660468?v=4",
50 | "profile": "https://jasonet.co",
51 | "contributions": [
52 | "code"
53 | ]
54 | }
55 | ],
56 | "contributorsPerLine": 7,
57 | "projectName": "create-probot-app",
58 | "projectOwner": "probot",
59 | "repoType": "github",
60 | "repoHost": "https://github.com",
61 | "skipCi": true
62 | }
63 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["github>probot/.github"]
3 | }
4 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Configuration for https://github.com/probot/stale
2 | _extends: .github
3 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | "on":
3 | push:
4 | branches:
5 | - master
6 | jobs:
7 | release:
8 | name: release
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/checkout@v4
12 | - uses: actions/setup-node@v4
13 | with:
14 | node-version: lts/*
15 | cache: npm
16 | - run: npm ci
17 | - run: npm run build --if-present
18 | - run: npx semantic-release
19 | env:
20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
22 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Test
2 | "on":
3 | push:
4 | branches:
5 | - master
6 | pull_request:
7 | types:
8 | - opened
9 | - synchronize
10 | jobs:
11 | test_matrix:
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | node:
16 | - 18
17 | - 20
18 | - 21
19 | steps:
20 | - uses: actions/checkout@v4
21 | - uses: actions/setup-node@v4
22 | with:
23 | node-version: ${{ matrix.node }}
24 | cache: npm
25 | - run: npm ci
26 | - run: npm run build
27 | - run: npm run test
28 | test:
29 | needs: test_matrix
30 | runs-on: ubuntu-latest
31 | steps:
32 | - uses: actions/checkout@v4
33 | - uses: actions/setup-node@v4
34 | with:
35 | node-version: 18
36 | cache: npm
37 | - run: npm install
38 | - run: npm run lint
39 |
--------------------------------------------------------------------------------
/.github/workflows/update-prettier.yml:
--------------------------------------------------------------------------------
1 | name: Update Prettier
2 | "on":
3 | push:
4 | branches:
5 | - dependabot/npm_and_yarn/prettier-*
6 | jobs:
7 | update_prettier:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v4
11 | - uses: actions/setup-node@v4
12 | with:
13 | cache: npm
14 | node-version: 16
15 | - run: npm ci
16 | - run: npm run lint:fix
17 | - uses: gr2m/create-or-update-pull-request-action@v1.x
18 | env:
19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
20 | with:
21 | title: Prettier updated
22 | body: An update to prettier required updates to your code.
23 | branch: ${{ github.ref }}
24 | commit-message: "style: prettier"
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | node_modules
3 |
4 | # Output folder
5 | bin
6 |
7 | # Logs
8 | *.log
9 |
10 | # Yarn lockfile. Use package-lock.json instead.
11 | yarn.lock
12 |
13 | # Test-related generated folders
14 | coverage
15 |
16 | # Miscellaneous
17 | .DS_Store
18 | Thumbs.db
19 | .vscode
20 | __create_probot_app__*
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | ISC License
2 |
3 | Copyright (c) 2017, Brandon Keepers
4 |
5 | Permission to use, copy, modify, and/or distribute this software for any
6 | purpose with or without fee is hereby granted, provided that the above
7 | copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Create Probot App
2 |
3 | [](https://github.com/probot/create-probot-app/actions)
4 |
5 | `create-probot-app` is a _command line_ (CLI) Node.js application that generates a new [Probot](https://github.com/probot/probot) app with everything you need to get started building. 👷🏽
6 |
7 | More specifically, this command line interface allows you to select from our pre-defined blueprints to choose a basic working example to start from.
8 |
9 | ## Installation
10 |
11 | Make sure you've got [Node.js installed](https://Node.js.org/en/download/) on your workstation, then open your terminal and type the following command:
12 |
13 | - if you're using `npm` (the package manager bundled with `Node.js`):
14 |
15 | ```sh
16 | npx create-probot-app my-first-app
17 | ```
18 |
19 | - if you're using Yarn:
20 |
21 | ```sh
22 | yarn create probot-app my-first-app
23 | ```
24 |
25 | and follow the instructions printed on the terminal as you go. `create-probot-app` will then take care of the heavy lifting required to setup a Probot app development environment, with proper folder structure, and even installing all the basic `Probot` dependencies.
26 |
27 | ## How to run locally
28 |
29 | See the [Probot docs](https://probot.github.io/docs/development/#running-the-app-locally) to get started running your app locally.
30 |
31 | ## Contributors ✨
32 |
33 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
34 |
35 |
36 |
37 |
38 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
54 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-probot-app",
3 | "version": "0.0.0-development",
4 | "description": "Create a Probot app",
5 | "bin": {
6 | "create-probot-app": "./bin/create-probot-app.js",
7 | "run-tests": "./bin/run-tests.js"
8 | },
9 | "files": [
10 | "bin",
11 | "templates"
12 | ],
13 | "scripts": {
14 | "test": "./script/test-all-templates.sh",
15 | "test:template": "./script/test-template.sh",
16 | "lint": "prettier --ignore-path .gitignore --check '**/*.{js,ts,json,yml,md}'",
17 | "lint:fix": "prettier --ignore-path .gitignore --write '**/*.{js,ts,json,yml,md}'",
18 | "dev:make-cpa": "node --input-type=module -e 'import { chBinMod } from \"./script/make-executable.js\"; chBinMod(\"create-probot-app\")'",
19 | "dev:make-tests": "node --input-type=module -e 'import { chBinMod } from \"./script/make-executable.js\"; chBinMod(\"run-tests\")'",
20 | "build": "npm run build:clean && tsc && npm run dev:make-cpa && npm run dev:make-tests",
21 | "build:clean": "rimraf bin",
22 | "build:source": "tsc && npm run dev:make-cpa",
23 | "build:tests": "tsc && npm run dev:make-tests"
24 | },
25 | "repository": "github:probot/create-probot-app",
26 | "keywords": [
27 | "probot"
28 | ],
29 | "author": "Brandon Keepers",
30 | "license": "ISC",
31 | "dependencies": {
32 | "chalk": "^5.2.0",
33 | "commander": "^12.0.0",
34 | "conjecture": "^0.1.2",
35 | "egad": "^0.2.0",
36 | "execa": "^8.0.1",
37 | "inquirer": "^9.1.4",
38 | "jsesc": "^3.0.2",
39 | "lodash.camelcase": "^4.3.0",
40 | "lodash.kebabcase": "^4.1.1",
41 | "simple-git": "^3.22.0",
42 | "stringify-author": "^0.1.3",
43 | "validate-npm-package-name": "^5.0.0"
44 | },
45 | "devDependencies": {
46 | "@types/cross-spawn": "^6.0.2",
47 | "@types/inquirer": "^9.0.3",
48 | "@types/jsesc": "^3.0.1",
49 | "@types/lodash.camelcase": "^4.3.7",
50 | "@types/lodash.kebabcase": "^4.1.7",
51 | "@types/node": "^20.0.0",
52 | "@types/rimraf": "^4.0.5",
53 | "@types/validate-npm-package-name": "^4.0.0",
54 | "prettier": "^3.2.4",
55 | "rimraf": "^5.0.5",
56 | "semantic-release": "^24.0.0",
57 | "typescript": "^5.3.3"
58 | },
59 | "type": "module",
60 | "engines": {
61 | "node": ">= 18"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/script/make-executable.js:
--------------------------------------------------------------------------------
1 | import fs from "node:fs";
2 | import path from "node:path";
3 | import { fileURLToPath } from "node:url";
4 |
5 | import pkg from "../package.json" with { type: "json" };
6 |
7 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
8 |
9 | const TYPE_MASK = parseInt("0770000", 8);
10 |
11 | /**
12 | * Converts TS file under ./bin/ into an executable file.
13 | *
14 | * By default, the compiled `bin/*.js` scripts ar not executable.
15 | * When a developer is modifying the application, they won't be able to run the
16 | * compiled scripts from the CLI.
17 | *
18 | * This utility function applies executable permissions to the compiled binary script.
19 | *
20 | * @param {string} name the name of the built JS file, e.g. 'create-probot-app'
21 | */
22 | export function chBinMod(name) {
23 | const binList = pkg.bin;
24 | const jsFilePath = binList[name];
25 | const distributableBinary = path.join(__dirname, "..", jsFilePath);
26 |
27 | try {
28 | if (fs.existsSync(distributableBinary)) {
29 | const currentMode = fs.statSync(distributableBinary).mode;
30 | let execMode = currentMode | ((currentMode >>> 2) & TYPE_MASK);
31 | // Add execute permissions for owner, group, and others.
32 | execMode |= 0o111;
33 | fs.chmodSync(distributableBinary, execMode);
34 | console.log(`Converted ${name} to an executable binary.`);
35 | }
36 | } catch (err) {
37 | console.error(err);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/script/setup.sh:
--------------------------------------------------------------------------------
1 | set -Ee # Exit immediately if a command returns a non-zero status
2 | set -u # Exit when references variables are undefined
3 | set -o pipefail # Exit when any program execution in a pipeline breaks
4 |
--------------------------------------------------------------------------------
/script/test-all-templates.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./script/setup.sh
3 |
4 | TEMPLATES=$(./bin/create-probot-app.js --show-templates ALL)
5 |
6 | for template in $TEMPLATES; do
7 | npm run test:template $template;
8 | done
9 |
--------------------------------------------------------------------------------
/script/test-template.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | . ./script/setup.sh
3 |
4 | readonly APP="./bin/create-probot-app.js"
5 | readonly TEMPLATE=$1
6 | readonly TEST_FOLDER=$(mktemp -d -t cpa-XXXXXXXXXX)
7 | readonly LOGFILENAME="test.output"
8 | readonly LOGFILE="${TEST_FOLDER}/${LOGFILENAME}"
9 |
10 | function create_app() {
11 | mkdir -p "$TEST_FOLDER"
12 | "$APP" \
13 | --appName "template-test-app" \
14 | --desc "A Probot App for building on Travis" \
15 | --author "Pro Báwt" \
16 | --email "probot@example.com" \
17 | --user "probot" \
18 | --template "$TEMPLATE" \
19 | --repo "create-probot-app-${TEMPLATE}" \
20 | "$TEST_FOLDER"
21 | }
22 |
23 | function run_npm_tests() {
24 | echo; echo "--[test ${TEMPLATE}]-- Run npm tests... "
25 | cd "$TEST_FOLDER"
26 | npm test 2>&1 | tee "$LOGFILENAME"
27 | cd - > /dev/null
28 | }
29 |
30 | echo "--[test ${TEMPLATE}]-- Run tests in ${TEST_FOLDER} folder"
31 | create_app
32 | run_npm_tests
33 | ./bin/run-tests.js $TEMPLATE $TEST_FOLDER
34 | echo "--[test ${TEMPLATE}]-- All tests completed successfully!"
35 |
--------------------------------------------------------------------------------
/src/create-probot-app.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import { askUser, runCliManager } from "./helpers/user-interaction.js";
3 | import { initGit } from "./helpers/init-git.js";
4 | import { installAndBuild } from "./helpers/run-npm.js";
5 | import { makeScaffolding } from "./helpers/filesystem.js";
6 | import { printSuccess, red } from "./helpers/write-help.js";
7 |
8 | runCliManager()
9 | .then((cliConfig) => askUser(cliConfig))
10 | .then((config) => makeScaffolding(config))
11 | .then(async (config) => {
12 | if (config.gitInit) await initGit(config.destination);
13 | return config;
14 | })
15 | .then(async (config) => await installAndBuild(config))
16 | .then((config) => printSuccess(config.appName, config.destination))
17 | .catch((err) => {
18 | console.log(red(err));
19 | process.exit(1);
20 | });
21 |
--------------------------------------------------------------------------------
/src/helpers/filesystem.ts:
--------------------------------------------------------------------------------
1 | import * as path from "node:path";
2 | import { fileURLToPath } from "node:url";
3 | import * as fs from "node:fs";
4 | import { generate } from "egad";
5 | import { Config } from "./user-interaction.js";
6 | import { yellow, green } from "./write-help.js";
7 |
8 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
9 |
10 | export const templatesSourcePath = path.join(__dirname, "../../templates/");
11 |
12 | /**
13 | * Validate `destination` path, throw error if not valid (e.g not an empty folder)
14 | * @param {string} destination destination path
15 | * @param {boolean} overwrite if true, don't throw error if path is a non-empty valid folder
16 | */
17 | export function ensureValidDestination(
18 | destination: string,
19 | overwrite: boolean,
20 | ): void {
21 | const invalidDestinationError: Error =
22 | new Error(`Invalid destination folder => ${destination}
23 | Please provide either an empty folder or a non existing path as
24 | `);
25 |
26 | try {
27 | fs.lstatSync(destination);
28 |
29 | try {
30 | fs.realpathSync(destination);
31 | } catch (error: any) {
32 | if (error.code === "ENOENT") throw invalidDestinationError; // Edge case: destination is a broken link
33 | }
34 | } catch (error: any) {
35 | if (error.code === "ENOENT") return;
36 | // The `destination` is neither a broken link nor an existing path
37 | else throw error;
38 | }
39 |
40 | if (fs.statSync(destination).isDirectory()) {
41 | if (fs.readdirSync(destination).length === 0) return; // Empty folder
42 | if (overwrite) {
43 | console.warn(
44 | yellow(`Explicit OVERWRITE option selected:
45 | Some files under "${fs.realpathSync(destination)}" might be overwritten!
46 | `),
47 | );
48 | return;
49 | }
50 | }
51 |
52 | // The `destination` is neither a valid folder nor an empty one
53 | throw invalidDestinationError;
54 | }
55 |
56 | /**
57 | * Create files and folder structure from Handlebars templates.
58 | *
59 | * @param {Config} config configuration object
60 | * @returns Promise which returns the input Config object
61 | */
62 | export async function makeScaffolding(config: Config): Promise {
63 | // Prepare template folder Handlebars source content merging `templates/__common__` and `templates/`
64 | const tempDestPath = fs.mkdtempSync("__create_probot_app__");
65 | [
66 | path.join(templatesSourcePath, "__common__"),
67 | path.join(templatesSourcePath, config.template),
68 | ].forEach((source) =>
69 | fs.cpSync(source, tempDestPath, {
70 | recursive: true,
71 | }),
72 | );
73 |
74 | fs.rmSync(path.join(tempDestPath, "__description__.txt"));
75 |
76 | if (fs.existsSync(path.join(tempDestPath, "gitignore")))
77 | fs.renameSync(
78 | path.join(tempDestPath, "gitignore"),
79 | path.join(tempDestPath, ".gitignore"),
80 | );
81 |
82 | const result = await generate(tempDestPath, config.destination, config, {
83 | overwrite: config.overwrite,
84 | });
85 |
86 | fs.rmSync(tempDestPath, {
87 | recursive: true,
88 | });
89 |
90 | result.forEach((fileInfo) => {
91 | console.log(
92 | `${
93 | fileInfo.skipped
94 | ? yellow("skipped existing file")
95 | : green("created file")
96 | }: ${fileInfo.path}`,
97 | );
98 | });
99 |
100 | console.log(green("\nFinished scaffolding files!"));
101 | return config;
102 | }
103 |
104 | interface Template {
105 | name: string;
106 | description: string;
107 | }
108 |
109 | export function getTemplates(): Template[] {
110 | return fs
111 | .readdirSync(templatesSourcePath)
112 | .filter((path) => path.substr(0, 2) !== "__")
113 | .map((template) => {
114 | let descFile = path.join(
115 | templatesSourcePath,
116 | template,
117 | "__description__.txt",
118 | );
119 | return {
120 | name: template,
121 | description: fs.readFileSync(descFile).toString().trimEnd(),
122 | };
123 | });
124 | }
125 |
--------------------------------------------------------------------------------
/src/helpers/init-git.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "node:fs";
2 | import * as path from "node:path";
3 | import { execa } from "execa";
4 | import simplegit from "simple-git";
5 |
6 | import { green, yellow, red } from "./write-help.js";
7 |
8 | function isInGitRepo(path: string): boolean {
9 | const gitRevParse = execa("git", ["rev-parse", "--is-inside-work-tree"], {
10 | cwd: path,
11 | stdio: "ignore",
12 | });
13 |
14 | if (gitRevParse.exitCode === 0) {
15 | console.log("Found already initialized Git repository");
16 | return true;
17 | }
18 | return false;
19 | }
20 |
21 | function isGitInstalled(): boolean {
22 | try {
23 | execa("git", ["--version"], {
24 | stdio: "ignore",
25 | });
26 | } catch (error: any) {
27 | console.log("`git` binary not found");
28 | return false;
29 | }
30 | return true;
31 | }
32 |
33 | /**
34 | * Initialize a Git repository in target destination folder
35 | *
36 | * @param {String} destination the destination folder path
37 | */
38 | export async function initGit(destination: string): Promise {
39 | let initializedGit = false;
40 |
41 | console.log(`\nInitializing Git repository in folder '${destination}'`);
42 |
43 | if (!isGitInstalled() || isInGitRepo(destination)) {
44 | console.log(yellow("Skipping Git initialization"));
45 | return;
46 | }
47 |
48 | const git = simplegit(destination);
49 |
50 | try {
51 | await git
52 | .init()
53 | .then(() => (initializedGit = true))
54 | .then(() => git.add("./*"))
55 | .then(() => git.commit("Initial commit from Create Probot App"))
56 | .then(() => console.log(green("Initialized a Git repository")));
57 | } catch (error) {
58 | if (initializedGit) {
59 | const gitFolder = path.join(destination, ".git");
60 | console.log(red(`Cleaning up ${gitFolder} folder`));
61 | try {
62 | fs.rmdirSync(gitFolder);
63 | } catch {}
64 | }
65 | console.log(red(`Errors while initializing Git repo: ${error}`));
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/helpers/run-npm.ts:
--------------------------------------------------------------------------------
1 | import { bold, yellow } from "./write-help.js";
2 | import { Config } from "./user-interaction.js";
3 | import { execa } from "execa";
4 |
5 | export function detectPackageManager(): string {
6 | const { npm_config_user_agent: userAgent } = process.env;
7 | if (userAgent) {
8 | if (userAgent.includes("yarn")) return "yarn";
9 | if (userAgent.includes("npm")) return "npm";
10 | }
11 | return "npm";
12 | }
13 |
14 | /**
15 | * Run `npm install` in `destination` folder, then run `npm run build`
16 | * if `toBuild` is true
17 | *
18 | * @param {Config} config configuration object
19 | *
20 | * @returns Promise which returns the input Config object
21 | */
22 | export async function installAndBuild(config: Config): Promise {
23 | const originalDir = process.cwd();
24 | process.chdir(config.destination);
25 | const packageManager = detectPackageManager();
26 | console.log(
27 | yellow("\nInstalling dependencies. This may take a few minutes...\n"),
28 | );
29 | try {
30 | await execa(packageManager, ["install"]);
31 | } catch (error: any) {
32 | process.chdir(originalDir);
33 | throw new Error(
34 | `\nCould not install npm dependencies.\nTry running ${bold(
35 | "npm install",
36 | )} yourself.\n`,
37 | );
38 | }
39 | if (config.toBuild) {
40 | console.log(yellow("\n\nCompile application...\n"));
41 | try {
42 | await execa(packageManager, ["run", "build"]);
43 | } catch (error: any) {
44 | process.chdir(originalDir);
45 | throw new Error(
46 | `\nCould not build application.\nTry running ${bold(
47 | "npm run build",
48 | )} yourself.\n`,
49 | );
50 | }
51 | }
52 | process.chdir(originalDir);
53 | return config;
54 | }
55 |
--------------------------------------------------------------------------------
/src/helpers/user-interaction.ts:
--------------------------------------------------------------------------------
1 | import * as fs from "node:fs";
2 | import * as path from "node:path";
3 | import { fileURLToPath } from "node:url";
4 |
5 | import { guessEmail, guessGitHubUsername, guessAuthor } from "conjecture";
6 | import camelCase from "lodash.camelcase";
7 | import * as commander from "commander";
8 | import inquirer, { Answers, Question, QuestionCollection } from "inquirer";
9 | import jsesc from "jsesc";
10 | import kebabCase from "lodash.kebabcase";
11 | import stringifyAuthor from "stringify-author";
12 | import validatePackageName from "validate-npm-package-name";
13 |
14 | import { blue, red, printHelpAndFail } from "./write-help.js";
15 | import { getTemplates, ensureValidDestination } from "./filesystem.js";
16 |
17 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
18 |
19 | const templateDelimiter = " => ";
20 |
21 | type QuestionI =
22 | | (
23 | | {
24 | default?(answers: Answers): string | boolean;
25 | }
26 | | Question
27 | )
28 | | QuestionCollection;
29 |
30 | interface CliConfig {
31 | destination: string;
32 | gitInit: boolean;
33 | overwrite: boolean;
34 | appName?: string;
35 | author?: string;
36 | description?: string;
37 | email?: string;
38 | repo?: string;
39 | template?: string;
40 | user?: string;
41 | }
42 |
43 | export interface Config extends CliConfig, Answers {
44 | appName: string;
45 | camelCaseAppName: string;
46 | description: string;
47 | template: string;
48 | toBuild: boolean;
49 | year: number;
50 | owner?: string;
51 | }
52 |
53 | /**
54 | * Partially sanitizes keys by escaping double-quotes.
55 | *
56 | * @param {Object} object The object to mutate.
57 | * @param {String[]} keys The keys on `object` to sanitize.
58 | */
59 | function sanitizeBy(object: Config, keys: string[]): void {
60 | keys.forEach((key) => {
61 | if (key in object) {
62 | object[key] = jsesc(object[key], {
63 | minimal: true,
64 | quotes: "double",
65 | });
66 | }
67 | });
68 | }
69 |
70 | function getQuestions(config: CliConfig): QuestionI[] {
71 | const templates = getTemplates();
72 |
73 | const questions: QuestionI[] = [
74 | {
75 | type: "input",
76 | name: "appName",
77 | default(answers: Answers): string {
78 | return answers.repo || kebabCase(path.basename(config.destination));
79 | },
80 | message: "App name:",
81 | when: !config.appName,
82 | validate(appName): true | string {
83 | const result = validatePackageName(appName);
84 | if (result.errors && result.errors.length > 0) {
85 | return result.errors.join(",");
86 | }
87 |
88 | return true;
89 | },
90 | },
91 | {
92 | type: "input",
93 | name: "description",
94 | default(): string {
95 | return "A Probot app";
96 | },
97 | message: "Description of app:",
98 | when: !config.description,
99 | },
100 | {
101 | type: "input",
102 | name: "author",
103 | default(): string {
104 | return guessAuthor();
105 | },
106 | message: "Author's full name:",
107 | when: !config.author,
108 | },
109 | {
110 | type: "input",
111 | name: "email",
112 | default(): Promise {
113 | return guessEmail();
114 | },
115 | message: "Author's email address:",
116 | when: config.gitInit && !config.email,
117 | },
118 | {
119 | type: "input",
120 | name: "user",
121 | default(answers: Answers): Promise {
122 | return guessGitHubUsername(answers.email);
123 | },
124 | message: "GitHub user or org name:",
125 | when: config.gitInit && !config.user,
126 | },
127 | {
128 | type: "input",
129 | name: "repo",
130 | default(answers: Answers): string {
131 | return answers.appName || kebabCase(path.basename(config.destination));
132 | },
133 | message: "Repository name:",
134 | when: config.gitInit && !config.repo,
135 | },
136 | {
137 | type: "list",
138 | name: "template",
139 | choices: templates.map(
140 | (template) =>
141 | `${template.name}${templateDelimiter}${template.description}`,
142 | ),
143 | message: "Which template would you like to use?",
144 | when(): boolean {
145 | if (config.template) {
146 | if (templates.find((template) => template.name === config.template)) {
147 | return false;
148 | }
149 | console.log(
150 | red(`The template ${blue(config.template)} does not exist.`),
151 | );
152 | }
153 | return true;
154 | },
155 | },
156 | ];
157 |
158 | return questions;
159 | }
160 |
161 | /**
162 | * Prompt the user for mandatory options not set via CLI
163 | *
164 | * @param config Configuration data already set via CLI options
165 | *
166 | * @returns the merged configuration options from CLI and user prompt
167 | */
168 | export async function askUser(config: CliConfig): Promise {
169 | console.log(
170 | "\nLet's create a Probot app!\nHit enter to accept the suggestion.\n",
171 | );
172 |
173 | const answers = {
174 | ...config,
175 | ...((await inquirer.prompt(getQuestions(config))) as Config),
176 | };
177 |
178 | // enrich with (meta)data + sanitize input
179 | answers.author = stringifyAuthor({
180 | name: answers.author,
181 | email: answers.email,
182 | });
183 | answers.toBuild = answers.template.slice(-3) === "-ts";
184 | answers.year = new Date().getFullYear();
185 | answers.camelCaseAppName = camelCase(config.appName || answers.appName);
186 | answers.owner = answers.user;
187 | answers.template = answers.template.split(templateDelimiter)[0]; // remove eventual description
188 | sanitizeBy(answers, ["author", "description"]);
189 |
190 | return answers;
191 | }
192 |
193 | /**
194 | * Run CLI manager to parse user provided options and arguments
195 | *
196 | * @returns resolves with the configuration options set via CLI
197 | */
198 | export async function runCliManager(): Promise {
199 | let destination: string = "";
200 |
201 | // TSC mangles output directory when using normal import methods for
202 | // package.json. See
203 | // https://github.com/Microsoft/TypeScript/issues/24715#issuecomment-542490675
204 | const pkg = JSON.parse(
205 | fs.readFileSync(path.join(__dirname, "..", "..", "package.json"), "utf-8"),
206 | );
207 |
208 | const program = new commander.Command("create-probot-app")
209 | .arguments("[destination]")
210 | .action((dest) => {
211 | if (dest) {
212 | destination = path.isAbsolute(dest)
213 | ? dest
214 | : path.resolve(process.cwd(), dest);
215 | }
216 | })
217 | .usage("[options] ")
218 | .option("-n, --appName ", "App name")
219 | .option('-d, --desc ""', "Description (contain in quotes)")
220 | .option('-a, --author ""', "Author name (contain in quotes)")
221 | .option("-e, --email ", "Author email address")
222 | .option("-u, --user ", "GitHub username or org (repo owner)")
223 | .option("-r, --repo ", "Repository name")
224 | .option("--overwrite", "Overwrite existing files", false)
225 | .option("-t, --template ", "Name of use case template")
226 | .option("--show-templates", "Print list of available templates and exit")
227 | .option("--no-git-init", "Skip Git repository initialization", false)
228 | .version(`Create Probot App v${pkg.version}`);
229 |
230 | const options = program.parse(process.argv).opts();
231 |
232 | if (options.showTemplates) {
233 | getTemplates().forEach((template) => console.log(template.name));
234 | process.exit();
235 | }
236 |
237 | if (!destination) printHelpAndFail();
238 | ensureValidDestination(destination, options.overwrite);
239 |
240 | return {
241 | appName: options.appName,
242 | author: options.author,
243 | description: options.desc,
244 | destination: destination,
245 | email: options.email,
246 | gitInit: options.gitInit,
247 | overwrite: options.overwrite,
248 | repo: options.repo,
249 | template: options.template,
250 | user: options.user,
251 | };
252 | }
253 |
--------------------------------------------------------------------------------
/src/helpers/write-help.ts:
--------------------------------------------------------------------------------
1 | import chalk from "chalk";
2 | import path from "node:path";
3 |
4 | export const green = chalk.green;
5 | export const blue = chalk.blue;
6 | export const red = chalk.red;
7 | export const yellow = chalk.yellow;
8 | export const bold = chalk.bold;
9 |
10 | const helpLines = [
11 | "",
12 | `Argument ${blue("")} is required.`,
13 | "",
14 | "Example:",
15 | ` ${green("create-probot-app")} ${blue("my-first-app")}`,
16 | "",
17 | `Run ${green("create-probot-app")} --help to see all options.`,
18 | ];
19 |
20 | function writeHelp(): void {
21 | helpLines.forEach((line) => {
22 | console.log(` ${line}`);
23 | });
24 | }
25 |
26 | export function printSuccess(appName: string, destination: string) {
27 | console.log(`
28 | Successfully created ${blue(appName)}.
29 |
30 | Begin using your app with:
31 |
32 | ${green("cd")} ${path.relative(process.cwd(), destination)}
33 | npm start
34 |
35 | Refer to your app's README for more usage instructions.
36 |
37 | Visit the Probot docs
38 | https://probot.github.io/docs/
39 |
40 | Get help from the community:
41 | https://probot.github.io/community/
42 |
43 | ${green("Enjoy building your Probot app!")}`);
44 | }
45 |
46 | export function printHelpAndFail(): void {
47 | console.log(
48 | `${green("create-probot-app")} [options] ${blue("")} `,
49 | );
50 | writeHelp();
51 | process.exit(1);
52 | }
53 |
--------------------------------------------------------------------------------
/src/run-tests.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import fs from "node:fs";
3 | import path from "node:path";
4 | import { red } from "./helpers/write-help.js";
5 |
6 | /**
7 | * Ensure `package.json` from templated app meets all requirements
8 | *
9 | * @param {string} appFolder path to the folder where templated application has been installed
10 | * @returns true if `package.json` is valid
11 | */
12 | function packageIsValid(appFolder: string): boolean {
13 | const packageJsonPath: string = path.join(appFolder, "package.json");
14 | const packageContent = JSON.parse(
15 | fs.readFileSync(packageJsonPath).toString(),
16 | );
17 | const mandatoryKeys: Record = (({
18 | name,
19 | homepage,
20 | description,
21 | }) => ({ name, homepage, description }))(packageContent);
22 |
23 | let errors: boolean = false;
24 |
25 | Object.keys(mandatoryKeys).forEach((key) => {
26 | if (mandatoryKeys[key] === undefined) {
27 | console.log(
28 | red(`ERROR: ${packageJsonPath} is missing mandatory a key: ${key}`),
29 | );
30 | errors = true;
31 | }
32 | });
33 |
34 | return !errors;
35 | }
36 |
37 | /**
38 | * Ensure `test.output` has no warning/errors.
39 | *
40 | * @param {string} appFolder path to installed application
41 | * @return `true` if no errors were found
42 | */
43 | function logIsValid(appFolder: string): boolean {
44 | const logFile = path.join(appFolder, "test.output");
45 | let logContent: string;
46 | let errors: boolean = false;
47 |
48 | try {
49 | logContent = fs.readFileSync(logFile).toString();
50 | } catch (error) {
51 | console.log(red(`ERROR: cannot read content of ${logFile}: ${error}`));
52 | return false;
53 | }
54 |
55 | logContent.split("\n").forEach((line) => {
56 | if (line.match("(WARN|Warn|warn)") || line.match("(ERR|Err|error)")) {
57 | console.log(red("ERROR: found warn/error output in log file:"));
58 | console.log(red(line));
59 | errors = true;
60 | }
61 | });
62 |
63 | return !errors;
64 | }
65 |
66 | // NOTE: argv[0] is /path/to/node, argv[1] is current script
67 | if (process.argv.length < 4)
68 | throw new Error(process.argv[1] + ": Wrong parameters");
69 | const templateName: string = process.argv[2];
70 | const installPath: string = process.argv[3];
71 |
72 | console.log(`--[test ${templateName}]-- Run final validation tests... `);
73 | if (!packageIsValid(installPath) || !logIsValid(installPath)) process.exit(1);
74 |
--------------------------------------------------------------------------------
/src/types/conjecture.d.ts:
--------------------------------------------------------------------------------
1 | export function guessAuthor(): string;
2 |
3 | export function guessEmail(): Promise;
4 |
5 | export function guessGitHubUsername(email: string): Promise;
6 |
--------------------------------------------------------------------------------
/src/types/egad.d.ts:
--------------------------------------------------------------------------------
1 | interface Options {
2 | /**
3 | * Set to `false` to avoid overwriting existing files.
4 | */
5 | overwrite?: boolean;
6 | }
7 |
8 | interface FileResult {
9 | path: string;
10 | skipped: boolean;
11 | }
12 |
13 | export function generate(
14 | source: string,
15 | dest: string,
16 | data?: Record,
17 | opts?: Options,
18 | ): Promise;
19 |
--------------------------------------------------------------------------------
/src/types/stringify-author.d.ts:
--------------------------------------------------------------------------------
1 | interface AuthorI {
2 | name?: string;
3 | email?: string;
4 | url?: string;
5 | }
6 |
7 | export default function stringifyAuthor(author: AuthorI): string;
8 |
--------------------------------------------------------------------------------
/templates/__common__/.dockerignore:
--------------------------------------------------------------------------------
1 | **/node_modules/
2 | **/.git
3 | **/README.md
4 | **/LICENSE
5 | **/.vscode
6 | **/npm-debug.log
7 | **/coverage
8 | **/.env
9 | **/.editorconfig
10 | **/dist
11 | **/*.pem
12 | Dockerfile
13 |
--------------------------------------------------------------------------------
/templates/__common__/.env.example:
--------------------------------------------------------------------------------
1 | # The ID of your GitHub App
2 | APP_ID=
3 | WEBHOOK_SECRET=development
4 |
5 | # Use `trace` to get verbose logging or `info` to show less
6 | LOG_LEVEL=debug
7 |
8 | # Go to https://smee.io/new set this to the URL that you are redirected to.
9 | WEBHOOK_PROXY_URL=
10 |
--------------------------------------------------------------------------------
/templates/__common__/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, gender identity and expression, level of experience,
9 | education, socio-economic status, nationality, personal appearance, race,
10 | religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | - Using welcoming and inclusive language
18 | - Being respectful of differing viewpoints and experiences
19 | - Gracefully accepting constructive criticism
20 | - Focusing on what is best for the community
21 | - Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | - The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | - Trolling, insulting/derogatory comments, and personal or political attacks
28 | - Public or private harassment
29 | - Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | - Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at {{{ email }}}. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
--------------------------------------------------------------------------------
/templates/__common__/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | [fork]: /fork
4 | [pr]: /compare
5 | [code-of-conduct]: CODE_OF_CONDUCT.md
6 |
7 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
8 |
9 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.
10 |
11 | ## Issues and PRs
12 |
13 | If you have suggestions for how this project could be improved, or want to report a bug, open an issue! We'd love all and any contributions. If you have questions, too, we'd love to hear them.
14 |
15 | We'd also love PRs. If you're thinking of a large PR, we advise opening up an issue first to talk about it, though! Look at the links below if you're not sure how to open a PR.
16 |
17 | ## Submitting a pull request
18 |
19 | 1. [Fork][fork] and clone the repository.
20 | 1. Configure and install the dependencies: `npm install`.
21 | 1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so there's no need to lint separately.
22 | 1. Create a new branch: `git checkout -b my-branch-name`.
23 | 1. Make your change, add tests, and make sure the tests still pass.
24 | 1. Push to your fork and [submit a pull request][pr].
25 | 1. Pat your self on the back and wait for your pull request to be reviewed and merged.
26 |
27 | Here are a few things you can do that will increase the likelihood of your pull request being accepted:
28 |
29 | - Write and update tests.
30 | - Keep your changes as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
31 | - Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
32 |
33 | Work in Progress pull requests are also welcome to get feedback early on, or if there is something blocked you.
34 |
35 | ## Resources
36 |
37 | - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
38 | - [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
39 | - [GitHub Help](https://help.github.com)
40 |
--------------------------------------------------------------------------------
/templates/__common__/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:20-slim
2 | WORKDIR /usr/src/app
3 | COPY package.json package-lock.json ./
4 | RUN npm ci --production
5 | RUN npm cache clean --force
6 | ENV NODE_ENV="production"
7 | COPY . .
8 | CMD [ "npm", "start" ]
9 |
--------------------------------------------------------------------------------
/templates/__common__/LICENSE:
--------------------------------------------------------------------------------
1 | ISC License
2 |
3 | Copyright (c) {{{ year }}}, {{{ author }}}
4 |
5 | Permission to use, copy, modify, and/or distribute this software for any
6 | purpose with or without fee is hereby granted, provided that the above
7 | copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 |
--------------------------------------------------------------------------------
/templates/__common__/README.md:
--------------------------------------------------------------------------------
1 | # {{ appName }}
2 |
3 | > A GitHub App built with [Probot](https://github.com/probot/probot) that {{ description }}
4 |
5 | ## Setup
6 |
7 | ```sh
8 | # Install dependencies
9 | npm install
10 |
11 | {{#if toBuild}}
12 | # Compile
13 | npm build
14 |
15 | {{/if}}
16 | # Run the bot
17 | npm start
18 | ```
19 |
20 | ## Docker
21 |
22 | ```sh
23 | # 1. Build container
24 | docker build -t {{ appName }} .
25 |
26 | # 2. Start container
27 | docker run -e APP_ID= -e PRIVATE_KEY= {{ appName }}
28 | ```
29 |
30 | ## Contributing
31 |
32 | If you have suggestions for how {{ appName }} could be improved, or want to report a bug, open an issue! We'd love all and any contributions.
33 |
34 | For more, check out the [Contributing Guide](CONTRIBUTING.md).
35 |
36 | ## License
37 |
38 | [ISC](LICENSE) © {{{ year }}} {{{ author }}}
39 |
--------------------------------------------------------------------------------
/templates/__common__/gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | npm-debug.log
3 | *.pem
4 | !mock-cert.pem
5 | .env
6 | coverage
7 | lib
8 |
--------------------------------------------------------------------------------
/templates/__common__/test/fixtures/mock-cert.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEowIBAAKCAQEAli7V49NdZe+XYC1pLaHM0te8kiDmZBJ1u2HJHN8GdbROB6NO
3 | VpC3xK7NxQn6xpvZ9ux20NvcDvGle+DOptZztBH+np6h2jZQ1/kD1yG1eQvVH4th
4 | /9oqHuIjmIfO8lIe4Hyd5Fw5xHkGqVETTGR+0c7kdZIlHmkOregUGtMYZRUi4YG+
5 | q0w+uFemiHpGKXbeCIAvkq7aIkisEzvPWfSyYdA6WJHpxFk7tD7D8VkzABLVRHCq
6 | AuyqPG39BhGZcGLXx5rGK56kDBJkyTR1t3DkHpwX+JKNG5UYNwOG4LcQj1fteeta
7 | TdkYUMjIyWbanlMYyC+dq7B5fe7el99jXQ1gXwIDAQABAoIBADKfiPOpzKLOtzzx
8 | MbHzB0LO+75aHq7+1faayJrVxqyoYWELuB1P3NIMhknzyjdmU3t7S7WtVqkm5Twz
9 | lBUC1q+NHUHEgRQ4GNokExpSP4SU63sdlaQTmv0cBxmkNarS6ZuMBgDy4XoLvaYX
10 | MSUf/uukDLhg0ehFS3BteVFtdJyllhDdTenF1Nb1rAeN4egt8XLsE5NQDr1szFEG
11 | xH5lb+8EDtzgsGpeIddWR64xP0lDIKSZWst/toYKWiwjaY9uZCfAhvYQ1RsO7L/t
12 | sERmpYgh+rAZUh/Lr98EI8BPSPhzFcSHmtqzzejvC5zrZPHcUimz0CGA3YBiLoJX
13 | V1OrxmECgYEAxkd8gpmVP+LEWB3lqpSvJaXcGkbzcDb9m0OPzHUAJDZtiIIf0UmO
14 | nvL68/mzbCHSj+yFjZeG1rsrAVrOzrfDCuXjAv+JkEtEx0DIevU1u60lGnevOeky
15 | r8Be7pmymFB9/gzQAd5ezIlTv/COgoO986a3h1yfhzrrzbqSiivw308CgYEAwecI
16 | aZZwqH3GifR+0+Z1B48cezA5tC8LZt5yObGzUfxKTWy30d7lxe9N59t0KUVt/QL5
17 | qVkd7mqGzsUMyxUN2U2HVnFTWfUFMhkn/OnCnayhILs8UlCTD2Xxoy1KbQH/9FIr
18 | xf0pbMNJLXeGfyRt/8H+BzSZKBw9opJBWE4gqfECgYBp9FdvvryHuBkt8UQCRJPX
19 | rWsRy6pY47nf11mnazpZH5Cmqspv3zvMapF6AIxFk0leyYiQolFWvAv+HFV5F6+t
20 | Si1mM8GCDwbA5zh6pEBDewHhw+UqMBh63HSeUhmi1RiOwrAA36CO8i+D2Pt+eQHv
21 | ir52IiPJcs4BUNrv5Q1BdwKBgBHgVNw3LGe8QMOTMOYkRwHNZdjNl2RPOgPf2jQL
22 | d/bFBayhq0jD/fcDmvEXQFxVtFAxKAc+2g2S8J67d/R5Gm/AQAvuIrsWZcY6n38n
23 | pfOXaLt1x5fnKcevpFlg4Y2vM4O416RHNLx8PJDehh3Oo/2CSwMrDDuwbtZAGZok
24 | icphAoGBAI74Tisfn+aeCZMrO8KxaWS5r2CD1KVzddEMRKlJvSKTY+dOCtJ+XKj1
25 | OsZdcDvDC5GtgcywHsYeOWHldgDWY1S8Z/PUo4eK9qBXYBXp3JEZQ1dqzFdz+Txi
26 | rBn2WsFLsxV9j2/ugm0PqWVBcU2bPUCwvaRu3SOms2teaLwGCkhr
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/templates/basic-js/__description__.txt:
--------------------------------------------------------------------------------
1 | Comment on new issues
2 |
--------------------------------------------------------------------------------
/templates/basic-js/app.yml:
--------------------------------------------------------------------------------
1 | # This is a GitHub App Manifest. These settings will be used by default when
2 | # initially configuring your GitHub App.
3 | #
4 | # NOTE: changing this file will not update your GitHub App settings.
5 | # You must visit github.com/settings/apps/your-app-name to edit them.
6 | #
7 | # Read more about configuring your GitHub App:
8 | # https://probot.github.io/docs/development/#configuring-a-github-app
9 | #
10 | # Read more about GitHub App Manifests:
11 | # https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/
12 |
13 | # The list of events the GitHub App subscribes to.
14 | # Uncomment the event names below to enable them.
15 | default_events:
16 | # - check_run
17 | # - check_suite
18 | # - commit_comment
19 | # - create
20 | # - delete
21 | # - deployment
22 | # - deployment_status
23 | # - fork
24 | # - gollum
25 | # - issue_comment
26 | - issues
27 | # - label
28 | # - milestone
29 | # - member
30 | # - membership
31 | # - org_block
32 | # - organization
33 | # - page_build
34 | # - project
35 | # - project_card
36 | # - project_column
37 | # - public
38 | # - pull_request
39 | # - pull_request_review
40 | # - pull_request_review_comment
41 | # - push
42 | # - release
43 | # - repository
44 | # - repository_import
45 | # - status
46 | # - team
47 | # - team_add
48 | # - watch
49 |
50 | # The set of permissions needed by the GitHub App. The format of the object uses
51 | # the permission name for the key (for example, issues) and the access type for
52 | # the value (for example, write).
53 | # Valid values are `read`, `write`, and `none`
54 | default_permissions:
55 | # Repository creation, deletion, settings, teams, and collaborators.
56 | # https://developer.github.com/v3/apps/permissions/#permission-on-administration
57 | # administration: read
58 |
59 | # Checks on code.
60 | # https://developer.github.com/v3/apps/permissions/#permission-on-checks
61 | # checks: read
62 |
63 | # Repository contents, commits, branches, downloads, releases, and merges.
64 | # https://developer.github.com/v3/apps/permissions/#permission-on-contents
65 | # contents: read
66 |
67 | # Deployments and deployment statuses.
68 | # https://developer.github.com/v3/apps/permissions/#permission-on-deployments
69 | # deployments: read
70 |
71 | # Issues and related comments, assignees, labels, and milestones.
72 | # https://developer.github.com/v3/apps/permissions/#permission-on-issues
73 | issues: write
74 |
75 | # Search repositories, list collaborators, and access repository metadata.
76 | # https://developer.github.com/v3/apps/permissions/#metadata-permissions
77 | metadata: read
78 |
79 | # Retrieve Pages statuses, configuration, and builds, as well as create new builds.
80 | # https://developer.github.com/v3/apps/permissions/#permission-on-pages
81 | # pages: read
82 |
83 | # Pull requests and related comments, assignees, labels, milestones, and merges.
84 | # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
85 | # pull_requests: read
86 |
87 | # Manage the post-receive hooks for a repository.
88 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
89 | # repository_hooks: read
90 |
91 | # Manage repository projects, columns, and cards.
92 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects
93 | # repository_projects: read
94 |
95 | # Retrieve security vulnerability alerts.
96 | # https://developer.github.com/v4/object/repositoryvulnerabilityalert/
97 | # vulnerability_alerts: read
98 |
99 | # Commit statuses.
100 | # https://developer.github.com/v3/apps/permissions/#permission-on-statuses
101 | # statuses: read
102 |
103 | # Organization members and teams.
104 | # https://developer.github.com/v3/apps/permissions/#permission-on-members
105 | # members: read
106 |
107 | # View and manage users blocked by the organization.
108 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking
109 | # organization_user_blocking: read
110 |
111 | # Manage organization projects, columns, and cards.
112 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects
113 | # organization_projects: read
114 |
115 | # Manage team discussions and related comments.
116 | # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions
117 | # team_discussions: read
118 |
119 | # Manage the post-receive hooks for an organization.
120 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks
121 | # organization_hooks: read
122 |
123 | # Get notified of, and update, content references.
124 | # https://developer.github.com/v3/apps/permissions/
125 | # organization_administration: read
126 | # The name of the GitHub App. Defaults to the name specified in package.json
127 | # name: My Probot App
128 |
129 | # The homepage of your GitHub App.
130 | # url: https://example.com/
131 |
132 | # A description of the GitHub App.
133 | # description: A description of my awesome app
134 |
135 | # Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app.
136 | # Default: true
137 | # public: false
138 |
--------------------------------------------------------------------------------
/templates/basic-js/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is the main entrypoint to your Probot app
3 | * @param {import('probot').Probot} app
4 | */
5 | export default (app) => {
6 | // Your code here
7 | app.log.info("Yay, the app was loaded!");
8 |
9 | app.on("issues.opened", async (context) => {
10 | const issueComment = context.issue({
11 | body: "Thanks for opening this issue!",
12 | });
13 | return context.octokit.issues.createComment(issueComment);
14 | });
15 |
16 | // For more information on building apps:
17 | // https://probot.github.io/docs/
18 |
19 | // To get your app running against GitHub, see:
20 | // https://probot.github.io/docs/development/
21 | };
22 |
--------------------------------------------------------------------------------
/templates/basic-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{ appName }}",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "{{{ description }}}",
6 | "author": "{{{ author }}}",
7 | "license": "ISC",
8 | "homepage": "https://github.com/{{ owner }}/{{ repo }}",
9 | "keywords": [
10 | "probot",
11 | "github",
12 | "probot-app"
13 | ],
14 | "scripts": {
15 | "start": "probot run ./index.js",
16 | "test": "node --test"
17 | },
18 | "dependencies": {
19 | "probot": "^13.0.1"
20 | },
21 | "devDependencies": {
22 | "nock": "^14.0.0-beta.5",
23 | "smee-client": "^2.0.0"
24 | },
25 | "engines": {
26 | "node": ">= 18"
27 | },
28 | "type": "module"
29 | }
30 |
--------------------------------------------------------------------------------
/templates/basic-js/test/fixtures/issues.opened.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "opened",
3 | "issue": {
4 | "number": 1,
5 | "user": {
6 | "login": "hiimbex"
7 | }
8 | },
9 | "repository": {
10 | "name": "testing-things",
11 | "owner": {
12 | "login": "hiimbex"
13 | }
14 | },
15 | "installation": {
16 | "id": 2
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/templates/basic-js/test/index.test.js:
--------------------------------------------------------------------------------
1 | import nock from "nock";
2 | // Requiring our app implementation
3 | import myProbotApp from "../index.js";
4 | import { Probot, ProbotOctokit } from "probot";
5 | // Requiring our fixtures
6 | //import payload from "./fixtures/issues.opened.json" with { type: "json" };
7 | const issueCreatedBody = { body: "Thanks for opening this issue!" };
8 | import fs from "fs";
9 | import path from "path";
10 | import { fileURLToPath } from "url";
11 |
12 | import { describe, beforeEach, afterEach, test } from "node:test";
13 | import assert from "node:assert";
14 |
15 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
16 |
17 | const privateKey = fs.readFileSync(
18 | path.join(__dirname, "fixtures/mock-cert.pem"),
19 | "utf-8",
20 | );
21 |
22 | const payload = JSON.parse(
23 | fs.readFileSync(path.join(__dirname, "fixtures/issues.opened.json"), "utf-8"),
24 | );
25 |
26 | describe("My Probot app", () => {
27 | let probot;
28 |
29 | beforeEach(() => {
30 | nock.disableNetConnect();
31 | probot = new Probot({
32 | appId: 123,
33 | privateKey,
34 | // disable request throttling and retries for testing
35 | Octokit: ProbotOctokit.defaults({
36 | retry: { enabled: false },
37 | throttle: { enabled: false },
38 | }),
39 | });
40 | // Load our app into probot
41 | probot.load(myProbotApp);
42 | });
43 |
44 | test("creates a comment when an issue is opened", async () => {
45 | const mock = nock("https://api.github.com")
46 | // Test that we correctly return a test token
47 | .post("/app/installations/2/access_tokens")
48 | .reply(200, {
49 | token: "test",
50 | permissions: {
51 | issues: "write",
52 | },
53 | })
54 |
55 | // Test that a comment is posted
56 | .post("/repos/hiimbex/testing-things/issues/1/comments", (body) => {
57 | assert.deepEqual(body, issueCreatedBody);
58 | return true;
59 | })
60 | .reply(200);
61 |
62 | // Receive a webhook event
63 | await probot.receive({ name: "issues", payload });
64 |
65 | assert.deepStrictEqual(mock.pendingMocks(), []);
66 | });
67 |
68 | afterEach(() => {
69 | nock.cleanAll();
70 | nock.enableNetConnect();
71 | });
72 | });
73 |
74 | // For more information about testing with Jest see:
75 | // https://facebook.github.io/jest/
76 |
77 | // For more information about testing with Nock see:
78 | // https://github.com/nock/nock
79 |
--------------------------------------------------------------------------------
/templates/basic-ts/__description__.txt:
--------------------------------------------------------------------------------
1 | Comment on new issues - written in TypeScript
2 |
--------------------------------------------------------------------------------
/templates/basic-ts/app.yml:
--------------------------------------------------------------------------------
1 | # This is a GitHub App Manifest. These settings will be used by default when
2 | # initially configuring your GitHub App.
3 | #
4 | # NOTE: changing this file will not update your GitHub App settings.
5 | # You must visit github.com/settings/apps/your-app-name to edit them.
6 | #
7 | # Read more about configuring your GitHub App:
8 | # https://probot.github.io/docs/development/#configuring-a-github-app
9 | #
10 | # Read more about GitHub App Manifests:
11 | # https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/
12 |
13 | # The list of events the GitHub App subscribes to.
14 | # Uncomment the event names below to enable them.
15 | default_events:
16 | # - check_run
17 | # - check_suite
18 | # - commit_comment
19 | # - create
20 | # - delete
21 | # - deployment
22 | # - deployment_status
23 | # - fork
24 | # - gollum
25 | # - issue_comment
26 | - issues
27 | # - label
28 | # - milestone
29 | # - member
30 | # - membership
31 | # - org_block
32 | # - organization
33 | # - page_build
34 | # - project
35 | # - project_card
36 | # - project_column
37 | # - public
38 | # - pull_request
39 | # - pull_request_review
40 | # - pull_request_review_comment
41 | # - push
42 | # - release
43 | # - repository
44 | # - repository_import
45 | # - status
46 | # - team
47 | # - team_add
48 | # - watch
49 |
50 | # The set of permissions needed by the GitHub App. The format of the object uses
51 | # the permission name for the key (for example, issues) and the access type for
52 | # the value (for example, write).
53 | # Valid values are `read`, `write`, and `none`
54 | default_permissions:
55 | # Repository creation, deletion, settings, teams, and collaborators.
56 | # https://developer.github.com/v3/apps/permissions/#permission-on-administration
57 | # administration: read
58 |
59 | # Checks on code.
60 | # https://developer.github.com/v3/apps/permissions/#permission-on-checks
61 | # checks: read
62 |
63 | # Repository contents, commits, branches, downloads, releases, and merges.
64 | # https://developer.github.com/v3/apps/permissions/#permission-on-contents
65 | # contents: read
66 |
67 | # Deployments and deployment statuses.
68 | # https://developer.github.com/v3/apps/permissions/#permission-on-deployments
69 | # deployments: read
70 |
71 | # Issues and related comments, assignees, labels, and milestones.
72 | # https://developer.github.com/v3/apps/permissions/#permission-on-issues
73 | issues: write
74 |
75 | # Search repositories, list collaborators, and access repository metadata.
76 | # https://developer.github.com/v3/apps/permissions/#metadata-permissions
77 | metadata: read
78 |
79 | # Retrieve Pages statuses, configuration, and builds, as well as create new builds.
80 | # https://developer.github.com/v3/apps/permissions/#permission-on-pages
81 | # pages: read
82 |
83 | # Pull requests and related comments, assignees, labels, milestones, and merges.
84 | # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
85 | # pull_requests: read
86 |
87 | # Manage the post-receive hooks for a repository.
88 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
89 | # repository_hooks: read
90 |
91 | # Manage repository projects, columns, and cards.
92 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects
93 | # repository_projects: read
94 |
95 | # Retrieve security vulnerability alerts.
96 | # https://developer.github.com/v4/object/repositoryvulnerabilityalert/
97 | # vulnerability_alerts: read
98 |
99 | # Commit statuses.
100 | # https://developer.github.com/v3/apps/permissions/#permission-on-statuses
101 | # statuses: read
102 |
103 | # Organization members and teams.
104 | # https://developer.github.com/v3/apps/permissions/#permission-on-members
105 | # members: read
106 |
107 | # View and manage users blocked by the organization.
108 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking
109 | # organization_user_blocking: read
110 |
111 | # Manage organization projects, columns, and cards.
112 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects
113 | # organization_projects: read
114 |
115 | # Manage team discussions and related comments.
116 | # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions
117 | # team_discussions: read
118 |
119 | # Manage the post-receive hooks for an organization.
120 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks
121 | # organization_hooks: read
122 |
123 | # Get notified of, and update, content references.
124 | # https://developer.github.com/v3/apps/permissions/
125 | # organization_administration: read
126 | # The name of the GitHub App. Defaults to the name specified in package.json
127 | # name: My Probot App
128 |
129 | # The homepage of your GitHub App.
130 | # url: https://example.com/
131 |
132 | # A description of the GitHub App.
133 | # description: A description of my awesome app
134 |
135 | # Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app.
136 | # Default: true
137 | # public: false
138 |
--------------------------------------------------------------------------------
/templates/basic-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{ appName }}",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "{{{ description }}}",
6 | "author": "{{{ author }}}",
7 | "license": "ISC",
8 | "homepage": "https://github.com/{{ owner }}/{{ repo }}",
9 | "keywords": [
10 | "probot",
11 | "github",
12 | "probot-app"
13 | ],
14 | "scripts": {
15 | "build": "tsc",
16 | "start": "probot run ./lib/index.js",
17 | "test": "vitest"
18 | },
19 | "dependencies": {
20 | "probot": "^13.0.1"
21 | },
22 | "devDependencies": {
23 | "@types/node": "^20.0.0",
24 | "nock": "^14.0.0-beta.5",
25 | "smee-client": "^2.0.0",
26 | "vitest": "^2.0.0",
27 | "typescript": "^5.3.3"
28 | },
29 | "engines": {
30 | "node": ">= 18"
31 | },
32 | "type": "module"
33 | }
34 |
--------------------------------------------------------------------------------
/templates/basic-ts/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Probot } from "probot";
2 |
3 | export default (app: Probot) => {
4 | app.on("issues.opened", async (context) => {
5 | const issueComment = context.issue({
6 | body: "Thanks for opening this issue!",
7 | });
8 | await context.octokit.issues.createComment(issueComment);
9 | });
10 | // For more information on building apps:
11 | // https://probot.github.io/docs/
12 |
13 | // To get your app running against GitHub, see:
14 | // https://probot.github.io/docs/development/
15 | };
16 |
--------------------------------------------------------------------------------
/templates/basic-ts/test/fixtures/issues.opened.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "opened",
3 | "issue": {
4 | "number": 1,
5 | "user": {
6 | "login": "hiimbex"
7 | }
8 | },
9 | "repository": {
10 | "name": "testing-things",
11 | "owner": {
12 | "login": "hiimbex"
13 | }
14 | },
15 | "installation": {
16 | "id": 2
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/templates/basic-ts/test/index.test.ts:
--------------------------------------------------------------------------------
1 | // You can import your modules
2 | // import index from '../src/index'
3 |
4 | import nock from "nock";
5 | // Requiring our app implementation
6 | import myProbotApp from "../src/index.js";
7 | import { Probot, ProbotOctokit } from "probot";
8 | // Requiring our fixtures
9 | //import payload from "./fixtures/issues.opened.json" with { "type": "json"};
10 | import fs from "fs";
11 | import path from "path";
12 | import { fileURLToPath } from "url";
13 | import { describe, beforeEach, afterEach, test, expect } from "vitest";
14 |
15 | const issueCreatedBody = { body: "Thanks for opening this issue!" };
16 |
17 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
18 |
19 | const privateKey = fs.readFileSync(
20 | path.join(__dirname, "fixtures/mock-cert.pem"),
21 | "utf-8",
22 | );
23 |
24 | const payload = JSON.parse(
25 | fs.readFileSync(path.join(__dirname, "fixtures/issues.opened.json"), "utf-8"),
26 | );
27 |
28 | describe("My Probot app", () => {
29 | let probot: any;
30 |
31 | beforeEach(() => {
32 | nock.disableNetConnect();
33 | probot = new Probot({
34 | appId: 123,
35 | privateKey,
36 | // disable request throttling and retries for testing
37 | Octokit: ProbotOctokit.defaults({
38 | retry: { enabled: false },
39 | throttle: { enabled: false },
40 | }),
41 | });
42 | // Load our app into probot
43 | probot.load(myProbotApp);
44 | });
45 |
46 | test("creates a comment when an issue is opened", async () => {
47 | const mock = nock("https://api.github.com")
48 | // Test that we correctly return a test token
49 | .post("/app/installations/2/access_tokens")
50 | .reply(200, {
51 | token: "test",
52 | permissions: {
53 | issues: "write",
54 | },
55 | })
56 |
57 | // Test that a comment is posted
58 | .post("/repos/hiimbex/testing-things/issues/1/comments", (body: any) => {
59 | expect(body).toMatchObject(issueCreatedBody);
60 | return true;
61 | })
62 | .reply(200);
63 |
64 | // Receive a webhook event
65 | await probot.receive({ name: "issues", payload });
66 |
67 | expect(mock.pendingMocks()).toStrictEqual([]);
68 | });
69 |
70 | afterEach(() => {
71 | nock.cleanAll();
72 | nock.enableNetConnect();
73 | });
74 | });
75 |
76 | // For more information about testing with Jest see:
77 | // https://facebook.github.io/jest/
78 |
79 | // For more information about using TypeScript in your tests, Jest recommends:
80 | // https://github.com/kulshekhar/ts-jest
81 |
82 | // For more information about testing with Nock see:
83 | // https://github.com/nock/nock
84 |
--------------------------------------------------------------------------------
/templates/basic-ts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "incremental": true,
4 | "target": "es2022",
5 | "module": "Node16",
6 | "declaration": true,
7 | "sourceMap": true,
8 | "outDir": "./lib",
9 |
10 | /* Strict Type-Checking Options */
11 | "strict": true,
12 |
13 | /* Additional Checks */
14 | "noUnusedLocals": true,
15 | "noUnusedParameters": true,
16 | "noImplicitReturns": true,
17 | "noFallthroughCasesInSwitch": true,
18 |
19 | "moduleResolution": "Node16",
20 | "esModuleInterop": true,
21 | "forceConsistentCasingInFileNames": true
22 | },
23 | "include": ["src/"],
24 | "compileOnSave": false
25 | }
26 |
--------------------------------------------------------------------------------
/templates/basic-ts/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vitest/config";
2 |
3 | export default defineConfig({
4 | test: {
5 | include: ["test/**/*.test.ts"],
6 | coverage: {
7 | provider: "v8",
8 | },
9 | },
10 | });
11 |
--------------------------------------------------------------------------------
/templates/checks-js/__description__.txt:
--------------------------------------------------------------------------------
1 | Handle check_suite request and rerequested actions
2 |
--------------------------------------------------------------------------------
/templates/checks-js/app.yml:
--------------------------------------------------------------------------------
1 | # This is a GitHub App Manifest. These settings will be used by default when
2 | # initially configuring your GitHub App.
3 | #
4 | # NOTE: changing this file will not update your GitHub App settings.
5 | # You must visit github.com/settings/apps/your-app-name to edit them.
6 | #
7 | # Read more about configuring your GitHub App:
8 | # https://probot.github.io/docs/development/#configuring-a-github-app
9 | #
10 | # Read more about GitHub App Manifests:
11 | # https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/
12 |
13 | # The list of events the GitHub App subscribes to.
14 | # Uncomment the event names below to enable them.
15 | default_events:
16 | - check_run
17 | - check_suite
18 | # - commit_comment
19 | # - create
20 | # - delete
21 | # - deployment
22 | # - deployment_status
23 | # - fork
24 | # - gollum
25 | # - issue_comment
26 | # - issues
27 | # - label
28 | # - milestone
29 | # - member
30 | # - membership
31 | # - org_block
32 | # - organization
33 | # - page_build
34 | # - project
35 | # - project_card
36 | # - project_column
37 | # - public
38 | # - pull_request
39 | # - pull_request_review
40 | # - pull_request_review_comment
41 | # - push
42 | # - release
43 | # - repository
44 | # - repository_import
45 | # - status
46 | # - team
47 | # - team_add
48 | # - watch
49 |
50 | # The set of permissions needed by the GitHub App. The format of the object uses
51 | # the permission name for the key (for example, issues) and the access type for
52 | # the value (for example, write).
53 | # Valid values are `read`, `write`, and `none`
54 | default_permissions:
55 | # Repository creation, deletion, settings, teams, and collaborators.
56 | # https://developer.github.com/v3/apps/permissions/#permission-on-administration
57 | # administration: read
58 |
59 | # Checks on code.
60 | # https://developer.github.com/v3/apps/permissions/#permission-on-checks
61 | checks: write
62 |
63 | # Repository contents, commits, branches, downloads, releases, and merges.
64 | # https://developer.github.com/v3/apps/permissions/#permission-on-contents
65 | # contents: read
66 |
67 | # Deployments and deployment statuses.
68 | # https://developer.github.com/v3/apps/permissions/#permission-on-deployments
69 | # deployments: read
70 |
71 | # Issues and related comments, assignees, labels, and milestones.
72 | # https://developer.github.com/v3/apps/permissions/#permission-on-issues
73 | # issues: read
74 |
75 | # Search repositories, list collaborators, and access repository metadata.
76 | # https://developer.github.com/v3/apps/permissions/#metadata-permissions
77 | metadata: read
78 |
79 | # Retrieve Pages statuses, configuration, and builds, as well as create new builds.
80 | # https://developer.github.com/v3/apps/permissions/#permission-on-pages
81 | # pages: read
82 |
83 | # Pull requests and related comments, assignees, labels, milestones, and merges.
84 | # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
85 | # pull_requests: read
86 |
87 | # Manage the post-receive hooks for a repository.
88 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
89 | # repository_hooks: read
90 |
91 | # Manage repository projects, columns, and cards.
92 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects
93 | # repository_projects: read
94 |
95 | # Retrieve security vulnerability alerts.
96 | # https://developer.github.com/v4/object/repositoryvulnerabilityalert/
97 | # vulnerability_alerts: read
98 |
99 | # Commit statuses.
100 | # https://developer.github.com/v3/apps/permissions/#permission-on-statuses
101 | # statuses: read
102 |
103 | # Organization members and teams.
104 | # https://developer.github.com/v3/apps/permissions/#permission-on-members
105 | # members: read
106 |
107 | # View and manage users blocked by the organization.
108 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking
109 | # organization_user_blocking: read
110 |
111 | # Manage organization projects, columns, and cards.
112 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects
113 | # organization_projects: read
114 |
115 | # Manage team discussions and related comments.
116 | # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions
117 | # team_discussions: read
118 |
119 | # Manage the post-receive hooks for an organization.
120 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks
121 | # organization_hooks: read
122 |
123 | # Get notified of, and update, content references.
124 | # https://developer.github.com/v3/apps/permissions/
125 | # organization_administration: read
126 | # The name of the GitHub App. Defaults to the name specified in package.json
127 | # name: My Probot App
128 |
129 | # The homepage of your GitHub App.
130 | # url: https://example.com/
131 |
132 | # A description of the GitHub App.
133 | # description: A description of my awesome app
134 |
135 | # Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app.
136 | # Default: true
137 | # public: false
138 |
--------------------------------------------------------------------------------
/templates/checks-js/index.js:
--------------------------------------------------------------------------------
1 | // Checks API example
2 | // See: https://developer.github.com/v3/checks/ to learn more
3 |
4 | /**
5 | * This is the main entrypoint to your Probot app
6 | * @param {import('probot').Probot} app
7 | */
8 | export default (app) => {
9 | app.on(["check_suite.requested", "check_run.rerequested"], check);
10 |
11 | async function check(context) {
12 | const startTime = new Date();
13 |
14 | // Do stuff
15 | const { head_branch: headBranch, head_sha: headSha } =
16 | context.payload.check_suite;
17 | // Probot API note: context.repo() => {username: 'hiimbex', repo: 'testing-things'}
18 | return context.octokit.checks.create(
19 | context.repo({
20 | name: "My app!",
21 | head_branch: headBranch,
22 | head_sha: headSha,
23 | status: "completed",
24 | started_at: startTime,
25 | conclusion: "success",
26 | completed_at: new Date(),
27 | output: {
28 | title: "Probot check!",
29 | summary: "The check has passed!",
30 | },
31 | }),
32 | );
33 | }
34 |
35 | // For more information on building apps:
36 | // https://probot.github.io/docs/
37 |
38 | // To get your app running against GitHub, see:
39 | // https://probot.github.io/docs/development/
40 | };
41 |
--------------------------------------------------------------------------------
/templates/checks-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{ appName }}",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "{{{ description }}}",
6 | "author": "{{{ author }}}",
7 | "license": "ISC",
8 | "homepage": "https://github.com/{{ owner }}/{{ repo }}",
9 | "keywords": [
10 | "probot",
11 | "github",
12 | "probot-app"
13 | ],
14 | "scripts": {
15 | "start": "probot run ./index.js",
16 | "test": "node --test"
17 | },
18 | "dependencies": {
19 | "probot": "^13.0.1"
20 | },
21 | "devDependencies": {
22 | "nock": "^14.0.0-beta.5",
23 | "smee-client": "^2.0.0"
24 | },
25 | "engines": {
26 | "node": ">= 18"
27 | },
28 | "type": "module"
29 | }
30 |
--------------------------------------------------------------------------------
/templates/checks-js/test/fixtures/check_run.created.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "My app!",
3 | "head_branch": "hiimbex-patch-46",
4 | "head_sha": "50e5628cda538bcbb6f3fec3edebe4bb5afb3891",
5 | "status": "completed",
6 | "started_at": "2018-10-05T17:35:21.594Z",
7 | "conclusion": "success",
8 | "completed_at": "2018-10-05T17:35:53.683Z",
9 | "output": {
10 | "title": "Probot check!",
11 | "summary": "The check has passed!"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/templates/checks-js/test/fixtures/check_suite.requested.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "requested",
3 | "check_suite": {
4 | "id": 17597619,
5 | "node_id": "MDEwOkNoZWNrU3VpdGUxNzU5NzYxOQ==",
6 | "head_branch": "hiimbex-patch-46",
7 | "head_sha": "50e5628cda538bcbb6f3fec3edebe4bb5afb3891",
8 | "status": "queued",
9 | "conclusion": null,
10 | "url": "https://api.github.com/repos/hiimbex/testing-things/check-suites/17597619",
11 | "before": "f5c621190066c1b2333b3e2ff01742b6696be443",
12 | "after": "50e5628cda538bcbb6f3fec3edebe4bb5afb3891",
13 | "pull_requests": [
14 | {
15 | "url": "https://api.github.com/repos/hiimbex/testing-things/pulls/121",
16 | "id": 220762830,
17 | "number": 121,
18 | "head": {
19 | "ref": "hiimbex-patch-46",
20 | "sha": "50e5628cda538bcbb6f3fec3edebe4bb5afb3891",
21 | "repo": {
22 | "id": 95162387,
23 | "url": "https://api.github.com/repos/hiimbex/testing-things",
24 | "name": "testing-things"
25 | }
26 | },
27 | "base": {
28 | "ref": "master",
29 | "sha": "43fd9749bea5ea6de51bdf01b3b1e7264cbe83bc",
30 | "repo": {
31 | "id": 95162387,
32 | "url": "https://api.github.com/repos/hiimbex/testing-things",
33 | "name": "testing-things"
34 | }
35 | }
36 | }
37 | ],
38 | "app": {
39 | "id": 18586,
40 | "node_id": "MDM6QXBwMTg1ODY=",
41 | "owner": {
42 | "login": "hiimbex",
43 | "id": 13410355,
44 | "node_id": "MDQ6VXNlcjEzNDEwMzU1",
45 | "avatar_url": "https://avatars1.githubusercontent.com/u/13410355?v=4",
46 | "gravatar_id": "",
47 | "url": "https://api.github.com/users/hiimbex",
48 | "html_url": "https://github.com/hiimbex",
49 | "followers_url": "https://api.github.com/users/hiimbex/followers",
50 | "following_url": "https://api.github.com/users/hiimbex/following{/other_user}",
51 | "gists_url": "https://api.github.com/users/hiimbex/gists{/gist_id}",
52 | "starred_url": "https://api.github.com/users/hiimbex/starred{/owner}{/repo}",
53 | "subscriptions_url": "https://api.github.com/users/hiimbex/subscriptions",
54 | "organizations_url": "https://api.github.com/users/hiimbex/orgs",
55 | "repos_url": "https://api.github.com/users/hiimbex/repos",
56 | "events_url": "https://api.github.com/users/hiimbex/events{/privacy}",
57 | "received_events_url": "https://api.github.com/users/hiimbex/received_events",
58 | "type": "User",
59 | "site_admin": false
60 | },
61 | "name": "checksoo",
62 | "description": "A Probot app",
63 | "external_url": "https://github.com/hiimbex/checksoo",
64 | "html_url": "https://github.com/apps/checksoo",
65 | "created_at": "2018-10-05T16:46:52Z",
66 | "updated_at": "2018-10-05T16:46:52Z"
67 | },
68 | "created_at": "2018-10-05T16:53:21Z",
69 | "updated_at": "2018-10-05T16:53:21Z",
70 | "latest_check_runs_count": 0,
71 | "check_runs_url": "https://api.github.com/repos/hiimbex/testing-things/check-suites/17597619/check-runs",
72 | "head_commit": {
73 | "id": "50e5628cda538bcbb6f3fec3edebe4bb5afb3891",
74 | "tree_id": "1d785b00b8f8163d656ffedddcb773a7077592f4",
75 | "message": "Update README.md",
76 | "timestamp": "2018-10-05T16:53:19Z",
77 | "author": {
78 | "name": "Bex Warner",
79 | "email": "bexmwarner@gmail.com"
80 | },
81 | "committer": {
82 | "name": "GitHub",
83 | "email": "noreply@github.com"
84 | }
85 | }
86 | },
87 | "repository": {
88 | "id": 95162387,
89 | "node_id": "MDEwOlJlcG9zaXRvcnk5NTE2MjM4Nw==",
90 | "name": "testing-things",
91 | "full_name": "hiimbex/testing-things",
92 | "private": false,
93 | "owner": {
94 | "login": "hiimbex",
95 | "id": 13410355,
96 | "node_id": "MDQ6VXNlcjEzNDEwMzU1",
97 | "avatar_url": "https://avatars1.githubusercontent.com/u/13410355?v=4",
98 | "gravatar_id": "",
99 | "url": "https://api.github.com/users/hiimbex",
100 | "html_url": "https://github.com/hiimbex",
101 | "followers_url": "https://api.github.com/users/hiimbex/followers",
102 | "following_url": "https://api.github.com/users/hiimbex/following{/other_user}",
103 | "gists_url": "https://api.github.com/users/hiimbex/gists{/gist_id}",
104 | "starred_url": "https://api.github.com/users/hiimbex/starred{/owner}{/repo}",
105 | "subscriptions_url": "https://api.github.com/users/hiimbex/subscriptions",
106 | "organizations_url": "https://api.github.com/users/hiimbex/orgs",
107 | "repos_url": "https://api.github.com/users/hiimbex/repos",
108 | "events_url": "https://api.github.com/users/hiimbex/events{/privacy}",
109 | "received_events_url": "https://api.github.com/users/hiimbex/received_events",
110 | "type": "User",
111 | "site_admin": false
112 | },
113 | "html_url": "https://github.com/hiimbex/testing-things",
114 | "description": "this repo is radical dude ugh",
115 | "fork": false,
116 | "url": "https://api.github.com/repos/hiimbex/testing-things",
117 | "forks_url": "https://api.github.com/repos/hiimbex/testing-things/forks",
118 | "keys_url": "https://api.github.com/repos/hiimbex/testing-things/keys{/key_id}",
119 | "collaborators_url": "https://api.github.com/repos/hiimbex/testing-things/collaborators{/collaborator}",
120 | "teams_url": "https://api.github.com/repos/hiimbex/testing-things/teams",
121 | "hooks_url": "https://api.github.com/repos/hiimbex/testing-things/hooks",
122 | "issue_events_url": "https://api.github.com/repos/hiimbex/testing-things/issues/events{/number}",
123 | "events_url": "https://api.github.com/repos/hiimbex/testing-things/events",
124 | "assignees_url": "https://api.github.com/repos/hiimbex/testing-things/assignees{/user}",
125 | "branches_url": "https://api.github.com/repos/hiimbex/testing-things/branches{/branch}",
126 | "tags_url": "https://api.github.com/repos/hiimbex/testing-things/tags",
127 | "blobs_url": "https://api.github.com/repos/hiimbex/testing-things/git/blobs{/sha}",
128 | "git_tags_url": "https://api.github.com/repos/hiimbex/testing-things/git/tags{/sha}",
129 | "git_refs_url": "https://api.github.com/repos/hiimbex/testing-things/git/refs{/sha}",
130 | "trees_url": "https://api.github.com/repos/hiimbex/testing-things/git/trees{/sha}",
131 | "statuses_url": "https://api.github.com/repos/hiimbex/testing-things/statuses/{sha}",
132 | "languages_url": "https://api.github.com/repos/hiimbex/testing-things/languages",
133 | "stargazers_url": "https://api.github.com/repos/hiimbex/testing-things/stargazers",
134 | "contributors_url": "https://api.github.com/repos/hiimbex/testing-things/contributors",
135 | "subscribers_url": "https://api.github.com/repos/hiimbex/testing-things/subscribers",
136 | "subscription_url": "https://api.github.com/repos/hiimbex/testing-things/subscription",
137 | "commits_url": "https://api.github.com/repos/hiimbex/testing-things/commits{/sha}",
138 | "git_commits_url": "https://api.github.com/repos/hiimbex/testing-things/git/commits{/sha}",
139 | "comments_url": "https://api.github.com/repos/hiimbex/testing-things/comments{/number}",
140 | "issue_comment_url": "https://api.github.com/repos/hiimbex/testing-things/issues/comments{/number}",
141 | "contents_url": "https://api.github.com/repos/hiimbex/testing-things/contents/{+path}",
142 | "compare_url": "https://api.github.com/repos/hiimbex/testing-things/compare/{base}...{head}",
143 | "merges_url": "https://api.github.com/repos/hiimbex/testing-things/merges",
144 | "archive_url": "https://api.github.com/repos/hiimbex/testing-things/{archive_format}{/ref}",
145 | "downloads_url": "https://api.github.com/repos/hiimbex/testing-things/downloads",
146 | "issues_url": "https://api.github.com/repos/hiimbex/testing-things/issues{/number}",
147 | "pulls_url": "https://api.github.com/repos/hiimbex/testing-things/pulls{/number}",
148 | "milestones_url": "https://api.github.com/repos/hiimbex/testing-things/milestones{/number}",
149 | "notifications_url": "https://api.github.com/repos/hiimbex/testing-things/notifications{?since,all,participating}",
150 | "labels_url": "https://api.github.com/repos/hiimbex/testing-things/labels{/name}",
151 | "releases_url": "https://api.github.com/repos/hiimbex/testing-things/releases{/id}",
152 | "deployments_url": "https://api.github.com/repos/hiimbex/testing-things/deployments",
153 | "created_at": "2017-06-22T22:38:49Z",
154 | "updated_at": "2018-09-15T14:44:14Z",
155 | "pushed_at": "2018-10-05T16:53:21Z",
156 | "git_url": "git://github.com/hiimbex/testing-things.git",
157 | "ssh_url": "git@github.com:hiimbex/testing-things.git",
158 | "clone_url": "https://github.com/hiimbex/testing-things.git",
159 | "svn_url": "https://github.com/hiimbex/testing-things",
160 | "homepage": null,
161 | "size": 99,
162 | "stargazers_count": 0,
163 | "watchers_count": 0,
164 | "language": "JavaScript",
165 | "has_issues": true,
166 | "has_projects": true,
167 | "has_downloads": true,
168 | "has_wiki": true,
169 | "has_pages": false,
170 | "forks_count": 2,
171 | "mirror_url": null,
172 | "archived": false,
173 | "open_issues_count": 75,
174 | "license": null,
175 | "forks": 2,
176 | "open_issues": 75,
177 | "watchers": 0,
178 | "default_branch": "master"
179 | },
180 | "sender": {
181 | "login": "hiimbex",
182 | "id": 13410355,
183 | "node_id": "MDQ6VXNlcjEzNDEwMzU1",
184 | "avatar_url": "https://avatars1.githubusercontent.com/u/13410355?v=4",
185 | "gravatar_id": "",
186 | "url": "https://api.github.com/users/hiimbex",
187 | "html_url": "https://github.com/hiimbex",
188 | "followers_url": "https://api.github.com/users/hiimbex/followers",
189 | "following_url": "https://api.github.com/users/hiimbex/following{/other_user}",
190 | "gists_url": "https://api.github.com/users/hiimbex/gists{/gist_id}",
191 | "starred_url": "https://api.github.com/users/hiimbex/starred{/owner}{/repo}",
192 | "subscriptions_url": "https://api.github.com/users/hiimbex/subscriptions",
193 | "organizations_url": "https://api.github.com/users/hiimbex/orgs",
194 | "repos_url": "https://api.github.com/users/hiimbex/repos",
195 | "events_url": "https://api.github.com/users/hiimbex/events{/privacy}",
196 | "received_events_url": "https://api.github.com/users/hiimbex/received_events",
197 | "type": "User",
198 | "site_admin": false
199 | },
200 | "installation": {
201 | "id": 2,
202 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uMzY3NDI4"
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/templates/checks-js/test/index.test.js:
--------------------------------------------------------------------------------
1 | import nock from "nock";
2 | // Requiring our app implementation
3 | import myProbotApp from "../index.js";
4 | import { Probot, ProbotOctokit } from "probot";
5 | // Requiring our fixtures
6 | //import checkSuitePayload from "./fixtures/check_suite.requested" with { type: "json" };
7 | //import checkRunSuccess from "./fixtures/check_run.created" with { type: "json" };
8 | import fs from "fs";
9 | import path from "path";
10 | import { fileURLToPath } from "url";
11 |
12 | import { describe, beforeEach, afterEach, test } from "node:test";
13 | import assert from "node:assert";
14 |
15 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
16 |
17 | const privateKey = fs.readFileSync(
18 | path.join(__dirname, "fixtures/mock-cert.pem"),
19 | "utf-8",
20 | );
21 |
22 | const checkSuitePayload = JSON.parse(
23 | fs.readFileSync(
24 | path.join(__dirname, "fixtures/check_suite.requested.json"),
25 | "utf-8",
26 | ),
27 | );
28 |
29 | const checkRunSuccess = JSON.parse(
30 | fs.readFileSync(
31 | path.join(__dirname, "fixtures/check_run.created.json"),
32 | "utf-8",
33 | ),
34 | );
35 |
36 | describe("My Probot app", () => {
37 | let probot;
38 |
39 | beforeEach(() => {
40 | nock.disableNetConnect();
41 | probot = new Probot({
42 | appId: 123,
43 | privateKey,
44 | // disable request throttling and retries for testing
45 | Octokit: ProbotOctokit.defaults({
46 | retry: { enabled: false },
47 | throttle: { enabled: false },
48 | }),
49 | });
50 | // Load our app into probot
51 | probot.load(myProbotApp);
52 | });
53 |
54 | test("creates a passing check", async () => {
55 | const mock = nock("https://api.github.com")
56 | .post("/app/installations/2/access_tokens")
57 | .reply(200, {
58 | token: "test",
59 | permissions: {
60 | checks: "write",
61 | },
62 | })
63 |
64 | .post("/repos/hiimbex/testing-things/check-runs", (body) => {
65 | body.started_at = "2018-10-05T17:35:21.594Z";
66 | body.completed_at = "2018-10-05T17:35:53.683Z";
67 | assert.deepStrictEqual(body, checkRunSuccess);
68 | return true;
69 | })
70 | .reply(200);
71 |
72 | // Receive a webhook event
73 | await probot.receive({ name: "check_suite", payload: checkSuitePayload });
74 |
75 | assert.deepStrictEqual(mock.pendingMocks(), []);
76 | });
77 |
78 | afterEach(() => {
79 | nock.cleanAll();
80 | nock.enableNetConnect();
81 | });
82 | });
83 |
84 | // For more information about testing with Jest see:
85 | // https://facebook.github.io/jest/
86 |
87 | // For more information about testing with Nock see:
88 | // https://github.com/nock/nock
89 |
--------------------------------------------------------------------------------
/templates/deploy-js/__description__.txt:
--------------------------------------------------------------------------------
1 | Creates a deployment on a pull request event
2 |
--------------------------------------------------------------------------------
/templates/deploy-js/app.yml:
--------------------------------------------------------------------------------
1 | # This is a GitHub App Manifest. These settings will be used by default when
2 | # initially configuring your GitHub App.
3 | #
4 | # NOTE: changing this file will not update your GitHub App settings.
5 | # You must visit github.com/settings/apps/your-app-name to edit them.
6 | #
7 | # Read more about configuring your GitHub App:
8 | # https://probot.github.io/docs/development/#configuring-a-github-app
9 | #
10 | # Read more about GitHub App Manifests:
11 | # https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/
12 |
13 | # The list of events the GitHub App subscribes to.
14 | # Uncomment the event names below to enable them.
15 | default_events:
16 | # - check_run
17 | # - check_suite
18 | # - commit_comment
19 | # - create
20 | # - delete
21 | - deployment
22 | # - deployment_status
23 | # - fork
24 | # - gollum
25 | # - issue_comment
26 | # - issues
27 | # - label
28 | # - milestone
29 | # - member
30 | # - membership
31 | # - org_block
32 | # - organization
33 | # - page_build
34 | # - project
35 | # - project_card
36 | # - project_column
37 | # - public
38 | - pull_request
39 | # - pull_request_review
40 | # - pull_request_review_comment
41 | # - push
42 | # - release
43 | # - repository
44 | # - repository_import
45 | # - status
46 | # - team
47 | # - team_add
48 | # - watch
49 |
50 | # The set of permissions needed by the GitHub App. The format of the object uses
51 | # the permission name for the key (for example, issues) and the access type for
52 | # the value (for example, write).
53 | # Valid values are `read`, `write`, and `none`
54 | default_permissions:
55 | # Repository creation, deletion, settings, teams, and collaborators.
56 | # https://developer.github.com/v3/apps/permissions/#permission-on-administration
57 | # administration: read
58 |
59 | # Checks on code.
60 | # https://developer.github.com/v3/apps/permissions/#permission-on-checks
61 | # checks: read
62 |
63 | # Repository contents, commits, branches, downloads, releases, and merges.
64 | # https://developer.github.com/v3/apps/permissions/#permission-on-contents
65 | # contents: read
66 |
67 | # Deployments and deployment statuses.
68 | # https://developer.github.com/v3/apps/permissions/#permission-on-deployments
69 | deployments: write
70 |
71 | # Issues and related comments, assignees, labels, and milestones.
72 | # https://developer.github.com/v3/apps/permissions/#permission-on-issues
73 | # issues: write
74 |
75 | # Search repositories, list collaborators, and access repository '.
76 | # https://developer.github.com/v3/apps/permissions/#metadata-permissions
77 | metadata: read
78 |
79 | # Retrieve Pages statuses, configuration, and builds, as well as create new builds.
80 | # https://developer.github.com/v3/apps/permissions/#permission-on-pages
81 | # pages: read
82 |
83 | # Pull requests and related comments, assignees, labels, milestones, and merges.
84 | # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
85 | pull_requests: read
86 |
87 | # Manage the post-receive hooks for a repository.
88 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
89 | # repository_hooks: read
90 |
91 | # Manage repository projects, columns, and cards.
92 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects
93 | # repository_projects: read
94 |
95 | # Retrieve security vulnerability alerts.
96 | # https://developer.github.com/v4/object/repositoryvulnerabilityalert/
97 | # vulnerability_alerts: read
98 |
99 | # Commit statuses.
100 | # https://developer.github.com/v3/apps/permissions/#permission-on-statuses
101 | # statuses: read
102 |
103 | # Organization members and teams.
104 | # https://developer.github.com/v3/apps/permissions/#permission-on-members
105 | # members: read
106 |
107 | # View and manage users blocked by the organization.
108 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking
109 | # organization_user_blocking: read
110 |
111 | # Manage organization projects, columns, and cards.
112 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects
113 | # organization_projects: read
114 |
115 | # Manage team discussions and related comments.
116 | # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions
117 | # team_discussions: read
118 |
119 | # Manage the post-receive hooks for an organization.
120 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks
121 | # organization_hooks: read
122 |
123 | # Get notified of, and update, content references.
124 | # https://developer.github.com/v3/apps/permissions/
125 | # organization_administration: read
126 | # The name of the GitHub App. Defaults to the name specified in package.json
127 | # name: My Probot App
128 |
129 | # The homepage of your GitHub App.
130 | # url: https://example.com/
131 |
132 | # A description of the GitHub App.
133 | # description: A description of my awesome app
134 |
135 | # Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app.
136 | # Default: true
137 | # public: false
138 |
--------------------------------------------------------------------------------
/templates/deploy-js/index.js:
--------------------------------------------------------------------------------
1 | // Deployments API example
2 | // See: https://developer.github.com/v3/repos/deployments/ to learn more
3 |
4 | /**
5 | * This is the main entrypoint to your Probot app
6 | * @param {import('probot').Probot} app
7 | */
8 | export default (app) => {
9 | // Your code here
10 | app.log.info("Yay, the app was loaded!");
11 | app.on(
12 | ["pull_request.opened", "pull_request.synchronize"],
13 | async (context) => {
14 | // Creates a deployment on a pull request event
15 | // Then sets the deployment status to success
16 | // NOTE: this example doesn't actually integrate with a cloud
17 | // provider to deploy your app, it just demos the basic API usage.
18 | app.log.info(context.payload);
19 |
20 | // Probot API note: context.repo() => { username: 'hiimbex', repo: 'testing-things' }
21 | const res = await context.octokit.repos.createDeployment(
22 | context.repo({
23 | ref: context.payload.pull_request.head.ref, // The ref to deploy. This can be a branch, tag, or SHA.
24 | task: "deploy", // Specifies a task to execute (e.g., deploy or deploy:migrations).
25 | auto_merge: true, // Attempts to automatically merge the default branch into the requested ref, if it is behind the default branch.
26 | required_contexts: [], // The status contexts to verify against commit status checks. If this parameter is omitted, then all unique contexts will be verified before a deployment is created. To bypass checking entirely pass an empty array. Defaults to all unique contexts.
27 | payload: {
28 | schema: "rocks!",
29 | }, // JSON payload with extra information about the deployment. Default: ""
30 | environment: "production", // Name for the target deployment environment (e.g., production, staging, qa)
31 | description: "My Probot App's first deploy!", // Short description of the deployment
32 | transient_environment: false, // Specifies if the given environment is specific to the deployment and will no longer exist at some point in the future.
33 | production_environment: true, // Specifies if the given environment is one that end-users directly interact with.
34 | }),
35 | );
36 |
37 | const deploymentId = res.data.id;
38 | await context.octokit.repos.createDeploymentStatus(
39 | context.repo({
40 | deployment_id: deploymentId,
41 | state: "success", // The state of the status. Can be one of error, failure, inactive, pending, or success
42 | log_url: "https://example.com", // The log URL to associate with this status. This URL should contain output to keep the user updated while the task is running or serve as historical information for what happened in the deployment.
43 | description: "My Probot App set a deployment status!", // A short description of the status.
44 | environment_url: "https://example.com", // Sets the URL for accessing your environment.
45 | auto_inactive: true, // Adds a new inactive status to all prior non-transient, non-production environment deployments with the same repository and environment name as the created status's deployment. An inactive status is only added to deployments that had a success state.
46 | }),
47 | );
48 | },
49 | );
50 |
51 | // For more information on building apps:
52 | // https://probot.github.io/docs/
53 |
54 | // To get your app running against GitHub, see:
55 | // https://probot.github.io/docs/development/
56 | };
57 |
--------------------------------------------------------------------------------
/templates/deploy-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{ appName }}",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "{{{ description }}}",
6 | "author": "{{{ author }}}",
7 | "license": "ISC",
8 | "homepage": "https://github.com/{{ owner }}/{{ repo }}",
9 | "keywords": [
10 | "probot",
11 | "github",
12 | "probot-app"
13 | ],
14 | "scripts": {
15 | "start": "probot run ./index.js",
16 | "test": "node --test"
17 | },
18 | "dependencies": {
19 | "probot": "^13.0.1"
20 | },
21 | "devDependencies": {
22 | "nock": "^14.0.0-beta.5",
23 | "smee-client": "^2.0.0"
24 | },
25 | "engines": {
26 | "node": ">= 18"
27 | },
28 | "type": "module"
29 | }
30 |
--------------------------------------------------------------------------------
/templates/deploy-js/test/fixtures/pull_request.opened.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "opened",
3 | "pull_request": {
4 | "head": {
5 | "ref": "hiimbex-patch-1"
6 | }
7 | },
8 | "repository": {
9 | "name": "testing-things",
10 | "owner": {
11 | "login": "hiimbex"
12 | }
13 | },
14 | "installation": {
15 | "id": 2
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/templates/deploy-js/test/index.test.js:
--------------------------------------------------------------------------------
1 | import nock from "nock";
2 | // Requiring our app implementation
3 | import myProbotApp from "../index.js";
4 | import { Probot, ProbotOctokit } from "probot";
5 | // Requiring our fixtures
6 | //import payload from "./fixtures/pull_request.opened" with { type: "json" };
7 | import fs from "fs";
8 | import path from "path";
9 | import { fileURLToPath } from "url";
10 | import { describe, beforeEach, afterEach, test } from "node:test";
11 | import assert from "node:assert";
12 |
13 | const __dirname = path.dirname(fileURLToPath(import.meta.url));
14 |
15 | const payload = JSON.parse(
16 | fs.readFileSync(
17 | path.join(__dirname, "fixtures/pull_request.opened.json"),
18 | "utf-8",
19 | ),
20 | );
21 |
22 | const deployment = {
23 | ref: "hiimbex-patch-1",
24 | task: "deploy",
25 | auto_merge: true,
26 | required_contexts: [],
27 | payload: {
28 | schema: "rocks!",
29 | },
30 | environment: "production",
31 | description: "My Probot App's first deploy!",
32 | transient_environment: false,
33 | production_environment: true,
34 | };
35 |
36 | const deploymentStatus = {
37 | state: "success",
38 | log_url: "https://example.com",
39 | description: "My Probot App set a deployment status!",
40 | environment_url: "https://example.com",
41 | auto_inactive: true,
42 | };
43 |
44 | const privateKey = fs.readFileSync(
45 | path.join(__dirname, "fixtures/mock-cert.pem"),
46 | "utf-8",
47 | );
48 |
49 | describe("My Probot app", () => {
50 | let probot;
51 |
52 | beforeEach(() => {
53 | nock.disableNetConnect();
54 | probot = new Probot({
55 | appId: 123,
56 | privateKey,
57 | // disable request throttling and retries for testing
58 | Octokit: ProbotOctokit.defaults({
59 | retry: { enabled: false },
60 | throttle: { enabled: false },
61 | }),
62 | });
63 | // Load our app into probot
64 | probot.load(myProbotApp);
65 | });
66 |
67 | test("creates a deployment and a deployment status", async () => {
68 | const mock = nock("https://api.github.com")
69 | // Test that we correctly return a test token
70 | .post("/app/installations/2/access_tokens")
71 | .reply(200, {
72 | token: "test",
73 | permissions: {
74 | deployments: "write",
75 | pull_requests: "read",
76 | },
77 | })
78 |
79 | // Test that a deployment is created
80 | .post("/repos/hiimbex/testing-things/deployments", (body) => {
81 | assert.deepStrictEqual(body, deployment);
82 | return true;
83 | })
84 | .reply(200, { id: 123 })
85 |
86 | // Test that a deployment status is created
87 | .post(
88 | "/repos/hiimbex/testing-things/deployments/123/statuses",
89 | (body) => {
90 | assert.deepStrictEqual(body, deploymentStatus);
91 | return true;
92 | },
93 | )
94 | .reply(200);
95 |
96 | // Receive a webhook event
97 | await probot.receive({ name: "pull_request", payload });
98 |
99 | assert.deepStrictEqual(mock.pendingMocks(), []);
100 | });
101 |
102 | afterEach(() => {
103 | nock.cleanAll();
104 | nock.enableNetConnect();
105 | });
106 | });
107 |
108 | // For more information about testing with Jest see:
109 | // https://facebook.github.io/jest/
110 |
111 | // For more information about testing with Nock see:
112 | // https://github.com/nock/nock
113 |
--------------------------------------------------------------------------------
/templates/git-data-js/__description__.txt:
--------------------------------------------------------------------------------
1 | Opens a PR every time someone installs your app for the first time
2 |
--------------------------------------------------------------------------------
/templates/git-data-js/app.yml:
--------------------------------------------------------------------------------
1 | # This is a GitHub App Manifest. These settings will be used by default when
2 | # initially configuring your GitHub App.
3 | #
4 | # NOTE: changing this file will not update your GitHub App settings.
5 | # You must visit github.com/settings/apps/your-app-name to edit them.
6 | #
7 | # Read more about configuring your GitHub App:
8 | # https://probot.github.io/docs/development/#configuring-a-github-app
9 | #
10 | # Read more about GitHub App Manifests:
11 | # https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/
12 |
13 | # The list of events the GitHub App subscribes to.
14 | # Uncomment the event names below to enable them.
15 | default_events:
16 | # - check_run
17 | # - check_suite
18 | # - commit_comment
19 | # - create
20 | # - delete
21 | # - deployment
22 | # - deployment_status
23 | # - fork
24 | # - gollum
25 | # - issue_comment
26 | # - issues
27 | # - label
28 | # - milestone
29 | # - member
30 | # - membership
31 | # - org_block
32 | # - organization
33 | # - page_build
34 | # - project
35 | # - project_card
36 | # - project_column
37 | # - public
38 | # - pull_request
39 | # - pull_request_review
40 | # - pull_request_review_comment
41 | # - push
42 | # - release
43 | # - repository
44 | # - repository_import
45 | # - status
46 | - team
47 | # - team_add
48 | # - watch
49 |
50 | # The set of permissions needed by the GitHub App. The format of the object uses
51 | # the permission name for the key (for example, issues) and the access type for
52 | # the value (for example, write).
53 | # Valid values are `read`, `write`, and `none`
54 | default_permissions:
55 | # Repository creation, deletion, settings, teams, and collaborators.
56 | # https://developer.github.com/v3/apps/permissions/#permission-on-administration
57 | # administration: read
58 |
59 | # Checks on code.
60 | # https://developer.github.com/v3/apps/permissions/#permission-on-checks
61 | # checks: write
62 |
63 | # Repository contents, commits, branches, downloads, releases, and merges.
64 | # https://developer.github.com/v3/apps/permissions/#permission-on-contents
65 | contents: write
66 |
67 | # Deployments and deployment statuses.
68 | # https://developer.github.com/v3/apps/permissions/#permission-on-deployments
69 | # deployments: read
70 |
71 | # Issues and related comments, assignees, labels, and milestones.
72 | # https://developer.github.com/v3/apps/permissions/#permission-on-issues
73 | # issues: read
74 |
75 | # Search repositories, list collaborators, and access repository metadata.
76 | # https://developer.github.com/v3/apps/permissions/#metadata-permissions
77 | metadata: read
78 |
79 | # Retrieve Pages statuses, configuration, and builds, as well as create new builds.
80 | # https://developer.github.com/v3/apps/permissions/#permission-on-pages
81 | # pages: read
82 |
83 | # Pull requests and related comments, assignees, labels, milestones, and merges.
84 | # https://developer.github.com/v3/apps/permissions/#permission-on-pull-requests
85 | pull_requests: write
86 |
87 | # Manage the post-receive hooks for a repository.
88 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-hooks
89 | # repository_hooks: read
90 |
91 | # Manage repository projects, columns, and cards.
92 | # https://developer.github.com/v3/apps/permissions/#permission-on-repository-projects
93 | # repository_projects: read
94 |
95 | # Retrieve security vulnerability alerts.
96 | # https://developer.github.com/v4/object/repositoryvulnerabilityalert/
97 | # vulnerability_alerts: read
98 |
99 | # Commit statuses.
100 | # https://developer.github.com/v3/apps/permissions/#permission-on-statuses
101 | # statuses: read
102 |
103 | # Organization members and teams.
104 | # https://developer.github.com/v3/apps/permissions/#permission-on-members
105 | # members: read
106 |
107 | # View and manage users blocked by the organization.
108 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-user-blocking
109 | # organization_user_blocking: read
110 |
111 | # Manage organization projects, columns, and cards.
112 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-projects
113 | # organization_projects: read
114 |
115 | # Manage team discussions and related comments.
116 | # https://developer.github.com/v3/apps/permissions/#permission-on-team-discussions
117 | # team_discussions: read
118 |
119 | # Manage the post-receive hooks for an organization.
120 | # https://developer.github.com/v3/apps/permissions/#permission-on-organization-hooks
121 | # organization_hooks: read
122 |
123 | # Get notified of, and update, content references.
124 | # https://developer.github.com/v3/apps/permissions/
125 | # organization_administration: read
126 | # The name of the GitHub App. Defaults to the name specified in package.json
127 | # name: My Probot App
128 |
129 | # The homepage of your GitHub App.
130 | # url: https://example.com/
131 |
132 | # A description of the GitHub App.
133 | # description: A description of my awesome app
134 |
135 | # Set to true when your GitHub App is available to the public or false when it is only accessible to the owner of the app.
136 | # Default: true
137 | # public: false
138 |
--------------------------------------------------------------------------------
/templates/git-data-js/index.js:
--------------------------------------------------------------------------------
1 | // Git Data API use case example
2 | // See: https://developer.github.com/v3/git/ to learn more
3 |
4 | /**
5 | * This is the main entrypoint to your Probot app
6 | * @param {import('probot').Probot} app
7 | */
8 | module.exports = (app) => {
9 | // Opens a PR every time someone installs your app for the first time
10 | app.on("installation.created", async (context) => {
11 | // shows all repos you've installed the app on
12 | context.log.info(context.payload.repositories);
13 |
14 | const owner = context.payload.installation.account.login;
15 |
16 | for (const repository of context.payload.repositories) {
17 | const repo = repository.name;
18 |
19 | // Generates a random number to ensure the git reference isn't already taken
20 | // NOTE: this is not recommended and just shows an example so it can work :)
21 |
22 | // test
23 | const branch = `new-branch-${Math.floor(Math.random() * 9999)}`;
24 |
25 | // Get current reference in Git
26 | const reference = await context.octokit.git.getRef({
27 | repo, // the repo
28 | owner, // the owner of the repo
29 | ref: "heads/master",
30 | });
31 | // Create a branch
32 | await context.octokit.git.createRef({
33 | repo,
34 | owner,
35 | ref: `refs/heads/${branch}`,
36 | sha: reference.data.object.sha, // accesses the sha from the heads/master reference we got
37 | });
38 | // create a new file
39 | await context.octokit.repos.createOrUpdateFileContents({
40 | repo,
41 | owner,
42 | path: "path/to/your/file.md", // the path to your config file
43 | message: "adds config file", // a commit message
44 | content: Buffer.from("My new file is awesome!").toString("base64"),
45 | // the content of your file, must be base64 encoded
46 | branch, // the branch name we used when creating a Git reference
47 | });
48 | // create a PR from that branch with the commit of our added file
49 | await context.octokit.pulls.create({
50 | repo,
51 | owner,
52 | title: "Adding my file!", // the title of the PR
53 | head: branch, // the branch our chances are on
54 | base: "master", // the branch to which you want to merge your changes
55 | body: "Adds my new file!", // the body of your PR,
56 | maintainer_can_modify: true, // allows maintainers to edit your app's PR
57 | });
58 | }
59 | });
60 | // For more information on building apps:
61 | // https://probot.github.io/docs/
62 |
63 | // To get your app running against GitHub, see:
64 | // https://probot.github.io/docs/development/
65 | };
66 |
--------------------------------------------------------------------------------
/templates/git-data-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "{{ appName }}",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "{{{ description }}}",
6 | "author": "{{{ author }}}",
7 | "license": "ISC",
8 | "homepage": "https://github.com/{{ owner }}/{{ repo }}",
9 | "keywords": [
10 | "probot",
11 | "github",
12 | "probot-app"
13 | ],
14 | "scripts": {
15 | "start": "probot run ./index.js",
16 | "test": "jest"
17 | },
18 | "dependencies": {
19 | "probot": "^13.0.1"
20 | },
21 | "devDependencies": {
22 | "jest": "^29.0.0",
23 | "nock": "^14.0.0-beta.5",
24 | "smee-client": "^2.0.0"
25 | },
26 | "engines": {
27 | "node": ">= 18"
28 | },
29 | "jest": {
30 | "testEnvironment": "node"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/templates/git-data-js/test/fixtures/installation.created.json:
--------------------------------------------------------------------------------
1 | {
2 | "action": "created",
3 | "installation": {
4 | "id": 2,
5 | "account": {
6 | "login": "hiimbex"
7 | }
8 | },
9 | "repositories": [
10 | {
11 | "name": "testing-things"
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/templates/git-data-js/test/index.test.js:
--------------------------------------------------------------------------------
1 | const nock = require("nock");
2 | // Requiring our app implementation
3 | const myProbotApp = require("..");
4 | const { Probot, ProbotOctokit } = require("probot");
5 | // Requiring our fixtures
6 | const installationCreatedPayload = require("./fixtures/installation.created");
7 | const fs = require("fs");
8 | const path = require("path");
9 |
10 | // Mocking out our use of random numbers
11 | const mockMath = Object.create(global.Math);
12 | mockMath.random = () => 1;
13 | global.Math = mockMath;
14 |
15 | const privateKey = fs.readFileSync(
16 | path.join(__dirname, "fixtures/mock-cert.pem"),
17 | "utf-8",
18 | );
19 |
20 | describe("My Probot app", () => {
21 | let probot;
22 |
23 | beforeEach(() => {
24 | nock.disableNetConnect();
25 | probot = new Probot({
26 | appId: 123,
27 | privateKey,
28 | // disable request throttling and retries for testing
29 | Octokit: ProbotOctokit.defaults({
30 | retry: { enabled: false },
31 | throttle: { enabled: false },
32 | }),
33 | });
34 | // Load our app into probot
35 | probot.load(myProbotApp);
36 | });
37 |
38 | test("creates a pull request on installation", async () => {
39 | const mock = nock("https://api.github.com")
40 | .post("/app/installations/2/access_tokens")
41 | .reply(200, {
42 | token: "test",
43 | permissions: {
44 | contents: "write",
45 | pull_requests: "write",
46 | },
47 | })
48 |
49 | .get("/repos/hiimbex/testing-things/git/ref/heads%2Fmaster")
50 | .reply(200, { object: { sha: "abc123" } })
51 |
52 | .post("/repos/hiimbex/testing-things/git/refs", {
53 | ref: "refs/heads/new-branch-9999",
54 | sha: "abc123",
55 | })
56 | .reply(200)
57 |
58 | .put(
59 | "/repos/hiimbex/testing-things/contents/path%2Fto%2Fyour%2Ffile.md",
60 | {
61 | branch: "new-branch-9999",
62 | message: "adds config file",
63 | content: "TXkgbmV3IGZpbGUgaXMgYXdlc29tZSE=",
64 | },
65 | )
66 | .reply(200)
67 |
68 | .post("/repos/hiimbex/testing-things/pulls", {
69 | title: "Adding my file!",
70 | head: "new-branch-9999",
71 | base: "master",
72 | body: "Adds my new file!",
73 | maintainer_can_modify: true,
74 | })
75 | .reply(200);
76 |
77 | // Receive a webhook event
78 | await probot.receive({
79 | name: "installation",
80 | payload: installationCreatedPayload,
81 | });
82 |
83 | expect(mock.pendingMocks()).toStrictEqual([]);
84 | });
85 |
86 | afterEach(() => {
87 | nock.cleanAll();
88 | nock.enableNetConnect();
89 | });
90 | });
91 |
92 | // For more information about testing with Jest see:
93 | // https://facebook.github.io/jest/
94 |
95 | // For more information about testing with Nock see:
96 | // https://github.com/nock/nock
97 |
--------------------------------------------------------------------------------
/tsconfig.all.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "noEmit": true
6 | },
7 | "include": ["src/**/*", "script/**/*", "*.js", "*.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": false,
4 | "module": "ESNext",
5 | "target": "es2022",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "noImplicitAny": true,
9 | "allowSyntheticDefaultImports": true,
10 | "skipLibCheck": false,
11 | "outDir": "bin",
12 | "baseUrl": ".",
13 | "paths": {
14 | "*": ["node_modules/*", "src/types/*"]
15 | }
16 | },
17 | "include": ["src/**/*"]
18 | }
19 |
--------------------------------------------------------------------------------