diff --git a/.github/workflows/node-ci.yml b/.github/workflows/node-ci.yml index ed97adf..128b8b7 100644 --- a/.github/workflows/node-ci.yml +++ b/.github/workflows/node-ci.yml @@ -20,14 +20,13 @@ jobs: strategy: matrix: node: - - 18.17.0 - - 20.6.1 - - 22 + - 20.19.0 + - 22.14.0 - 23 steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup node - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: cache: npm node-version: ${{ matrix.node }} @@ -38,7 +37,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup node - uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4.3.0 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version-file: .nvmrc cache: npm @@ -46,7 +45,10 @@ jobs: - run: npm install --global corepack@latest - run: corepack npm audit signatures - run: npm test - - uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 + - run: npx @gravityci/cli ./lib/ + env: + GRAVITY_TOKEN: ${{ secrets.GRAVITY_TOKEN }} + - uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2 release: needs: - verify diff --git a/README.md b/README.md index c503832..7909d75 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,8 @@ $ npm install @form8ion/github --save-prod ### Enabling actions against the GitHub API -This plugin leverages the [.netrc strategy](https://github.com/travi/octokit-auth-netrc) -for [octokit](https://github.com/octokit/rest.js/). Be sure to -[add your personal access token](https://github.com/travi/octokit-auth-netrc#defining-your-token) -to leverage the GitHub API integration benefits of this plugin. +Provide an authenticated octokit instance as the `octokit` property in the +options ### Enabling repository configuration with `repository-settings/app` @@ -92,6 +90,7 @@ The settings file generated by this tool assumes that it is extending an ```javascript import any from '@travi/any'; +import {octokit} from '@form8ion/github-core'; import {lift, promptConstants, scaffold, test} from '@form8ion/github'; ``` @@ -99,6 +98,13 @@ import {lift, promptConstants, scaffold, test} from '@form8ion/github'; ```javascript const projectRoot = process.cwd(); +const octokitInstance = octokit.getNetrcAuthenticatedInstance(); +const logger = { + info: message => console.error(message), + success: message => console.error(message), + warn: message => console.error(message), + error: message => console.error(message) +}; await scaffold( { @@ -110,27 +116,51 @@ await scaffold( { prompt: async ({id}) => { const {questionNames, ids} = promptConstants; - const expectedPromptId = ids.GITHUB_DETAILS; - - if (expectedPromptId === id) { - return {[questionNames[expectedPromptId].GITHUB_ACCOUNT]: any.word()}; + const { + GITHUB_DETAILS: githubDetailsPromptId, + ADMIN_SETTINGS: repositorySettingsPromptId + } = ids; + + switch (id) { + case githubDetailsPromptId: + return {[questionNames[githubDetailsPromptId].GITHUB_ACCOUNT]: any.word()}; + case repositorySettingsPromptId: + return {[questionNames[repositorySettingsPromptId].SETTINGS_MANAGED_AS_CODE]: any.boolean()}; + default: + throw new Error(`Unknown prompt with ID: ${id}`); } - - throw new Error(`Unknown prompt with ID: ${id}`); - } + }, + octokit: octokitInstance, + logger } ); if (await test({projectRoot})) { - await lift({ - projectRoot, - vcs: {owner: 'account-name', name: 'repository-name'}, - results: { - projectDetails: {homepage: any.url()}, - tags: any.listOf(any.word), - nextSteps: any.listOf(() => ({summary: any.sentence(), description: any.sentence()})) + await lift( + { + projectRoot, + vcs: {owner: 'account-name', name: 'repository-name'}, + results: { + projectDetails: {homepage: any.url()}, + tags: any.listOf(any.word), + nextSteps: any.listOf(() => ({summary: any.sentence(), description: any.sentence()})) + } + }, + { + octokit: octokitInstance, + logger, + prompt: async ({id}) => { + const {questionNames, ids} = promptConstants; + const expectedPromptId = ids.REQUIRED_CHECK_BYPASS; + + if (expectedPromptId === id) { + return {[questionNames[expectedPromptId].CHECK_BYPASS_TEAM]: any.integer()}; + } + + throw new Error(`Unknown prompt with ID: ${id}`); + } } - }); + ); } ``` diff --git a/example.js b/example.js index 5ea9fd4..f356423 100644 --- a/example.js +++ b/example.js @@ -1,8 +1,9 @@ // #### Import // remark-usage-ignore-next 2 -import {resolve} from 'path'; +import {resolve} from 'node:path'; import stubbedFs from 'mock-fs'; import any from '@travi/any'; +import {octokit} from '@form8ion/github-core'; import {lift, promptConstants, scaffold, test} from './lib/index.js'; // remark-usage-ignore-next @@ -10,7 +11,16 @@ stubbedFs({node_modules: stubbedFs.load(resolve('node_modules'))}); // #### Execute +// remark-usage-ignore-next +/* eslint-disable no-console */ const projectRoot = process.cwd(); +const octokitInstance = octokit.getNetrcAuthenticatedInstance(); +const logger = { + info: message => console.error(message), + success: message => console.error(message), + warn: message => console.error(message), + error: message => console.error(message) +}; await scaffold( { @@ -22,25 +32,52 @@ await scaffold( { prompt: async ({id}) => { const {questionNames, ids} = promptConstants; - const expectedPromptId = ids.GITHUB_DETAILS; + const { + GITHUB_DETAILS: githubDetailsPromptId, + ADMIN_SETTINGS: repositorySettingsPromptId + } = ids; - if (expectedPromptId === id) { - return {[questionNames[expectedPromptId].GITHUB_ACCOUNT]: any.word()}; + switch (id) { + case githubDetailsPromptId: + return {[questionNames[githubDetailsPromptId].GITHUB_ACCOUNT]: any.word()}; + case repositorySettingsPromptId: + return {[questionNames[repositorySettingsPromptId].SETTINGS_MANAGED_AS_CODE]: any.boolean()}; + default: + throw new Error(`Unknown prompt with ID: ${id}`); } - - throw new Error(`Unknown prompt with ID: ${id}`); - } + }, + octokit: octokitInstance, + logger } ); if (await test({projectRoot})) { - await lift({ - projectRoot, - vcs: {owner: 'account-name', name: 'repository-name'}, - results: { - projectDetails: {homepage: any.url()}, - tags: any.listOf(any.word), - nextSteps: any.listOf(() => ({summary: any.sentence(), description: any.sentence()})) + await lift( + { + projectRoot, + vcs: {owner: 'account-name', name: 'repository-name'}, + results: { + projectDetails: {homepage: any.url()}, + tags: any.listOf(any.word), + nextSteps: any.listOf(() => ({summary: any.sentence(), description: any.sentence()})) + } + }, + { + octokit: octokitInstance, + logger, + prompt: async ({id}) => { + const {questionNames, ids} = promptConstants; + const expectedPromptId = ids.REQUIRED_CHECK_BYPASS; + + if (expectedPromptId === id) { + return {[questionNames[expectedPromptId].CHECK_BYPASS_TEAM]: any.integer()}; + } + + throw new Error(`Unknown prompt with ID: ${id}`); + } } - }); + ); } + +// remark-usage-ignore-next +/* eslint-enable no-console */ diff --git a/package-lock.json b/package-lock.json index ff2d162..f2ec538 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,12 @@ "license": "MIT", "dependencies": { "@form8ion/core": "^4.6.1", - "@form8ion/repository-settings": "^1.1.4", + "@form8ion/github-core": "^1.0.0", + "@form8ion/repository-settings": "^2.0.0-beta.2", "@octokit/rest": "^21.0.0", - "@travi/cli-messages": "^1.1.1", "deepmerge": "^4.3.1", "lodash.uniqby": "^4.7.0", - "lodash.zip": "^4.2.0", - "octokit-auth-netrc": "^3.1.1" + "lodash.zip": "^4.2.0" }, "devDependencies": { "@cucumber/cucumber": "11.2.0", @@ -35,23 +34,23 @@ "http-status-codes": "2.3.0", "husky": "9.1.7", "js-yaml": "4.1.0", - "lockfile-lint": "4.14.0", + "lockfile-lint": "4.14.1", "ls-engines": "0.9.3", "mock-fs": "5.5.0", - "msw": "2.7.3", + "msw": "2.7.5", "npm-run-all2": "7.0.2", - "publint": "0.3.11", + "publint": "0.3.12", "remark-cli": "12.0.1", "remark-toc": "9.0.0", "remark-usage": "11.0.1", "rimraf": "6.0.1", - "rollup": "4.39.0", + "rollup": "4.40.1", "rollup-plugin-auto-external": "2.0.0", - "vitest": "3.1.1", + "vitest": "3.1.2", "vitest-when": "0.6.0" }, "engines": { - "node": "^18.17 || >=20.6.1" + "node": "^20.19.0 || >=22.14.0" } }, "node_modules/@ampproject/remapping": { @@ -993,9 +992,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", - "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", "cpu": [ "ppc64" ], @@ -1010,9 +1009,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", - "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", "cpu": [ "arm" ], @@ -1027,9 +1026,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", - "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", "cpu": [ "arm64" ], @@ -1044,9 +1043,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", - "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", "cpu": [ "x64" ], @@ -1061,9 +1060,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", - "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", "cpu": [ "arm64" ], @@ -1078,9 +1077,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", - "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", "cpu": [ "x64" ], @@ -1095,9 +1094,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", - "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", "cpu": [ "arm64" ], @@ -1112,9 +1111,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", - "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", "cpu": [ "x64" ], @@ -1129,9 +1128,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", - "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", "cpu": [ "arm" ], @@ -1146,9 +1145,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", - "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", "cpu": [ "arm64" ], @@ -1163,9 +1162,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", - "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", "cpu": [ "ia32" ], @@ -1180,9 +1179,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", - "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", "cpu": [ "loong64" ], @@ -1197,9 +1196,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", - "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", "cpu": [ "mips64el" ], @@ -1214,9 +1213,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", - "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", "cpu": [ "ppc64" ], @@ -1231,9 +1230,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", - "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", "cpu": [ "riscv64" ], @@ -1248,9 +1247,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", - "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", "cpu": [ "s390x" ], @@ -1265,9 +1264,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", - "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", "cpu": [ "x64" ], @@ -1282,9 +1281,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", - "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", "cpu": [ "arm64" ], @@ -1299,9 +1298,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", - "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", "cpu": [ "x64" ], @@ -1316,9 +1315,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", - "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", "cpu": [ "arm64" ], @@ -1333,9 +1332,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", - "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", "cpu": [ "x64" ], @@ -1350,9 +1349,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", - "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", "cpu": [ "x64" ], @@ -1367,9 +1366,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", - "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", "cpu": [ "arm64" ], @@ -1384,9 +1383,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", - "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", "cpu": [ "ia32" ], @@ -1401,9 +1400,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", - "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", "cpu": [ "x64" ], @@ -1418,9 +1417,9 @@ } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", + "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", "dev": true, "license": "MIT", "dependencies": { @@ -1570,6 +1569,21 @@ "node": "^18.19.0 || ^20.9.0 || >=22.11.0" } }, + "node_modules/@form8ion/github-core": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@form8ion/github-core/-/github-core-1.1.0.tgz", + "integrity": "sha512-MvfZecLN4fTP2OUJeuulR0Owl1FRYLwOd8d9ZhoXbo8xxTLe+jl2RM00zjyXRQ84oDV9qCyMvxK/TTdIpRvPJw==", + "license": "MIT", + "dependencies": { + "@form8ion/core": "^4.8.0", + "@octokit/rest": "^21.1.1", + "@travi/cli-messages": "^1.1.1", + "octokit-auth-netrc": "^3.1.2" + }, + "engines": { + "node": "^20.18.0 || >=22.11.0" + } + }, "node_modules/@form8ion/remark-lint-preset": { "version": "6.0.7", "resolved": "https://registry.npmjs.org/@form8ion/remark-lint-preset/-/remark-lint-preset-6.0.7.tgz", @@ -1593,13 +1607,19 @@ } }, "node_modules/@form8ion/repository-settings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@form8ion/repository-settings/-/repository-settings-1.3.0.tgz", - "integrity": "sha512-aRjcRpuGx3fwQXqUoUd4MHWw+R5MvE3DzxPFEgHBjA7vczsixbmmGlx+WWclPd8a2Rljd2M/iyfiO3NsYX2ziA==", + "version": "2.0.0-beta.3", + "resolved": "https://registry.npmjs.org/@form8ion/repository-settings/-/repository-settings-2.0.0-beta.3.tgz", + "integrity": "sha512-8XKWBrhgRJ0kzToKAc8Tlgs62osOU/NI0QFCTRyQFp1xx9XrtkYTwhW98LDPWPmKzjkLjpXIT1W2+jBGG4qpnQ==", "license": "MIT", "dependencies": { "@form8ion/core": "^4.3.0", - "@travi/cli-messages": "^1.1.0" + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": "^20.19.0 || >=22.14.0" + }, + "peerDependencies": { + "@octokit/core": "^6.1.5" } }, "node_modules/@gar/promisify": { @@ -2896,9 +2916,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.39.0.tgz", - "integrity": "sha512-lGVys55Qb00Wvh8DMAocp5kIcaNzEFTmGhfFd88LfaogYTRKrdxgtlO5H6S49v2Nd8R2C6wLOal0qv6/kCkOwA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz", + "integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==", "cpu": [ "arm" ], @@ -2910,9 +2930,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.39.0.tgz", - "integrity": "sha512-It9+M1zE31KWfqh/0cJLrrsCPiF72PoJjIChLX+rEcujVRCb4NLQ5QzFkzIZW8Kn8FTbvGQBY5TkKBau3S8cCQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz", + "integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==", "cpu": [ "arm64" ], @@ -2924,9 +2944,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.39.0.tgz", - "integrity": "sha512-lXQnhpFDOKDXiGxsU9/l8UEGGM65comrQuZ+lDcGUx+9YQ9dKpF3rSEGepyeR5AHZ0b5RgiligsBhWZfSSQh8Q==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz", + "integrity": "sha512-VWXGISWFY18v/0JyNUy4A46KCFCb9NVsH+1100XP31lud+TzlezBbz24CYzbnA4x6w4hx+NYCXDfnvDVO6lcAA==", "cpu": [ "arm64" ], @@ -2938,9 +2958,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.39.0.tgz", - "integrity": "sha512-mKXpNZLvtEbgu6WCkNij7CGycdw9cJi2k9v0noMb++Vab12GZjFgUXD69ilAbBh034Zwn95c2PNSz9xM7KYEAQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz", + "integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==", "cpu": [ "x64" ], @@ -2952,9 +2972,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.39.0.tgz", - "integrity": "sha512-jivRRlh2Lod/KvDZx2zUR+I4iBfHcu2V/BA2vasUtdtTN2Uk3jfcZczLa81ESHZHPHy4ih3T/W5rPFZ/hX7RtQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz", + "integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==", "cpu": [ "arm64" ], @@ -2966,9 +2986,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.39.0.tgz", - "integrity": "sha512-8RXIWvYIRK9nO+bhVz8DwLBepcptw633gv/QT4015CpJ0Ht8punmoHU/DuEd3iw9Hr8UwUV+t+VNNuZIWYeY7Q==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz", + "integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==", "cpu": [ "x64" ], @@ -2980,9 +3000,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.39.0.tgz", - "integrity": "sha512-mz5POx5Zu58f2xAG5RaRRhp3IZDK7zXGk5sdEDj4o96HeaXhlUwmLFzNlc4hCQi5sGdR12VDgEUqVSHer0lI9g==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz", + "integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==", "cpu": [ "arm" ], @@ -2994,9 +3014,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.39.0.tgz", - "integrity": "sha512-+YDwhM6gUAyakl0CD+bMFpdmwIoRDzZYaTWV3SDRBGkMU/VpIBYXXEvkEcTagw/7VVkL2vA29zU4UVy1mP0/Yw==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz", + "integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==", "cpu": [ "arm" ], @@ -3008,9 +3028,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.39.0.tgz", - "integrity": "sha512-EKf7iF7aK36eEChvlgxGnk7pdJfzfQbNvGV/+l98iiMwU23MwvmV0Ty3pJ0p5WQfm3JRHOytSIqD9LB7Bq7xdQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz", + "integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==", "cpu": [ "arm64" ], @@ -3022,9 +3042,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.39.0.tgz", - "integrity": "sha512-vYanR6MtqC7Z2SNr8gzVnzUul09Wi1kZqJaek3KcIlI/wq5Xtq4ZPIZ0Mr/st/sv/NnaPwy/D4yXg5x0B3aUUA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz", + "integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==", "cpu": [ "arm64" ], @@ -3036,9 +3056,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.39.0.tgz", - "integrity": "sha512-NMRUT40+h0FBa5fb+cpxtZoGAggRem16ocVKIv5gDB5uLDgBIwrIsXlGqYbLwW8YyO3WVTk1FkFDjMETYlDqiw==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz", + "integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==", "cpu": [ "loong64" ], @@ -3050,9 +3070,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.39.0.tgz", - "integrity": "sha512-0pCNnmxgduJ3YRt+D+kJ6Ai/r+TaePu9ZLENl+ZDV/CdVczXl95CbIiwwswu4L+K7uOIGf6tMo2vm8uadRaICQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz", + "integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==", "cpu": [ "ppc64" ], @@ -3064,9 +3084,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.39.0.tgz", - "integrity": "sha512-t7j5Zhr7S4bBtksT73bO6c3Qa2AV/HqiGlj9+KB3gNF5upcVkx+HLgxTm8DK4OkzsOYqbdqbLKwvGMhylJCPhQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz", + "integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==", "cpu": [ "riscv64" ], @@ -3078,9 +3098,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.39.0.tgz", - "integrity": "sha512-m6cwI86IvQ7M93MQ2RF5SP8tUjD39Y7rjb1qjHgYh28uAPVU8+k/xYWvxRO3/tBN2pZkSMa5RjnPuUIbrwVxeA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz", + "integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==", "cpu": [ "riscv64" ], @@ -3092,9 +3112,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.39.0.tgz", - "integrity": "sha512-iRDJd2ebMunnk2rsSBYlsptCyuINvxUfGwOUldjv5M4tpa93K8tFMeYGpNk2+Nxl+OBJnBzy2/JCscGeO507kA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz", + "integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==", "cpu": [ "s390x" ], @@ -3106,9 +3126,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.39.0.tgz", - "integrity": "sha512-t9jqYw27R6Lx0XKfEFe5vUeEJ5pF3SGIM6gTfONSMb7DuG6z6wfj2yjcoZxHg129veTqU7+wOhY6GX8wmf90dA==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz", + "integrity": "sha512-XiK5z70PEFEFqcNj3/zRSz/qX4bp4QIraTy9QjwJAb/Z8GM7kVUsD0Uk8maIPeTyPCP03ChdI+VVmJriKYbRHQ==", "cpu": [ "x64" ], @@ -3120,9 +3140,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.39.0.tgz", - "integrity": "sha512-ThFdkrFDP55AIsIZDKSBWEt/JcWlCzydbZHinZ0F/r1h83qbGeenCt/G/wG2O0reuENDD2tawfAj2s8VK7Bugg==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz", + "integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==", "cpu": [ "x64" ], @@ -3134,9 +3154,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.39.0.tgz", - "integrity": "sha512-jDrLm6yUtbOg2TYB3sBF3acUnAwsIksEYjLeHL+TJv9jg+TmTwdyjnDex27jqEMakNKf3RwwPahDIt7QXCSqRQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz", + "integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==", "cpu": [ "arm64" ], @@ -3148,9 +3168,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.39.0.tgz", - "integrity": "sha512-6w9uMuza+LbLCVoNKL5FSLE7yvYkq9laSd09bwS0tMjkwXrmib/4KmoJcrKhLWHvw19mwU+33ndC69T7weNNjQ==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz", + "integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==", "cpu": [ "ia32" ], @@ -3162,9 +3182,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.39.0.tgz", - "integrity": "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz", + "integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==", "cpu": [ "x64" ], @@ -3570,9 +3590,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", - "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", "dev": true, "license": "MIT", "dependencies": { @@ -3643,14 +3663,14 @@ "license": "ISC" }, "node_modules/@vitest/expect": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.1.tgz", - "integrity": "sha512-q/zjrW9lgynctNbwvFtQkGK9+vvHA5UzVi2V8APrp1C6fG6/MuYYkmlx4FubuqLycCeSdHD5aadWfua/Vr0EUA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.1.2.tgz", + "integrity": "sha512-O8hJgr+zREopCAqWl3uCVaOdqJwZ9qaDwUP7vy3Xigad0phZe9APxKhPcDNqYYi0rX5oMvwJMSCAXY2afqeTSA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -3659,13 +3679,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.1.tgz", - "integrity": "sha512-bmpJJm7Y7i9BBELlLuuM1J1Q6EQ6K5Ye4wcyOpOMXMcePYKSIYlpcrCm4l/O6ja4VJA5G2aMJiuZkZdnxlC3SA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.1.2.tgz", + "integrity": "sha512-kOtd6K2lc7SQ0mBqYv/wdGedlqPdM/B38paPY+OwJ1XiNi44w3Fpog82UfOibmHaV9Wod18A09I9SCKLyDMqgw==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.1.1", + "@vitest/spy": "3.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -3686,9 +3706,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.1.tgz", - "integrity": "sha512-dg0CIzNx+hMMYfNmSqJlLSXEmnNhMswcn3sXO7Tpldr0LiGmg3eXdLLhwkv2ZqgHb/d5xg5F7ezNFRA1fA13yA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.1.2.tgz", + "integrity": "sha512-R0xAiHuWeDjTSB3kQ3OQpT8Rx3yhdOAIm/JM4axXxnG7Q/fS8XUwggv/A4xzbQA+drYRjzkMnpYnOGAc4oeq8w==", "dev": true, "license": "MIT", "dependencies": { @@ -3699,13 +3719,13 @@ } }, "node_modules/@vitest/runner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.1.tgz", - "integrity": "sha512-X/d46qzJuEDO8ueyjtKfxffiXraPRfmYasoC4i5+mlLEJ10UvPb0XH5M9C3gWuxd7BAQhpK42cJgJtq53YnWVA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.1.2.tgz", + "integrity": "sha512-bhLib9l4xb4sUMPXnThbnhX2Yi8OutBMA8Yahxa7yavQsFDtwY/jrUZwpKp2XH9DhRFJIeytlyGpXCqZ65nR+g==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.1.1", + "@vitest/utils": "3.1.2", "pathe": "^2.0.3" }, "funding": { @@ -3713,13 +3733,13 @@ } }, "node_modules/@vitest/snapshot": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.1.tgz", - "integrity": "sha512-bByMwaVWe/+1WDf9exFxWWgAixelSdiwo2p33tpqIlM14vW7PRV5ppayVXtfycqze4Qhtwag5sVhX400MLBOOw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.1.2.tgz", + "integrity": "sha512-Q1qkpazSF/p4ApZg1vfZSQ5Yw6OCQxVMVrLjslbLFA1hMDrT2uxtqMaw8Tc/jy5DLka1sNs1Y7rBcftMiaSH/Q==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -3728,9 +3748,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.1.tgz", - "integrity": "sha512-+EmrUOOXbKzLkTDwlsc/xrwOlPDXyVk3Z6P6K4oiCndxz7YLpp/0R0UsWVOKT0IXWjjBJuSMk6D27qipaupcvQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.1.2.tgz", + "integrity": "sha512-OEc5fSXMws6sHVe4kOFyDSj/+4MSwst0ib4un0DlcYgQvRuYQ0+M2HyqGaauUMnjq87tmUaMNDxKQx7wNfVqPA==", "dev": true, "license": "MIT", "dependencies": { @@ -3741,13 +3761,13 @@ } }, "node_modules/@vitest/utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.1.tgz", - "integrity": "sha512-1XIjflyaU2k3HMArJ50bwSh3wKWPD6Q47wz/NUSmRV0zNywPc4w79ARjg/i/aNINHwA+mIALhUVqD9/aUvZNgg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.1.2.tgz", + "integrity": "sha512-5GGd0ytZ7BH3H6JTj9Kw7Prn1Nbg0wZVrIvou+UWxm54d+WoXXgAgjFJ8wn3LdagWLFSEfpPeyYrByZaGEZHLg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.1.1", + "@vitest/pretty-format": "3.1.2", "loupe": "^3.1.3", "tinyrainbow": "^2.0.0" }, @@ -4849,9 +4869,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001712", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001712.tgz", - "integrity": "sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==", + "version": "1.0.30001715", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz", + "integrity": "sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==", "dev": true, "funding": [ { @@ -6051,9 +6071,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.135", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.135.tgz", - "integrity": "sha512-8gXUdEmvb+WCaYUhA0Svr08uSeRjM2w3x5uHOc1QbaEVzJXB8rgm5eptieXzyKoVEtinLvW6MtTcurA65PeS1Q==", + "version": "1.5.143", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.143.tgz", + "integrity": "sha512-QqklJMOFBMqe46k8iIOwA9l2hz57V2OKMmP5eSWcUvwx+mASAsbU+wkF1pHjn9ZVSBPrsYWr4/W/95y5SwYg2g==", "dev": true, "license": "ISC" }, @@ -6241,9 +6261,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", "dev": true, "license": "MIT" }, @@ -6308,9 +6328,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", - "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -6321,31 +6341,31 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.2", - "@esbuild/android-arm": "0.25.2", - "@esbuild/android-arm64": "0.25.2", - "@esbuild/android-x64": "0.25.2", - "@esbuild/darwin-arm64": "0.25.2", - "@esbuild/darwin-x64": "0.25.2", - "@esbuild/freebsd-arm64": "0.25.2", - "@esbuild/freebsd-x64": "0.25.2", - "@esbuild/linux-arm": "0.25.2", - "@esbuild/linux-arm64": "0.25.2", - "@esbuild/linux-ia32": "0.25.2", - "@esbuild/linux-loong64": "0.25.2", - "@esbuild/linux-mips64el": "0.25.2", - "@esbuild/linux-ppc64": "0.25.2", - "@esbuild/linux-riscv64": "0.25.2", - "@esbuild/linux-s390x": "0.25.2", - "@esbuild/linux-x64": "0.25.2", - "@esbuild/netbsd-arm64": "0.25.2", - "@esbuild/netbsd-x64": "0.25.2", - "@esbuild/openbsd-arm64": "0.25.2", - "@esbuild/openbsd-x64": "0.25.2", - "@esbuild/sunos-x64": "0.25.2", - "@esbuild/win32-arm64": "0.25.2", - "@esbuild/win32-ia32": "0.25.2", - "@esbuild/win32-x64": "0.25.2" + "@esbuild/aix-ppc64": "0.25.3", + "@esbuild/android-arm": "0.25.3", + "@esbuild/android-arm64": "0.25.3", + "@esbuild/android-x64": "0.25.3", + "@esbuild/darwin-arm64": "0.25.3", + "@esbuild/darwin-x64": "0.25.3", + "@esbuild/freebsd-arm64": "0.25.3", + "@esbuild/freebsd-x64": "0.25.3", + "@esbuild/linux-arm": "0.25.3", + "@esbuild/linux-arm64": "0.25.3", + "@esbuild/linux-ia32": "0.25.3", + "@esbuild/linux-loong64": "0.25.3", + "@esbuild/linux-mips64el": "0.25.3", + "@esbuild/linux-ppc64": "0.25.3", + "@esbuild/linux-riscv64": "0.25.3", + "@esbuild/linux-s390x": "0.25.3", + "@esbuild/linux-x64": "0.25.3", + "@esbuild/netbsd-arm64": "0.25.3", + "@esbuild/netbsd-x64": "0.25.3", + "@esbuild/openbsd-arm64": "0.25.3", + "@esbuild/openbsd-x64": "0.25.3", + "@esbuild/sunos-x64": "0.25.3", + "@esbuild/win32-arm64": "0.25.3", + "@esbuild/win32-ia32": "0.25.3", + "@esbuild/win32-x64": "0.25.3" } }, "node_modules/escalade": { @@ -7840,9 +7860,9 @@ "license": "MIT" }, "node_modules/graphql": { - "version": "16.10.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", - "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", "dev": true, "license": "MIT", "engines": { @@ -9431,16 +9451,16 @@ } }, "node_modules/lockfile-lint": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/lockfile-lint/-/lockfile-lint-4.14.0.tgz", - "integrity": "sha512-uyXZ8X4J6EsicG87p0y4SHorJBwABLcaXOpI/j3h8SO/OX4fKTJ6Cqqi+U3zjgU0fo+u/4KbB7fl8ZzTewd0Ow==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/lockfile-lint/-/lockfile-lint-4.14.1.tgz", + "integrity": "sha512-NW0Tk1qfldhbhJWQENYQWANdmlanXKxvTJYRYKn56INYjaP2M07Ua2SJYkUMS+ZbYwxDzul/C6pDsV/NEXrl+A==", "dev": true, "license": "Apache-2.0", "dependencies": { "cosmiconfig": "^9.0.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", - "lockfile-lint-api": "^5.9.1", + "lockfile-lint-api": "^5.9.2", "yargs": "^17.7.2" }, "bin": { @@ -9451,9 +9471,9 @@ } }, "node_modules/lockfile-lint-api": { - "version": "5.9.1", - "resolved": "https://registry.npmjs.org/lockfile-lint-api/-/lockfile-lint-api-5.9.1.tgz", - "integrity": "sha512-us5IT1bGA6KXbq1WrhrSzk9mtPgHKz5nhvv3S4hwcYnhcVOKW2uK0W8+PN9oIgv4pI49WsD5wBdTQFTpNChF/Q==", + "version": "5.9.2", + "resolved": "https://registry.npmjs.org/lockfile-lint-api/-/lockfile-lint-api-5.9.2.tgz", + "integrity": "sha512-3QhxWxl3jT9GcMxuCnTsU8Tz5U6U1lKBlKBu2zOYOz/x3ONUoojEtky3uzoaaDgExcLqIX0Aqv2I7TZXE383CQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -11380,9 +11400,9 @@ "license": "MIT" }, "node_modules/msw": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/msw/-/msw-2.7.3.tgz", - "integrity": "sha512-+mycXv8l2fEAjFZ5sjrtjJDmm2ceKGjrNbBr1durRg6VkU9fNUE/gsmQ51hWbHqs+l35W1iM+ZsmOD9Fd6lspw==", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/msw/-/msw-2.7.5.tgz", + "integrity": "sha512-00MyTlY3TJutBa5kiU+jWiz2z5pNJDYHn2TgPkGkh92kMmNH43RqvMXd8y/7HxNn8RjzUbvZWYZjcS36fdb6sw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -12331,9 +12351,9 @@ "license": "BlueOak-1.0.0" }, "node_modules/package-manager-detector": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.1.0.tgz", - "integrity": "sha512-Y8f9qUlBzW8qauJjd/eu6jlpJZsuPJm2ZAV0cDVd420o4EdpH5RPdoCv+60/TdJflGatr4sDfpAL6ArWZbM5tA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.2.0.tgz", + "integrity": "sha512-PutJepsOtsqVfUsxCzgTTpyXmiAgvKptIgY4th5eq5UXXFhj5PxfQ9hnGkypMeovpAvVshFRItoFHYO18TCOqA==", "dev": true, "license": "MIT" }, @@ -12925,9 +12945,9 @@ } }, "node_modules/publint": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.11.tgz", - "integrity": "sha512-snArkBXO8Sl1Nlnqr3Y3DCT9CzNw8QxzlFXZ6nRkyEPEUGPRg25lM4IjNQyIyp3vRwpsZ24EEexmKSIZdVMizA==", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/publint/-/publint-0.3.12.tgz", + "integrity": "sha512-1w3MMtL9iotBjm1mmXtG3Nk06wnq9UhGNRpQ2j6n1Zq7YAD6gnxMMZMIxlRPAydVjVbjSm+n0lhwqsD1m4LD5w==", "dev": true, "license": "MIT", "dependencies": { @@ -13792,16 +13812,16 @@ } }, "node_modules/remark-lint-no-unused-definitions": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-4.0.1.tgz", - "integrity": "sha512-AdMbaCeMpj32HvDUuyI+bQyu/405Nby/rgFW8XDpI7U7ufPhHl+jj9J4NgeW7Z8DrODGr0iFgPNt6JtNLskFdA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-4.0.2.tgz", + "integrity": "sha512-KRzPmvfq6b3LSEcAQZobAn+5eDfPTle0dPyDEywgPSc3E7MIdRZQenL9UL8iIqHQWK4FvdUD0GX8FXGqu5EuCw==", "dev": true, "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "unified-lint-rule": "^3.0.0", - "unist-util-visit": "^5.0.0" + "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", @@ -14196,9 +14216,9 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", - "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", + "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", "dev": true, "license": "ISC", "dependencies": { @@ -14279,9 +14299,9 @@ } }, "node_modules/rollup": { - "version": "4.39.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.39.0.tgz", - "integrity": "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.40.1.tgz", + "integrity": "sha512-C5VvvgCCyfyotVITIAv+4efVytl5F7wt+/I2i9q9GZcEXW9BP52YYOXC58igUi+LFZVHukErIIqQSWwv/M3WRw==", "dev": true, "license": "MIT", "dependencies": { @@ -14295,26 +14315,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.39.0", - "@rollup/rollup-android-arm64": "4.39.0", - "@rollup/rollup-darwin-arm64": "4.39.0", - "@rollup/rollup-darwin-x64": "4.39.0", - "@rollup/rollup-freebsd-arm64": "4.39.0", - "@rollup/rollup-freebsd-x64": "4.39.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", - "@rollup/rollup-linux-arm-musleabihf": "4.39.0", - "@rollup/rollup-linux-arm64-gnu": "4.39.0", - "@rollup/rollup-linux-arm64-musl": "4.39.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", - "@rollup/rollup-linux-riscv64-gnu": "4.39.0", - "@rollup/rollup-linux-riscv64-musl": "4.39.0", - "@rollup/rollup-linux-s390x-gnu": "4.39.0", - "@rollup/rollup-linux-x64-gnu": "4.39.0", - "@rollup/rollup-linux-x64-musl": "4.39.0", - "@rollup/rollup-win32-arm64-msvc": "4.39.0", - "@rollup/rollup-win32-ia32-msvc": "4.39.0", - "@rollup/rollup-win32-x64-msvc": "4.39.0", + "@rollup/rollup-android-arm-eabi": "4.40.1", + "@rollup/rollup-android-arm64": "4.40.1", + "@rollup/rollup-darwin-arm64": "4.40.1", + "@rollup/rollup-darwin-x64": "4.40.1", + "@rollup/rollup-freebsd-arm64": "4.40.1", + "@rollup/rollup-freebsd-x64": "4.40.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.40.1", + "@rollup/rollup-linux-arm-musleabihf": "4.40.1", + "@rollup/rollup-linux-arm64-gnu": "4.40.1", + "@rollup/rollup-linux-arm64-musl": "4.40.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.40.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1", + "@rollup/rollup-linux-riscv64-gnu": "4.40.1", + "@rollup/rollup-linux-riscv64-musl": "4.40.1", + "@rollup/rollup-linux-s390x-gnu": "4.40.1", + "@rollup/rollup-linux-x64-gnu": "4.40.1", + "@rollup/rollup-linux-x64-musl": "4.40.1", + "@rollup/rollup-win32-arm64-msvc": "4.40.1", + "@rollup/rollup-win32-ia32-msvc": "4.40.1", + "@rollup/rollup-win32-x64-msvc": "4.40.1", "fsevents": "~2.3.2" } }, @@ -15538,6 +15558,51 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", + "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", @@ -15806,9 +15871,9 @@ } }, "node_modules/type-fest": { - "version": "4.39.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz", - "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==", + "version": "4.40.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.40.1.tgz", + "integrity": "sha512-9YvLNnORDpI+vghLU/Nf+zSv0kL47KbVJ1o3sKgoTefl6i+zebxbiDQWoe/oWWqPhIgQdRZRT1KA9sCPL810SA==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -16614,15 +16679,18 @@ } }, "node_modules/vite": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", - "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.3.tgz", + "integrity": "sha512-5nXH+QsELbFKhsEfWLkHrvgRpTdGJzqOZ+utSdmPTvwHmvU6ITTm3xx+mRusihkcI8GeC7lCDyn3kDtiki9scw==", "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -16686,9 +16754,9 @@ } }, "node_modules/vite-node": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.1.tgz", - "integrity": "sha512-V+IxPAE2FvXpTCHXyNem0M+gWm6J7eRyWPR6vYoG/Gl+IscNOjXzztUhimQgTxaAoUoj40Qqimaa0NLIOOAH4w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.1.2.tgz", + "integrity": "sha512-/8iMryv46J3aK13iUXsei5G/A3CUlW4665THCPS+K8xAaqrVWiGB4RfXMQXCLjpK9P2eK//BczrVkn5JLAk6DA==", "dev": true, "license": "MIT", "dependencies": { @@ -16708,32 +16776,61 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", + "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/vitest": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.1.tgz", - "integrity": "sha512-kiZc/IYmKICeBAZr9DQ5rT7/6bD9G7uqQEki4fxazi1jdVl2mWGzedtBs5s6llz59yQhVb7FFY2MbHzHCnT79Q==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.1.2.tgz", + "integrity": "sha512-WaxpJe092ID1C0mr+LH9MmNrhfzi8I65EX/NRU/Ld016KqQNRgxSOlGNP1hHN+a/F8L15Mh8klwaF77zR3GeDQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/expect": "3.1.1", - "@vitest/mocker": "3.1.1", - "@vitest/pretty-format": "^3.1.1", - "@vitest/runner": "3.1.1", - "@vitest/snapshot": "3.1.1", - "@vitest/spy": "3.1.1", - "@vitest/utils": "3.1.1", + "@vitest/expect": "3.1.2", + "@vitest/mocker": "3.1.2", + "@vitest/pretty-format": "^3.1.2", + "@vitest/runner": "3.1.2", + "@vitest/snapshot": "3.1.2", + "@vitest/spy": "3.1.2", + "@vitest/utils": "3.1.2", "chai": "^5.2.0", "debug": "^4.4.0", - "expect-type": "^1.2.0", + "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", - "std-env": "^3.8.1", + "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.13", "tinypool": "^1.0.2", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.1.1", + "vite-node": "3.1.2", "why-is-node-running": "^2.3.0" }, "bin": { @@ -16749,8 +16846,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.1.1", - "@vitest/ui": "3.1.1", + "@vitest/browser": "3.1.2", + "@vitest/ui": "3.1.2", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index 2f7e024..28d38cd 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "version": "0.0.0-semantically-released", "type": "module", "engines": { - "node": "^18.17 || >=20.6.1" + "node": "^20.19.0 || >=22.14.0" }, "author": "Matt Travi (https://matt.travi.org)", "repository": "form8ion/github", @@ -57,13 +57,12 @@ "packageManager": "npm@11.3.0+sha512.96eb611483f49c55f7fa74df61b588de9e213f80a256728e6798ddc67176c7b07e4a1cfc7de8922422cbce02543714367037536955221fa451b0c4fefaf20c66", "dependencies": { "@form8ion/core": "^4.6.1", - "@form8ion/repository-settings": "^1.1.4", + "@form8ion/github-core": "^1.0.0", + "@form8ion/repository-settings": "^2.0.0-beta.2", "@octokit/rest": "^21.0.0", - "@travi/cli-messages": "^1.1.1", "deepmerge": "^4.3.1", "lodash.uniqby": "^4.7.0", - "lodash.zip": "^4.2.0", - "octokit-auth-netrc": "^3.1.1" + "lodash.zip": "^4.2.0" }, "devDependencies": { "@cucumber/cucumber": "11.2.0", @@ -82,19 +81,19 @@ "http-status-codes": "2.3.0", "husky": "9.1.7", "js-yaml": "4.1.0", - "lockfile-lint": "4.14.0", + "lockfile-lint": "4.14.1", "ls-engines": "0.9.3", "mock-fs": "5.5.0", - "msw": "2.7.3", + "msw": "2.7.5", "npm-run-all2": "7.0.2", - "publint": "0.3.11", + "publint": "0.3.12", "remark-cli": "12.0.1", "remark-toc": "9.0.0", "remark-usage": "11.0.1", "rimraf": "6.0.1", - "rollup": "4.39.0", + "rollup": "4.40.1", "rollup-plugin-auto-external": "2.0.0", - "vitest": "3.1.1", + "vitest": "3.1.2", "vitest-when": "0.6.0" } } diff --git a/src/index.js b/src/index.js index 22a4f22..25154ef 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,5 @@ +export {sourceHostedOnGitHub as test} from '@form8ion/github-core'; + export {constants as promptConstants} from './prompt/index.js'; export {default as scaffold} from './scaffolder.js'; -export {default as test} from './tester.js'; export {default as lift} from './lifter.js'; diff --git a/src/lifter.js b/src/lifter.js index 9682c16..90f7c7a 100644 --- a/src/lifter.js +++ b/src/lifter.js @@ -2,10 +2,12 @@ import {test as repositoryMaintainedWithRepositorySettings, lift as liftSettings import nextSteps from './next-steps/next-steps.js'; -export default async function ({projectRoot, vcs, results}) { +export default async function liftGithub({projectRoot, vcs, results}, {octokit, logger, prompt}) { + logger.info('Lifting GitHub'); + if (await repositoryMaintainedWithRepositorySettings({projectRoot})) { - await liftSettings({projectRoot, results}); + await liftSettings({projectRoot, results, vcs}, {logger, prompt}); } - return nextSteps({results, vcs}); + return nextSteps({results, vcs}, {octokit}); } diff --git a/src/lifter.test.js b/src/lifter.test.js index 77ecdcf..9619e56 100644 --- a/src/lifter.test.js +++ b/src/lifter.test.js @@ -15,22 +15,30 @@ describe('lifter', () => { const results = any.simpleObject(); const vcs = any.simpleObject(); const nextStepsResult = any.simpleObject(); + const octokit = any.simpleObject(); + const logger = { + info: () => undefined, + success: () => undefined, + warn: () => undefined, + error: () => undefined + }; beforeEach(() => { - when(nextSteps).calledWith({results, vcs}).thenResolve(nextStepsResult); + when(nextSteps).calledWith({results, vcs}, {octokit}).thenResolve(nextStepsResult); }); it('should apply the settings lifter if the project is managed with the settings app', async () => { + const prompt = () => undefined; when(repositoryMaintainedWithRepositorySettings).calledWith({projectRoot}).thenResolve(true); - expect(await lift({projectRoot, results, vcs})).toEqual(nextStepsResult); - expect(liftSettings).toHaveBeenCalledWith({projectRoot, results}); + expect(await lift({projectRoot, results, vcs}, {octokit, logger, prompt})).toEqual(nextStepsResult); + expect(liftSettings).toHaveBeenCalledWith({projectRoot, results, vcs}, {logger, prompt}); }); it('should apply not the settings lifter if the project is not managed with the settings app', async () => { when(repositoryMaintainedWithRepositorySettings).calledWith({projectRoot}).thenResolve(false); - expect(await lift({projectRoot, results, vcs})).toEqual(nextStepsResult); - expect(liftSettings).not.toHaveBeenCalledWith({projectRoot, results}); + expect(await lift({projectRoot, results, vcs}, {octokit, logger})).toEqual(nextStepsResult); + expect(liftSettings).not.toHaveBeenCalledWith({projectRoot, results}, {logger}); }); }); diff --git a/src/next-steps/next-steps.js b/src/next-steps/next-steps.js index 305d531..cd6c332 100644 --- a/src/next-steps/next-steps.js +++ b/src/next-steps/next-steps.js @@ -1,11 +1,7 @@ import zip from 'lodash.zip'; import uniqBy from 'lodash.uniqby'; -import {factory as getAuthenticatedOctokit} from '../octokit/factory.js'; - -export default async function ({results: {nextSteps}, vcs: {name: repoName, owner}}) { - const octokit = getAuthenticatedOctokit(); - +export default async function addIssuesForNextSteps({results: {nextSteps}, vcs: {name: repoName, owner}}, {octokit}) { if (octokit && nextSteps) { const deduplicatedNextSteps = uniqBy(nextSteps, 'summary'); const issues = await Promise.all( diff --git a/src/next-steps/next-steps.test.js b/src/next-steps/next-steps.test.js index 650cad1..436602d 100644 --- a/src/next-steps/next-steps.test.js +++ b/src/next-steps/next-steps.test.js @@ -4,22 +4,23 @@ import {describe, expect, it, vi} from 'vitest'; import any from '@travi/any'; import {when} from 'vitest-when'; -import {factory as octokitFactory} from '../octokit/factory.js'; import nextSteps from './next-steps.js'; vi.mock('../octokit/factory.js'); describe('next-steps', () => { it('should return an empty list when no octokit client is available', async () => { - octokitFactory.mockReturnValue(undefined); - - expect(await nextSteps({results: {nextSteps: any.listOf(any.simpleObject)}, vcs: {}})).toEqual({nextSteps: []}); + expect(await nextSteps( + {results: {nextSteps: any.listOf(any.simpleObject)}, vcs: {}}, + {octokit: undefined} + )).toEqual({nextSteps: []}); }); it('should return an empty list when no next-steps are provided', async () => { - octokitFactory.mockReturnValue(any.simpleObject); - - expect(await nextSteps({results: {nextSteps: undefined}, vcs: {}})).toEqual({nextSteps: []}); + expect(await nextSteps( + {results: {nextSteps: undefined}, vcs: {}}, + {octokit: any.simpleObject()} + )).toEqual({nextSteps: []}); }); it('should return the URLs of the created issues', async () => { @@ -35,14 +36,15 @@ describe('next-steps', () => { const octokit = {...any.simpleObject(), issues: {create}}; const repoName = any.word(); const owner = any.word(); - octokitFactory.mockReturnValue(octokit); issueUrls.forEach((url, index) => { when(create) .calledWith({title: summaries[index], body: descriptions[index], owner, repo: repoName}) .thenResolve({data: {url}}); }); - expect(await nextSteps({results: {nextSteps: [...steps, ...structuredClone(steps)]}, vcs: {owner, name: repoName}})) - .toEqual({nextSteps: zip(issueUrls, steps).map(([url, step]) => ({...step, url}))}); + expect(await nextSteps( + {results: {nextSteps: [...steps, ...structuredClone(steps)]}, vcs: {owner, name: repoName}}, + {octokit} + )).toEqual({nextSteps: zip(issueUrls, steps).map(([url, step]) => ({...step, url}))}); }); }); diff --git a/src/octokit/factory.js b/src/octokit/factory.js deleted file mode 100644 index a18d5ca..0000000 --- a/src/octokit/factory.js +++ /dev/null @@ -1,22 +0,0 @@ -// eslint-disable-next-line import/no-unresolved -import {Octokit} from '@octokit/rest'; -import {createNetrcAuth} from 'octokit-auth-netrc'; -import {info, warn} from '@travi/cli-messages'; - -export function factory() { - try { - info('Getting GitHub Personal Access Token from ~/.netrc', {level: 'secondary'}); - - return new Octokit({authStrategy: createNetrcAuth}); - } catch (e) { - if ('ENONETRCTOKEN' !== e.code) throw e; - - warn('No GitHub Personal Access Token available in ~/.netrc'); - info( - 'Make your token available with the steps described at ' - + 'https://github.com/travi/github-scaffolder#enabling-actions-against-the-github-api' - ); - - return undefined; - } -} diff --git a/src/octokit/factory.test.js b/src/octokit/factory.test.js deleted file mode 100644 index b006b34..0000000 --- a/src/octokit/factory.test.js +++ /dev/null @@ -1,43 +0,0 @@ -// eslint-disable-next-line import/no-unresolved -import * as octokit from '@octokit/rest'; -import {createNetrcAuth} from 'octokit-auth-netrc'; - -import {afterEach, describe, expect, it, vi} from 'vitest'; -import any from '@travi/any'; -import {when} from 'vitest-when'; - -import {factory} from './factory.js'; - -vi.mock('@octokit/rest'); - -describe('github client factory', () => { - afterEach(() => { - vi.clearAllMocks(); - }); - - it('should authenticate the client using the token from netrc', () => { - const instance = any.simpleObject(); - when(octokit.Octokit).calledWith({authStrategy: createNetrcAuth}).thenReturn(instance); - - expect(factory()).toBe(instance); - }); - - it('should not return a client if no token is available in the netrc', () => { - const error = new Error('from test'); - error.code = 'ENONETRCTOKEN'; - octokit.Octokit.mockImplementation(() => { - throw error; - }); - - expect(factory()).toBeUndefined(); - }); - - it('should rethrow an error that is unrelated to a missing netrc token', () => { - const error = new Error('from test'); - octokit.Octokit.mockImplementation(() => { - throw error; - }); - - expect(() => factory()).toThrowError(error); - }); -}); diff --git a/src/prompt/constants.js b/src/prompt/constants.js index b72ab26..4f53508 100644 --- a/src/prompt/constants.js +++ b/src/prompt/constants.js @@ -1,3 +1,13 @@ -export const ids = {GITHUB_DETAILS: 'GITHUB_DETAILS'}; +import {promptConstants as repositorySettingsPromptConstants} from '@form8ion/repository-settings'; -export const questionNames = {[ids.GITHUB_DETAILS]: {GITHUB_ACCOUNT: 'GITHUB_ACCOUNT'}}; +export const ids = { + GITHUB_DETAILS: 'GITHUB_DETAILS', + ADMIN_SETTINGS: 'ADMIN_SETTINGS', + ...repositorySettingsPromptConstants.ids +}; + +export const questionNames = { + [ids.GITHUB_DETAILS]: {GITHUB_ACCOUNT: 'GITHUB_ACCOUNT'}, + [ids.ADMIN_SETTINGS]: {SETTINGS_MANAGED_AS_CODE: 'SETTINGS_MANAGED_AS_CODE'}, + ...repositorySettingsPromptConstants.questionNames +}; diff --git a/src/repository/prompt.js b/src/repository/prompt.js new file mode 100644 index 0000000..1950fc3 --- /dev/null +++ b/src/repository/prompt.js @@ -0,0 +1,16 @@ +import {constants} from '../prompt/index.js'; + +export default async function promptForRepositoryOwner(prompt) { + const promptId = constants.ids.GITHUB_DETAILS; + const githubAccountQuestionName = constants.questionNames[promptId].GITHUB_ACCOUNT; + + const {[githubAccountQuestionName]: owner} = await prompt({ + id: promptId, + questions: [{ + name: githubAccountQuestionName, + message: 'Which GitHub account should the repository be hosted within?' + }] + }); + + return owner; +} diff --git a/src/repository/prompt.test.js b/src/repository/prompt.test.js new file mode 100644 index 0000000..e671e4d --- /dev/null +++ b/src/repository/prompt.test.js @@ -0,0 +1,27 @@ +import {describe, expect, it, vi} from 'vitest'; +import {when} from 'vitest-when'; +import any from '@travi/any'; + +import {constants} from '../prompt/index.js'; +import promptForRepositoryOwner from './prompt.js'; + +describe('GitHub details prompt', () => { + const promptId = constants.ids.GITHUB_DETAILS; + const githubAccountQuestionName = constants.questionNames[promptId].GITHUB_ACCOUNT; + + it('should prompt for the GitHub account to host the repository', async () => { + const prompt = vi.fn(); + const githubAccount = any.word(); + when(prompt) + .calledWith({ + id: promptId, + questions: [{ + name: githubAccountQuestionName, + message: 'Which GitHub account should the repository be hosted within?' + }] + }) + .thenResolve({[githubAccountQuestionName]: githubAccount}); + + expect(await promptForRepositoryOwner(prompt)).toEqual(githubAccount); + }); +}); diff --git a/src/repository/scaffolder.js b/src/repository/scaffolder.js index ce6ada4..2c795f1 100644 --- a/src/repository/scaffolder.js +++ b/src/repository/scaffolder.js @@ -1,4 +1,4 @@ -import {error, info, success, warn} from '@travi/cli-messages'; +import promptForRepositoryOwner from './prompt.js'; async function authenticatedUserIsMemberOfRequestedOrganization(account, octokit) { const {data: organizations} = await octokit.orgs.listForAuthenticatedUser(); @@ -12,11 +12,11 @@ async function fetchDetailsForExistingRepository(owner, name, octokit) { return {sshUrl, htmlUrl}; } -async function createForUser(octokit, owner, name, visibility) { +async function createForUser({octokit, logger, owner, name, visibility}) { try { const repositoryDetails = await fetchDetailsForExistingRepository(owner, name, octokit); - warn(`The repository named ${owner}/${name} already exists on GitHub`); + logger.warn(`The repository named ${owner}/${name} already exists on GitHub`); return repositoryDetails; } catch (e) { @@ -26,7 +26,7 @@ async function createForUser(octokit, owner, name, visibility) { private: 'Private' === visibility }); - success(`Repository ${name} created for user ${owner} at ${htmlUrl}`); + logger.success(`Repository ${name} created for user ${owner} at ${htmlUrl}`); return {sshUrl, htmlUrl}; } @@ -35,11 +35,11 @@ async function createForUser(octokit, owner, name, visibility) { } } -async function createForOrganization(octokit, owner, name, visibility) { +async function createForOrganization({octokit, logger, owner, name, visibility}) { try { const repositoryDetails = await fetchDetailsForExistingRepository(owner, name, octokit); - warn(`The repository named ${owner}/${name} already exists on GitHub`); + logger.warn(`The repository named ${owner}/${name} already exists on GitHub`); return repositoryDetails; } catch (e) { @@ -50,7 +50,7 @@ async function createForOrganization(octokit, owner, name, visibility) { private: 'Private' === visibility }); - success(`Repository ${name} created for organization ${owner} at ${htmlUrl}`); + logger.success(`Repository ${name} created for organization ${owner} at ${htmlUrl}`); return {sshUrl, htmlUrl}; } @@ -59,23 +59,27 @@ async function createForOrganization(octokit, owner, name, visibility) { } } -export default async function ({name, owner, visibility, octokit}) { +export default async function scaffoldRepository({name, visibility}, {octokit, logger, prompt}) { if (!octokit) { - error('Repository cannot be created without a proper GitHub Personal Access Token!'); + logger.error('Repository cannot be created without a proper GitHub Personal Access Token!'); return {}; } - info('Creating repository on GitHub', {level: 'secondary'}); + const owner = await promptForRepositoryOwner(prompt); + + logger.info(`Creating repository on GitHub for account '${owner}'`, {level: 'secondary'}); const {data: {login: authenticatedUser}} = await octokit.users.getAuthenticated(); if (owner === authenticatedUser) { - return {vcs: {...await createForUser(octokit, owner, name, visibility), name, owner, host: 'github'}}; + return {vcs: {...await createForUser({octokit, logger, owner, name, visibility}), name, owner, host: 'github'}}; } if (await authenticatedUserIsMemberOfRequestedOrganization(owner, octokit)) { - return {vcs: {...await createForOrganization(octokit, owner, name, visibility), name, owner, host: 'github'}}; + return { + vcs: {...await createForOrganization({octokit, logger, owner, name, visibility}), name, owner, host: 'github'} + }; } throw new Error(`User ${authenticatedUser} does not have access to create a repository in the ${owner} account`); diff --git a/src/repository/scaffolder.test.js b/src/repository/scaffolder.test.js index 6dd9a8d..9233c20 100644 --- a/src/repository/scaffolder.test.js +++ b/src/repository/scaffolder.test.js @@ -4,8 +4,11 @@ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; import any from '@travi/any'; import {when} from 'vitest-when'; +import promptForRepositoryOwner from './prompt.js'; import scaffoldRepository from './scaffolder.js'; +vi.mock('./prompt.js'); + describe('creation', () => { const sshUrl = any.url(); const htmlUrl = any.url(); @@ -14,9 +17,20 @@ describe('creation', () => { const name = any.word(); const fetchFailureError = new Error('fetching the repo failed'); const repoNotFoundError = new Error('Repo not found in test'); + const logger = { + info: () => undefined, + success: () => undefined, + warn: () => undefined, + error: () => undefined + }; + const prompt = () => undefined; repoNotFoundError.status = StatusCodes.NOT_FOUND; + beforeEach(() => { + when(promptForRepositoryOwner).calledWith(prompt).thenResolve(account); + }); + describe('for user', () => { let getAuthenticated; @@ -39,7 +53,7 @@ describe('creation', () => { throw repoNotFoundError; }); - expect(await scaffoldRepository({name, owner: account, visibility: 'Public', octokit: client})) + expect(await scaffoldRepository({name, visibility: 'Public'}, {octokit: client, logger, prompt})) .toEqual({vcs: {sshUrl, htmlUrl, name, host: 'github', owner: account}}); }); @@ -49,7 +63,7 @@ describe('creation', () => { const client = {repos: {createForAuthenticatedUser, get}, users: {getAuthenticated}}; when(get).calledWith({owner: account, repo: name}).thenResolve(repoDetailsResponse); - expect(await scaffoldRepository({name, owner: account, visibility: 'Public', octokit: client})) + expect(await scaffoldRepository({name, visibility: 'Public'}, {octokit: client, logger, prompt})) .toEqual({vcs: {sshUrl, htmlUrl, name, host: 'github', owner: account}}); expect(createForAuthenticatedUser).not.toHaveBeenCalled(); }); @@ -63,7 +77,7 @@ describe('creation', () => { throw repoNotFoundError; }); - expect(await scaffoldRepository({name, owner: account, visibility: 'Private', octokit: client})) + expect(await scaffoldRepository({name, visibility: 'Private'}, {octokit: client, logger, prompt})) .toEqual({vcs: {sshUrl, htmlUrl, name, host: 'github', owner: account}}); }); @@ -74,7 +88,7 @@ describe('creation', () => { throw fetchFailureError; }); - await expect(scaffoldRepository({name, owner: account, visibility: 'Private', octokit: client})) + await expect(scaffoldRepository({name, visibility: 'Private'}, {octokit: client, logger, prompt})) .rejects.toThrowError(fetchFailureError); }); }); @@ -104,7 +118,7 @@ describe('creation', () => { throw repoNotFoundError; }); - expect(await scaffoldRepository({name, owner: account, visibility: 'Public', octokit: client})) + expect(await scaffoldRepository({name, visibility: 'Public'}, {octokit: client, logger, prompt})) .toEqual({vcs: {sshUrl, htmlUrl, name, host: 'github', owner: account}}); }); @@ -114,7 +128,7 @@ describe('creation', () => { const client = {repos: {createInOrg, get}, users: {getAuthenticated}, orgs: {listForAuthenticatedUser}}; when(get).calledWith({owner: account, repo: name}).thenResolve(repoDetailsResponse); - expect(await scaffoldRepository({name, owner: account, visibility: 'Public', octokit: client})) + expect(await scaffoldRepository({name, visibility: 'Public'}, {octokit: client, logger, prompt})) .toEqual({vcs: {sshUrl, htmlUrl, name, host: 'github', owner: account}}); expect(createInOrg).not.toHaveBeenCalled(); }); @@ -128,7 +142,7 @@ describe('creation', () => { throw repoNotFoundError; }); - expect(await scaffoldRepository({name, owner: account, visibility: 'Private', octokit: client})) + expect(await scaffoldRepository({name, visibility: 'Private'}, {octokit: client, logger, prompt})) .toEqual({vcs: {sshUrl, htmlUrl, name, host: 'github', owner: account}}); }); @@ -139,7 +153,7 @@ describe('creation', () => { throw fetchFailureError; }); - await expect(scaffoldRepository({name, owner: account, visibility: 'Private', octokit: client})) + await expect(scaffoldRepository({name, visibility: 'Private'}, {octokit: client, logger, prompt})) .rejects.toThrowError(fetchFailureError); }); }); @@ -153,7 +167,7 @@ describe('creation', () => { getAuthenticated.mockResolvedValue({data: {login: authenticatedUser}}); listForAuthenticatedUser.mockResolvedValue({data: any.listOf(() => ({...any.simpleObject(), login: any.word}))}); - await expect(scaffoldRepository({name, owner: account, visibility: any.word(), octokit: client})) + await expect(scaffoldRepository({name, visibility: any.word()}, {octokit: client, logger, prompt})) .rejects.toThrowError( `User ${authenticatedUser} does not have access to create a repository in the ${account} account` ); @@ -162,7 +176,7 @@ describe('creation', () => { describe('no octokit instance', () => { it('should not attempt to create a repository if no authenticated octokit instance is provided', async () => { - expect(await scaffoldRepository({name, owner: account, visibility: any.word()})) + expect(await scaffoldRepository({name, visibility: any.word()}, {logger, prompt})) .toEqual({}); }); }); diff --git a/src/scaffolder.js b/src/scaffolder.js index 78f0535..ba9674a 100644 --- a/src/scaffolder.js +++ b/src/scaffolder.js @@ -1,42 +1,23 @@ import {promises as fs} from 'node:fs'; -import {error, info} from '@travi/cli-messages'; -import {scaffold as scaffoldSettings} from '@form8ion/repository-settings'; -import {constants} from './prompt/index.js'; -import {factory as getAuthenticatedOctokit} from './octokit/factory.js'; +import {scaffold as scaffoldSettings} from './settings/index.js'; import {scaffold as scaffoldRepository} from './repository/index.js'; -async function promptForOwner(prompt) { - const promptId = constants.ids.GITHUB_DETAILS; - const githubAccountQuestionName = constants.questionNames[promptId].GITHUB_ACCOUNT; +export default async function scaffoldGithub( + {projectName, visibility, description, projectRoot}, + {prompt, octokit, logger} +) { + logger.info('Initializing GitHub'); - const {[githubAccountQuestionName]: owner} = await prompt({ - id: promptId, - questions: [{ - name: githubAccountQuestionName, - message: 'Which GitHub account should the repository be hosted within?' - }] - }); - - return owner; -} - -export default async function ({projectName, visibility, description, projectRoot}, {prompt}) { - info('Initializing GitHub'); - - const octokit = getAuthenticatedOctokit(); - const [owner] = await Promise.all([ - promptForOwner(prompt), - fs.mkdir(`${projectRoot}/.github`, {recursive: true}) - ]); + await fs.mkdir(`${projectRoot}/.github`, {recursive: true}); try { - const repositoryResult = await scaffoldRepository({octokit, name: projectName, owner, visibility}); - await scaffoldSettings({projectRoot, projectName, visibility, description}); + const repositoryResult = await scaffoldRepository({name: projectName, visibility}, {octokit, logger, prompt}); + await scaffoldSettings({projectRoot, projectName, visibility, description}, {logger, prompt}); return repositoryResult; } catch (e) { - error(e.message); + logger.error(e.message); throw e; } diff --git a/src/scaffolder.test.js b/src/scaffolder.test.js index 8c3a7e7..2b7e1a8 100644 --- a/src/scaffolder.test.js +++ b/src/scaffolder.test.js @@ -1,74 +1,61 @@ import {promises as fs} from 'node:fs'; -import {scaffold as scaffoldSettings} from '@form8ion/repository-settings'; import {when} from 'vitest-when'; import any from '@travi/any'; import {beforeEach, describe, expect, it, vi} from 'vitest'; -import {factory as octokitFactory} from './octokit/factory.js'; +import {scaffold as scaffoldSettings} from './settings/index.js'; import {scaffold as scaffoldRepository} from './repository/index.js'; import scaffold from './scaffolder.js'; -import {constants} from './prompt/index.js'; vi.mock('node:fs'); -vi.mock('@form8ion/repository-settings'); -vi.mock('./octokit/factory.js'); +vi.mock('./settings/index.js'); vi.mock('./repository/index.js'); describe('scaffolder', () => { let prompt; const projectRoot = any.string(); const name = any.word(); - const owner = any.word(); const visibility = any.word(); const description = any.sentence(); const octokitClient = any.simpleObject(); - const promptId = constants.ids.GITHUB_DETAILS; - const githubAccountQuestionName = constants.questionNames[promptId].GITHUB_ACCOUNT; + const logger = { + info: () => undefined, + success: () => undefined, + warn: () => undefined, + error: () => undefined + }; beforeEach(() => { - octokitFactory.mockReturnValue(octokitClient); - prompt = vi.fn(); }); it('should create the github repository', async () => { const repositoryResult = any.simpleObject(); when(scaffoldRepository) - .calledWith({octokit: octokitClient, name, owner, visibility}) + .calledWith({name, visibility}, {octokit: octokitClient, logger, prompt}) .thenResolve(repositoryResult); - when(prompt) - .calledWith({ - questions: [{ - name: githubAccountQuestionName, - message: 'Which GitHub account should the repository be hosted within?' - }], - id: promptId - }) - .thenResolve({[githubAccountQuestionName]: owner}); expect(await scaffold( {projectName: name, visibility, projectRoot, description}, - {prompt} + {prompt, octokit: octokitClient, logger} )).toEqual(repositoryResult); expect(fs.mkdir).toHaveBeenCalledWith(`${projectRoot}/.github`, {recursive: true}); - expect(scaffoldSettings).toHaveBeenCalledWith({projectRoot, projectName: name, visibility, description}); + expect(scaffoldSettings).toHaveBeenCalledWith( + {projectRoot, projectName: name, visibility, description}, + {logger, prompt} + ); }); it('should not scaffold settings when an error occurs scaffolding the repository', async () => { const error = new Error(any.sentence()); when(scaffoldRepository) - .calledWith({octokit: octokitClient, name, owner, visibility}) + .calledWith({name, visibility}, {octokit: octokitClient, logger, prompt}) .thenReject(error); - when(prompt).calledWith({ - questions: [{ - name: githubAccountQuestionName, - message: 'Which GitHub account should the repository be hosted within?' - }], - id: promptId - }).thenResolve({[githubAccountQuestionName]: owner}); - await expect(scaffold({projectName: name, visibility, projectRoot, description}, {prompt})) - .rejects.toThrowError(error); + await expect(scaffold( + {projectName: name, visibility, projectRoot, description}, + {prompt, octokit: octokitClient, logger} + )).rejects.toThrowError(error); }); }); diff --git a/src/settings/index.js b/src/settings/index.js new file mode 100644 index 0000000..8a5a8f5 --- /dev/null +++ b/src/settings/index.js @@ -0,0 +1 @@ +export {default as scaffold} from './scaffolder.js'; diff --git a/src/settings/prompt.js b/src/settings/prompt.js new file mode 100644 index 0000000..630eaaf --- /dev/null +++ b/src/settings/prompt.js @@ -0,0 +1,18 @@ +import {constants} from '../prompt/index.js'; + +export default async function promptForAdminSettingsHandling(prompt) { + const promptId = constants.ids.ADMIN_SETTINGS; + const settingsAsCodeQuestionName = constants.questionNames[promptId].SETTINGS_MANAGED_AS_CODE; + + const {[settingsAsCodeQuestionName]: manageSettingsAsCode} = await prompt({ + id: promptId, + questions: [{ + name: settingsAsCodeQuestionName, + message: 'Should the admin settings of the repository be managed as code?', + type: 'confirm', + default: true + }] + }); + + return manageSettingsAsCode; +} diff --git a/src/settings/prompt.test.js b/src/settings/prompt.test.js new file mode 100644 index 0000000..280a186 --- /dev/null +++ b/src/settings/prompt.test.js @@ -0,0 +1,29 @@ +import {describe, vi, it, expect} from 'vitest'; +import {when} from 'vitest-when'; +import any from '@travi/any'; + +import {constants} from '../prompt/index.js'; +import promptForAdminSettingsHandling from './prompt.js'; + +describe('admin settings prompt', () => { + const promptId = constants.ids.ADMIN_SETTINGS; + const settingsAsCodeQuestionName = constants.questionNames[promptId].SETTINGS_MANAGED_AS_CODE; + + it('should prompt for input about how to manage the admin settings of the repository', async () => { + const prompt = vi.fn(); + const manageSettingsAsCode = any.boolean(); + when(prompt) + .calledWith({ + id: promptId, + questions: [{ + name: settingsAsCodeQuestionName, + message: 'Should the admin settings of the repository be managed as code?', + type: 'confirm', + default: true + }] + }) + .thenResolve({[settingsAsCodeQuestionName]: manageSettingsAsCode}); + + expect(await promptForAdminSettingsHandling(prompt)).toEqual(manageSettingsAsCode); + }); +}); diff --git a/src/settings/scaffolder.js b/src/settings/scaffolder.js new file mode 100644 index 0000000..e9815ec --- /dev/null +++ b/src/settings/scaffolder.js @@ -0,0 +1,12 @@ +import {scaffold as scaffoldSettings} from '@form8ion/repository-settings'; + +import adminSettingsPrompt from './prompt.js'; + +export default async function scaffoldAdminSettings( + {projectRoot, projectName, visibility, description}, + {logger, prompt} +) { + if (await adminSettingsPrompt(prompt)) { + await scaffoldSettings({projectRoot, projectName, visibility, description}, {logger}); + } +} diff --git a/src/settings/scaffolder.test.js b/src/settings/scaffolder.test.js new file mode 100644 index 0000000..6011ffa --- /dev/null +++ b/src/settings/scaffolder.test.js @@ -0,0 +1,36 @@ +import {scaffold as scaffoldSettings} from '@form8ion/repository-settings'; + +import {describe, it, vi, expect} from 'vitest'; +import any from '@travi/any'; +import {when} from 'vitest-when'; + +import adminSettingsPrompt from './prompt.js'; +import scaffoldAdminSettings from './scaffolder.js'; + +vi.mock('@form8ion/repository-settings'); +vi.mock('./prompt.js'); + +describe('repository-settings scaffolder', () => { + const projectRoot = any.string(); + const projectName = any.word(); + const visibility = any.word(); + const description = any.sentence(); + const logger = any.simpleObject(); + const prompt = any.simpleObject(); + + it('should configure the repository-settings app if settings will be managed as code', async () => { + when(adminSettingsPrompt).calledWith(prompt).thenResolve(true); + + await scaffoldAdminSettings({projectRoot, projectName, visibility, description}, {logger, prompt}); + + expect(scaffoldSettings).toHaveBeenCalledWith({projectRoot, projectName, visibility, description}, {logger}); + }); + + it('should configure the repository-settings app if settings will be managed as code', async () => { + when(adminSettingsPrompt).calledWith(prompt).thenResolve(false); + + await scaffoldAdminSettings({projectRoot, projectName, visibility, description}, {logger, prompt}); + + expect(scaffoldSettings).not.toHaveBeenCalled(); + }); +}); diff --git a/src/tester.js b/src/tester.js deleted file mode 100644 index 7e5bfb0..0000000 --- a/src/tester.js +++ /dev/null @@ -1,5 +0,0 @@ -import {directoryExists} from '@form8ion/core'; - -export default function ({projectRoot}) { - return directoryExists(`${projectRoot}/.github`); -} diff --git a/src/tester.test.js b/src/tester.test.js deleted file mode 100644 index ece72c3..0000000 --- a/src/tester.test.js +++ /dev/null @@ -1,25 +0,0 @@ -import {directoryExists} from '@form8ion/core'; - -import any from '@travi/any'; -import {when} from 'vitest-when'; -import {describe, expect, it, vi} from 'vitest'; - -import projectIsVersionedOnGithub from './tester.js'; - -vi.mock('@form8ion/core'); - -describe('github predicate', () => { - const projectRoot = any.string(); - - it('should return `true` when the `.github` directory is present', async () => { - when(directoryExists).calledWith(`${projectRoot}/.github`).thenResolve(true); - - expect(await projectIsVersionedOnGithub({projectRoot})).toBe(true); - }); - - it('should return `false` when the `.github` directory is not present', async () => { - when(directoryExists).calledWith(`${projectRoot}/.github`).thenResolve(false); - - expect(await projectIsVersionedOnGithub({projectRoot})).toBe(false); - }); -}); diff --git a/test/integration/features/lift.feature b/test/integration/features/lift.feature index 9036784..effc505 100644 --- a/test/integration/features/lift.feature +++ b/test/integration/features/lift.feature @@ -5,6 +5,7 @@ Feature: Lift And netrc contains a GitHub token And the repository settings are managed by the settings app And next steps are provided + And a maintenance team exists in the organization When the scaffolder results are processed Then properties are updated in the settings file And issues are created for next-steps diff --git a/test/integration/features/scaffold.feature b/test/integration/features/scaffold.feature index 70bb0a1..4d052e5 100644 --- a/test/integration/features/scaffold.feature +++ b/test/integration/features/scaffold.feature @@ -85,3 +85,14 @@ Feature: Scaffolder But the .github directory was created And no repository settings are configured And and an authorization error is thrown + + Scenario: admin settings not managed by the repository-settings app + Given netrc contains a GitHub token + And no repository exists for the "user" on GitHub + And the visibility of the repository should be "Public" + But the admin settings should not be managed by the repository-settings app + When the project is scaffolded + Then a repository is created on GitHub + And the .github directory was created + And repository details are returned + And no repository settings are configured diff --git a/test/integration/features/step_definitions/common-steps.js b/test/integration/features/step_definitions/common-steps.js index ad470be..ee1b26c 100644 --- a/test/integration/features/step_definitions/common-steps.js +++ b/test/integration/features/step_definitions/common-steps.js @@ -1,5 +1,6 @@ import {dirname, resolve} from 'node:path'; import {fileURLToPath} from 'node:url'; +import {octokit} from '@form8ion/github-core'; import {After, Before, When} from '@cucumber/cucumber'; import stubbedFs from 'mock-fs'; @@ -12,6 +13,12 @@ const __dirname = dirname(fileURLToPath(import.meta.url)); // eslint-di const stubbedNodeModules = stubbedFs.load(resolve(__dirname, '..', '..', '..', '..', 'node_modules')); let scaffold, test, lift, promptConstants; +const logger = { + info: () => undefined, + success: () => undefined, + warn: () => undefined, + error: () => undefined +}; Before(async function () { // eslint-disable-next-line import/no-extraneous-dependencies,import/no-unresolved @@ -41,7 +48,22 @@ When('the project is scaffolded', async function () { description: this.projectDescription }, { - prompt: ({id}) => ({[promptConstants.questionNames[id].GITHUB_ACCOUNT]: this.githubUser}) + prompt: ({id}) => { + const {questionNames, ids} = promptConstants; + const githubDetailsPromptId = ids.GITHUB_DETAILS; + const repositorySettingsPromptId = ids.ADMIN_SETTINGS; + + switch (id) { + case githubDetailsPromptId: + return {[questionNames[githubDetailsPromptId].GITHUB_ACCOUNT]: this.githubUser}; + case repositorySettingsPromptId: + return {[questionNames[repositorySettingsPromptId].SETTINGS_MANAGED_AS_CODE]: this.useSettingsApp}; + default: + throw new Error(`Unknown prompt with ID: ${id}`); + } + }, + octokit: octokit.getNetrcAuthenticatedInstance(), + logger } ); } catch (err) { @@ -65,14 +87,21 @@ When('the scaffolder results are processed', async function () { }); if (await test({projectRoot: this.projectRoot})) { - this.result = await lift({ - projectRoot: this.projectRoot, - vcs: {name: this.projectName, owner: this.githubUser}, - results: { - projectDetails: this.projectDetails, - tags: this.tags, - ...this.nextSteps && {nextSteps: [...this.nextSteps, ...structuredClone(this.nextSteps)]} + this.result = await lift( + { + projectRoot: this.projectRoot, + vcs: {name: this.projectName, owner: this.githubUser}, + results: { + projectDetails: this.projectDetails, + tags: this.tags, + ...this.nextSteps && {nextSteps: [...this.nextSteps, ...structuredClone(this.nextSteps)]} + } + }, + { + octokit: octokit.getNetrcAuthenticatedInstance(), + logger, + prompt: ({id}) => ({[promptConstants.questionNames[id].CHECK_BYPASS_TEAM]: this.maintenanceTeamId}) } - }); + ); } }); diff --git a/test/integration/features/step_definitions/maintenance-team-steps.js b/test/integration/features/step_definitions/maintenance-team-steps.js new file mode 100644 index 0000000..ba18b4a --- /dev/null +++ b/test/integration/features/step_definitions/maintenance-team-steps.js @@ -0,0 +1,6 @@ +import {Given} from '@cucumber/cucumber'; +import any from '@travi/any'; + +Given('a maintenance team exists in the organization', async function () { + this.maintenanceTeamId = any.integer(); +}); diff --git a/test/integration/features/step_definitions/settings-steps.js b/test/integration/features/step_definitions/settings-steps.js index 55d43f5..a220f8d 100644 --- a/test/integration/features/step_definitions/settings-steps.js +++ b/test/integration/features/step_definitions/settings-steps.js @@ -3,7 +3,11 @@ import yaml from 'js-yaml'; import {fileExists} from '@form8ion/core'; import assert from 'node:assert'; -import {Given, Then} from '@cucumber/cucumber'; +import {Before, Given, Then} from '@cucumber/cucumber'; + +Before(function () { + this.useSettingsApp = true; +}); Given('the repository settings are managed by the settings app', async function () { this.settingsApp = true; @@ -13,6 +17,10 @@ Given('the repository settings are not managed by the settings app', async funct this.settingsApp = false; }); +Given('the admin settings should not be managed by the repository-settings app', async function () { + this.useSettingsApp = false; +}); + Then('repository settings are configured', async function () { const settings = yaml.load(await fs.readFile(`${process.cwd()}/.github/settings.yml`)); @@ -43,29 +51,30 @@ Then('properties are updated in the settings file', async function () { ...this.homepage && {homepage: this.homepage}, topics: this.tags.join(', ') }, - branches: [ + branches: [{name: 'master', protection: null}], + rulesets: [ { - name: 'master', - protection: null - } - ], - rulesets: [{ - conditions: { - ref_name: { - exclude: [], - include: [ - '~DEFAULT_BRANCH' - ] - } + conditions: {ref_name: {exclude: [], include: ['~DEFAULT_BRANCH']}}, + enforcement: 'active', + name: 'prevent destruction of the default branch', + rules: [{type: 'deletion'}, {type: 'non_fast_forward'}], + target: 'branch' }, - enforcement: 'active', - name: 'prevent destruction of the default branch', - rules: [ - {type: 'deletion'}, - {type: 'non_fast_forward'} - ], - target: 'branch' - }] + { + name: 'verification must pass', + target: 'branch', + enforcement: 'active', + conditions: {ref_name: {include: ['~DEFAULT_BRANCH'], exclude: []}}, + rules: [{ + type: 'required_status_checks', + parameters: { + strict_required_status_checks_policy: false, + required_status_checks: [{context: 'workflow-result', integration_id: 15368}] + } + }], + bypass_actors: [{actor_id: this.maintenanceTeamId, actor_type: 'Team', bypass_mode: 'always'}] + } + ] } ); });