From e7bf441de9aa5adbfeab4aff9cd663d486fcc66b Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:23:31 -0700 Subject: [PATCH 01/18] add TODO comment for implementation of permissions --- main.js | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/main.js b/main.js index 8011b51..b46122d 100644 --- a/main.js +++ b/main.js @@ -25,15 +25,42 @@ if (!privateKey) { throw new Error("Input required and not supplied: private-key"); } const owner = core.getInput("owner"); -const repositories = core.getInput("repositories") +const repositories = core + .getInput("repositories") .split(/[\n,]+/) - .map(s => s.trim()) - .filter(x => x !== ''); + .map((s) => s.trim()) + .filter((x) => x !== ""); const skipTokenRevoke = Boolean( - core.getInput("skip-token-revoke") || core.getInput("skip_token_revoke") + core.getInput("skip-token-revoke") || core.getInput("skip_token_revoke"), ); +// TODO: get all permissions from inputs. Find all environment variables with `INPUT_PERMISSION_` prefix +// and parse them into an object: {[permission_name]: [permission_access]} +// e.g. +// +// with: +// permission-organization-administration: write +// +// will set the environment variable +// +// ` INPUT_PERMISSION_ORGANIZATION_ADMINISTRATION=write` +// +// `` which should be parsed into this permissions object +// +// { "organization-administration": "write" }` +// +// Ideally we verify all permission variables and their values, and log a warning if one is unknown. +// This should be a follow up issue though. +// +// Code could look something like this +// +// const permissions = getPermissionsFromInputs(process.env) +// +// Where permissions is either undefined (unlimited) or a `Record`. We should pass it after `repositories` to `main()` +// +// @see https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#inputs + main( appId, privateKey, @@ -42,7 +69,7 @@ main( core, createAppAuth, request, - skipTokenRevoke + skipTokenRevoke, ).catch((error) => { /* c8 ignore next 3 */ console.error(error); From 44c52c73d7d439511f4d65dd89f6809283411d22 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:12:48 -0700 Subject: [PATCH 02/18] WIP implementation, not yet tested --- lib/main.js | 34 +++++++++++++++++++--------------- main.js | 43 +++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 39 deletions(-) diff --git a/lib/main.js b/lib/main.js index 0f3d07b..eb7a7a7 100644 --- a/lib/main.js +++ b/lib/main.js @@ -6,6 +6,7 @@ import pRetry from "p-retry"; * @param {string} privateKey * @param {string} owner * @param {string[]} repositories + * @param {undefined | Record} permissions * @param {import("@actions/core")} core * @param {import("@octokit/auth-app").createAppAuth} createAppAuth * @param {import("@octokit/request").request} request @@ -16,10 +17,11 @@ export async function main( privateKey, owner, repositories, + permissions, core, createAppAuth, request, - skipTokenRevoke + skipTokenRevoke, ) { let parsedOwner = ""; let parsedRepositoryNames = []; @@ -31,7 +33,7 @@ export async function main( parsedRepositoryNames = [repo]; core.info( - `owner and repositories not set, creating token for the current repository ("${repo}")` + `owner and repositories not set, creating token for the current repository ("${repo}")`, ); } @@ -40,7 +42,7 @@ export async function main( parsedOwner = owner; core.info( - `repositories not set, creating token for all repositories for given owner "${owner}"` + `repositories not set, creating token for all repositories for given owner "${owner}"`, ); } @@ -51,8 +53,8 @@ export async function main( core.info( `owner not set, creating owner for given repositories "${repositories.join( - "," - )}" in current owner ("${parsedOwner}")` + ",", + )}" in current owner ("${parsedOwner}")`, ); } @@ -63,8 +65,8 @@ export async function main( core.info( `owner and repositories set, creating token for repositories "${repositories.join( - "," - )}" owned by "${owner}"` + ",", + )}" owned by "${owner}"`, ); } @@ -84,18 +86,18 @@ export async function main( request, auth, parsedOwner, - parsedRepositoryNames + parsedRepositoryNames, ), { onFailedAttempt: (error) => { core.info( `Failed to create token for "${parsedRepositoryNames.join( - "," - )}" (attempt ${error.attemptNumber}): ${error.message}` + ",", + )}" (attempt ${error.attemptNumber}): ${error.message}`, ); }, retries: 3, - } + }, )); } else { // Otherwise get the installation for the owner, which can either be an organization or a user account @@ -104,11 +106,11 @@ export async function main( { onFailedAttempt: (error) => { core.info( - `Failed to create token for "${parsedOwner}" (attempt ${error.attemptNumber}): ${error.message}` + `Failed to create token for "${parsedOwner}" (attempt ${error.attemptNumber}): ${error.message}`, ); }, retries: 3, - } + }, )); } @@ -126,7 +128,7 @@ export async function main( } } -async function getTokenFromOwner(request, auth, parsedOwner) { +async function getTokenFromOwner(request, auth, parsedOwner, permissions) { // https://docs.github.com/rest/apps/apps?apiVersion=2022-11-28#get-a-user-installation-for-the-authenticated-app // This endpoint works for both users and organizations const response = await request("GET /users/{username}/installation", { @@ -140,6 +142,7 @@ async function getTokenFromOwner(request, auth, parsedOwner) { const authentication = await auth({ type: "installation", installationId: response.data.id, + permissions, }); const installationId = response.data.id; @@ -152,7 +155,7 @@ async function getTokenFromRepository( request, auth, parsedOwner, - parsedRepositoryNames + parsedRepositoryNames, ) { // https://docs.github.com/rest/apps/apps?apiVersion=2022-11-28#get-a-repository-installation-for-the-authenticated-app const response = await request("GET /repos/{owner}/{repo}/installation", { @@ -168,6 +171,7 @@ async function getTokenFromRepository( type: "installation", installationId: response.data.id, repositoryNames: parsedRepositoryNames, + permissions, }); const installationId = response.data.id; diff --git a/main.js b/main.js index b46122d..24b9968 100644 --- a/main.js +++ b/main.js @@ -35,37 +35,32 @@ const skipTokenRevoke = Boolean( core.getInput("skip-token-revoke") || core.getInput("skip_token_revoke"), ); -// TODO: get all permissions from inputs. Find all environment variables with `INPUT_PERMISSION_` prefix -// and parse them into an object: {[permission_name]: [permission_access]} -// e.g. -// -// with: -// permission-organization-administration: write -// -// will set the environment variable -// -// ` INPUT_PERMISSION_ORGANIZATION_ADMINISTRATION=write` -// -// `` which should be parsed into this permissions object -// -// { "organization-administration": "write" }` -// -// Ideally we verify all permission variables and their values, and log a warning if one is unknown. -// This should be a follow up issue though. -// -// Code could look something like this -// -// const permissions = getPermissionsFromInputs(process.env) -// -// Where permissions is either undefined (unlimited) or a `Record`. We should pass it after `repositories` to `main()` -// // @see https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#inputs +function getPermissionsFromInputs(env) { + return Object.entries(env).reduce((permissions, [key, value]) => { + if (!key.startsWith("INPUT_PERMISSION_")) return permissions; + + const permission = key.slice("INPUT_PERMISSION_".length).toLowerCase(); + if (permissions === undefined) { + return { [permission]: value }; + } + + return { + // @ts-expect-error - needs to be typed correctly + ...permissions, + [permission]: value, + }; + }, undefined); +} + +const permissions = getPermissionsFromInputs(process.env); main( appId, privateKey, owner, repositories, + permissions, core, createAppAuth, request, From 0fd353522d30e4d3cbd9eaef288f98bb32263270 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:46:38 -0700 Subject: [PATCH 03/18] test: log out requests for snapshot testing --- lib/main.js | 5 +- tests/main.js | 26 +++++- tests/snapshots/index.js.md | 169 +++++++++++++++++++++++++++++++--- tests/snapshots/index.js.snap | Bin 1318 -> 1895 bytes 4 files changed, 183 insertions(+), 17 deletions(-) diff --git a/lib/main.js b/lib/main.js index eb7a7a7..b9cb759 100644 --- a/lib/main.js +++ b/lib/main.js @@ -87,9 +87,11 @@ export async function main( auth, parsedOwner, parsedRepositoryNames, + permissions, ), { onFailedAttempt: (error) => { + console.log(error); core.info( `Failed to create token for "${parsedRepositoryNames.join( ",", @@ -102,7 +104,7 @@ export async function main( } else { // Otherwise get the installation for the owner, which can either be an organization or a user account ({ authentication, installationId, appSlug } = await pRetry( - () => getTokenFromOwner(request, auth, parsedOwner), + () => getTokenFromOwner(request, auth, parsedOwner, permissions), { onFailedAttempt: (error) => { core.info( @@ -156,6 +158,7 @@ async function getTokenFromRepository( auth, parsedOwner, parsedRepositoryNames, + permissions, ) { // https://docs.github.com/rest/apps/apps?apiVersion=2022-11-28#get-a-repository-installation-for-the-authenticated-app const response = await request("GET /repos/{owner}/{repo}/installation", { diff --git a/tests/main.js b/tests/main.js index 245b6e6..f74d442 100644 --- a/tests/main.js +++ b/tests/main.js @@ -60,11 +60,15 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { const owner = env.INPUT_OWNER ?? env.GITHUB_REPOSITORY_OWNER; const currentRepoName = env.GITHUB_REPOSITORY.split("/")[1]; const repo = encodeURIComponent( - (env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0] + (env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0], ); + + const getInstallationPath = `${basePath}/repos/${owner}/${repo}/installation`; + console.log(`\nGET ${getInstallationPath}\n`); + mockPool .intercept({ - path: `${basePath}/repos/${owner}/${repo}/installation`, + path: getInstallationPath, method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -75,27 +79,39 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { .reply( 200, { id: mockInstallationId, app_slug: mockAppSlug }, - { headers: { "content-type": "application/json" } } + { headers: { "content-type": "application/json" } }, ); // Mock installation access token request const mockInstallationAccessToken = "ghs_16C7e42F292c6912E7710c838347Ae178B4a"; // This token is invalidated. It’s from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app. const mockExpiresAt = "2016-07-11T22:14:10Z"; + const createInstallationAccessTokenPath = `${basePath}/app/installations/${mockInstallationId}/access_tokens`; mockPool .intercept({ - path: `${basePath}/app/installations/${mockInstallationId}/access_tokens`, + path: createInstallationAccessTokenPath, method: "POST", headers: { accept: "application/vnd.github.v3+json", "user-agent": "actions/create-github-app-token", // Note: Intentionally omitting the `authorization` header, since JWT creation is not idempotent. }, + // log out payload for output snapshot testing + body(payload) { + console.log( + `\nPOST ${createInstallationAccessTokenPath}\n${JSON.stringify( + payload, + null, + 2, + )}\n`, + ); + return true; + }, }) .reply( 201, { token: mockInstallationAccessToken, expires_at: mockExpiresAt }, - { headers: { "content-type": "application/json" } } + { headers: { "content-type": "application/json" } }, ); // Run the callback diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 73a4c6a..706f6f7 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -24,7 +24,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ + `␊ + GET /api/v3/repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ + ␊ + POST /api/v3/app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ + ␊ + POST /api/v3/app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -83,7 +94,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -103,7 +125,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"failed-repo\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"failed-repo\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -122,8 +155,19 @@ Generated by [AVA](https://avajs.dev). > stdout - `repositories not set, creating token for all repositories for given owner "smockle"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + repositories not set, creating token for all repositories for given owner "smockle"␊ Failed to create token for "smockle" (attempt 1): GitHub API not available␊ + ␊ + POST /app/installations/123456/access_tokens␊ + null␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + null␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -142,8 +186,45 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + RequestError [HttpError]: GitHub API not available␊ + at file:///Users/gregor/code/actions/create-github-app-token/node_modules/@octokit/request/dist-bundle/index.js:106:21␊ + at process.processTicksAndRejections (node:internal/process/task_queues:95:5)␊ + at async hook (file:///Users/gregor/code/actions/create-github-app-token/node_modules/@octokit/auth-app/dist-node/index.js:319:18)␊ + at async getTokenFromRepository (file:///Users/gregor/code/actions/create-github-app-token/lib/main.js:164:20)␊ + at async RetryOperation._fn (file:///Users/gregor/code/actions/create-github-app-token/node_modules/p-retry/index.js:57:20) {␊ + status: 500,␊ + request: {␊ + method: 'GET',␊ + url: 'https://api.github.com/repos/actions/failed-repo/installation',␊ + headers: {␊ + accept: 'application/vnd.github.v3+json',␊ + 'user-agent': 'actions/create-github-app-token',␊ + authorization: 'bearer [REDACTED]'␊ + },␊ + request: { hook: [Function: bound hook] AsyncFunction }␊ + },␊ + response: {␊ + url: 'https://api.github.com/repos/actions/failed-repo/installation',␊ + status: 500,␊ + headers: {},␊ + data: 'GitHub API not available'␊ + },␊ + attemptNumber: 1,␊ + retriesLeft: 3␊ + }␊ Failed to create token for "failed-repo" (attempt 1): GitHub API not available␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"failed-repo\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"failed-repo\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -162,7 +243,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -181,7 +273,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -200,7 +303,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -219,7 +333,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `repositories not set, creating token for all repositories for given owner "actions"␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + repositories not set, creating token for all repositories for given owner "actions"␊ + ␊ + POST /app/installations/123456/access_tokens␊ + null␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + null␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -238,7 +363,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner not set, creating owner for given repositories "create-github-app-token" in current owner ("actions")␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner not set, creating owner for given repositories "create-github-app-token" in current owner ("actions")␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -257,7 +393,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ + ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 061ef5b8b6372f1cb16b1cea0dac1646c8574b67..205110358f235f10eae89ecdbef84b727dc3a7a6 100644 GIT binary patch literal 1895 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 From 70b72c050adc45a9ef54e44fabcce9416c209ea8 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:48:04 -0700 Subject: [PATCH 04/18] add test for permissions input --- tests/main-token-permissions-set.test.js | 7 ++++++ tests/snapshots/index.js.md | 30 +++++++++++++++++++++++ tests/snapshots/index.js.snap | Bin 1895 -> 1968 bytes 3 files changed, 37 insertions(+) create mode 100644 tests/main-token-permissions-set.test.js diff --git a/tests/main-token-permissions-set.test.js b/tests/main-token-permissions-set.test.js new file mode 100644 index 0000000..b3f6386 --- /dev/null +++ b/tests/main-token-permissions-set.test.js @@ -0,0 +1,7 @@ +import { test } from "./main.js"; + +// Verify `main` successfully sets permissions +await test(() => { + process.env.INPUT_PERMISSION_ISSUES = `write`; + process.env.INPUT_PERMISSION_PULL_REQUESTS = `read`; +}); diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 706f6f7..d4534fd 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -415,6 +415,36 @@ Generated by [AVA](https://avajs.dev). ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ::save-state name=expiresAt::2016-07-11T22:14:10Z` +## main-token-permissions-set.test.js + +> stderr + + '' + +> stdout + + `␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"],\\"permissions\\":{\\"issues\\":\\"write\\",\\"pull_requests\\":\\"read\\"}}"␊ + ␊ + ␊ + POST /app/installations/123456/access_tokens␊ + "{\\"repositories\\":[\\"create-github-app-token\\"],\\"permissions\\":{\\"issues\\":\\"write\\",\\"pull_requests\\":\\"read\\"}}"␊ + ␊ + ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ␊ + ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ␊ + ::set-output name=installation-id::123456␊ + ␊ + ::set-output name=app-slug::github-actions␊ + ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ + ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ## post-revoke-token-fail-response.test.js > stderr diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 205110358f235f10eae89ecdbef84b727dc3a7a6..2b3c7d059642fea9b5a0611d673852ed4b0ce59b 100644 GIT binary patch literal 1968 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 Date: Thu, 20 Mar 2025 11:53:12 -0700 Subject: [PATCH 05/18] log out GET installation request on actual request --- tests/main.js | 6 +- tests/snapshots/index.js.md | 101 ++++++++++++++++++++++++---------- tests/snapshots/index.js.snap | Bin 1968 -> 1989 bytes 3 files changed, 77 insertions(+), 30 deletions(-) diff --git a/tests/main.js b/tests/main.js index f74d442..0359577 100644 --- a/tests/main.js +++ b/tests/main.js @@ -64,11 +64,13 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { ); const getInstallationPath = `${basePath}/repos/${owner}/${repo}/installation`; - console.log(`\nGET ${getInstallationPath}\n`); mockPool .intercept({ - path: getInstallationPath, + path(pathString) { + console.log(`\nGET ${pathString}\n`); + return pathString === getInstallationPath; + }, method: "GET", headers: { accept: "application/vnd.github.v3+json", diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index d4534fd..438e377 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -24,10 +24,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ + ␊ + GET /api/v3/repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /api/v3/repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ ␊ POST /api/v3/app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ @@ -94,10 +97,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ @@ -125,10 +131,16 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ - GET /repos/actions/create-github-app-token/installation␊ + `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + ␊ + GET /repos/actions/failed-repo/installation␊ + ␊ + ␊ + GET /repos/actions/failed-repo/installation␊ + ␊ + ␊ + GET /app/installations/123456/access_tokens␊ ␊ - owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"failed-repo\\"]}"␊ @@ -155,12 +167,18 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ - GET /repos/actions/create-github-app-token/installation␊ + `repositories not set, creating token for all repositories for given owner "smockle"␊ + ␊ + GET /users/smockle/installation␊ ␊ - repositories not set, creating token for all repositories for given owner "smockle"␊ Failed to create token for "smockle" (attempt 1): GitHub API not available␊ ␊ + GET /users/smockle/installation␊ + ␊ + ␊ + GET /app/installations/123456/access_tokens␊ + ␊ + ␊ POST /app/installations/123456/access_tokens␊ null␊ ␊ @@ -186,10 +204,10 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ - GET /repos/actions/create-github-app-token/installation␊ + `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ + ␊ + GET /repos/actions/failed-repo/installation␊ ␊ - owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ RequestError [HttpError]: GitHub API not available␊ at file:///Users/gregor/code/actions/create-github-app-token/node_modules/@octokit/request/dist-bundle/index.js:106:21␊ at process.processTicksAndRejections (node:internal/process/task_queues:95:5)␊ @@ -218,6 +236,12 @@ Generated by [AVA](https://avajs.dev). }␊ Failed to create token for "failed-repo" (attempt 1): GitHub API not available␊ ␊ + GET /repos/actions/failed-repo/installation␊ + ␊ + ␊ + GET /app/installations/123456/access_tokens␊ + ␊ + ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"failed-repo\\"]}"␊ ␊ @@ -243,10 +267,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ @@ -273,10 +300,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ @@ -303,10 +333,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ @@ -333,10 +366,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ - GET /repos/actions/create-github-app-token/installation␊ + `repositories not set, creating token for all repositories for given owner "actions"␊ + ␊ + GET /users/actions/installation␊ + ␊ + ␊ + GET /app/installations/123456/access_tokens␊ ␊ - repositories not set, creating token for all repositories for given owner "actions"␊ ␊ POST /app/installations/123456/access_tokens␊ null␊ @@ -363,10 +399,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner not set, creating owner for given repositories "create-github-app-token" in current owner ("actions")␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner not set, creating owner for given repositories "create-github-app-token" in current owner ("actions")␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ @@ -393,10 +432,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ @@ -423,10 +465,13 @@ Generated by [AVA](https://avajs.dev). > stdout - `␊ + `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ + ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ GET /repos/actions/create-github-app-token/installation␊ ␊ - owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"],\\"permissions\\":{\\"issues\\":\\"write\\",\\"pull_requests\\":\\"read\\"}}"␊ diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 2b3c7d059642fea9b5a0611d673852ed4b0ce59b..63850df9a435068a10e9557810d05d819d6e58fb 100644 GIT binary patch literal 1989 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 Date: Thu, 20 Mar 2025 12:18:33 -0700 Subject: [PATCH 06/18] only log intercepted requests once --- lib/request.js | 2 +- tests/main.js | 32 +++++++++--- tests/snapshots/index.js.md | 93 ---------------------------------- tests/snapshots/index.js.snap | Bin 1989 -> 1926 bytes 4 files changed, 26 insertions(+), 101 deletions(-) diff --git a/lib/request.js b/lib/request.js index 1bc8332..7593fb7 100644 --- a/lib/request.js +++ b/lib/request.js @@ -17,7 +17,7 @@ const proxyUrl = const proxyFetch = (url, options) => { const urlHost = new URL(url).hostname; const noProxy = (process.env.no_proxy || process.env.NO_PROXY || "").split( - "," + ",", ); if (!noProxy.includes(urlHost)) { diff --git a/tests/main.js b/tests/main.js index 0359577..4650978 100644 --- a/tests/main.js +++ b/tests/main.js @@ -65,10 +65,13 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { const getInstallationPath = `${basePath}/repos/${owner}/${repo}/installation`; + const logGetInstallationRequest = once((pathString) => + console.log(`\nGET ${pathString}\n`), + ); mockPool .intercept({ path(pathString) { - console.log(`\nGET ${pathString}\n`); + logGetInstallationRequest(pathString); return pathString === getInstallationPath; }, method: "GET", @@ -89,6 +92,9 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { "ghs_16C7e42F292c6912E7710c838347Ae178B4a"; // This token is invalidated. It’s from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app. const mockExpiresAt = "2016-07-11T22:14:10Z"; const createInstallationAccessTokenPath = `${basePath}/app/installations/${mockInstallationId}/access_tokens`; + const logCreateInstallationAccessTokenRequest = once((path, payload) => { + console.log(`\nPOST ${path}\n${JSON.stringify(payload, null, 2)}\n`); + }); mockPool .intercept({ path: createInstallationAccessTokenPath, @@ -100,12 +106,9 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { }, // log out payload for output snapshot testing body(payload) { - console.log( - `\nPOST ${createInstallationAccessTokenPath}\n${JSON.stringify( - payload, - null, - 2, - )}\n`, + logCreateInstallationAccessTokenRequest( + createInstallationAccessTokenPath, + payload, ); return true; }, @@ -122,3 +125,18 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { // Run the main script await import("../main.js"); } + +/** + * Undici seems to invoke the `path()` and `body()` callbacks twice, + * which results in us logging the requests twice. This helper ensures + * we only log the request once. + */ +export function once(fn) { + let called = false; + return (...args) => { + if (!called) { + called = true; + return fn(...args); + } + }; +} diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 438e377..1472fbd 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -29,13 +29,6 @@ Generated by [AVA](https://avajs.dev). GET /api/v3/repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /api/v3/repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /api/v3/app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ - ␊ POST /api/v3/app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ ␊ @@ -102,13 +95,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ ␊ @@ -136,16 +122,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/failed-repo/installation␊ ␊ ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ - ␊ - GET /app/installations/123456/access_tokens␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"failed-repo\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"failed-repo\\"]}"␊ ␊ @@ -173,16 +149,6 @@ Generated by [AVA](https://avajs.dev). ␊ Failed to create token for "smockle" (attempt 1): GitHub API not available␊ ␊ - GET /users/smockle/installation␊ - ␊ - ␊ - GET /app/installations/123456/access_tokens␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - null␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ null␊ ␊ @@ -236,16 +202,6 @@ Generated by [AVA](https://avajs.dev). }␊ Failed to create token for "failed-repo" (attempt 1): GitHub API not available␊ ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ - ␊ - GET /app/installations/123456/access_tokens␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"failed-repo\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"failed-repo\\"]}"␊ ␊ @@ -272,13 +228,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ ␊ @@ -305,13 +254,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ ␊ @@ -338,13 +280,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ ␊ @@ -371,13 +306,6 @@ Generated by [AVA](https://avajs.dev). GET /users/actions/installation␊ ␊ ␊ - GET /app/installations/123456/access_tokens␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - null␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ null␊ ␊ @@ -404,13 +332,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ ␊ @@ -437,13 +358,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ ␊ @@ -470,13 +384,6 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"],\\"permissions\\":{\\"issues\\":\\"write\\",\\"pull_requests\\":\\"read\\"}}"␊ - ␊ - ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"],\\"permissions\\":{\\"issues\\":\\"write\\",\\"pull_requests\\":\\"read\\"}}"␊ ␊ diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 63850df9a435068a10e9557810d05d819d6e58fb..d023c69ff99004d241d6ddc1dea8a9ef115d8152 100644 GIT binary patch literal 1926 zcmV;12YL8GRzV ztvK)(0C)CJ(laNk^fpsqFbXR}x zd#}FtUZuMJ((8u8AF4lpgPQ3O-vISB6Wk3jlIT;7fy;OlYgN^#boG^Diql99gjT=* zCJ3mezy4t9!IJq|{?5{OmoTJV40}okC}lF>0yMFwhAir6F+|>xI2J=ptX{ZX%(j7ZEu1@rOBu|?D% z58|#%Bj(03EHIlZL2fpmuZRA|xZ0*#{FbLG_= z&9(InkNQ3;l}wx}Id9uemUG)7N9}pM+s^TsQz{WcgTNh8H6)}zP@Ve57n``&*llbz z{Ee-8V`p=-Uh^L{A2ruDx3RwY=<_vd-cqPt5$h<{!08BoW-*IFWIc3QKuF@`WkZb@ zDvbMtOx#MMYlhM>x=K@xwxYd7sjrcG?YEZ-`eQ5T z5mSoszMEwITqVC)&+2r!yl=`FNPHbLnWi2W8dMxbA;W+`f_I7J=jB9(*$;BeY(~r{ zwwEKewYPuxvq)Bu9~4i0QS_^gc6YZX499C7kiwJz;v_qVj2k zfy?nEWE_h$(UoVpvio>m*|jqrA!`$tZYe_JZ=D;1l1pv&Ngl#O7u%&0CuoTeP*u+KI2(XIj{D&&bm2MC&t z5cGg*`xjLTr3nk1PzB5aS4&5~5WW^erac<#fziV;>@oc$?!xxd{RF}!ggR9kN9o@Z zAz-~8TGe+?p;-fkzTknXLJPG#H4IEKL#4rFttBvd#YdpNFJf+%Yds;Wm*!?87m81c zEs1)Rg&5cwxMCTUPsz+X_mGAe^hN63=K?2bBgqoKZ^#=RxyB7M1+GLD39hh68`;fC zb#vv$&4Y$vUa00~pN)}2B6mlPgg*>%qR?2OR9<@XoGN#%qD=oyN_@u76b4qQ);NkZ z)E|;;o*R~QOj$^~A^wK~=W!S=)Nh8^jQb;&@ zqIG01kFO9g007m{V<8gH^PbzZ=}YVj>G>kSYu8;|1lSpgAP!M^(-xVwG%sLEyWN-v zHVFfKQ+=gKy|zIb^@-_73X>z%^!Fk2hiaP#EqsNEX;?Kj2;&+hr=gb)^fXn&&g&Rs zRAg(NtUsI}QgzCG7zi5`f9ySP@vS)hZ>JtZImT z1~5WB5CMVm-p*mUVsFJVBv2k`9Vz0Ojge|%yy}b54K<%44Uh&X)x;KNF_=*YVADU{^D@w z@p0J>JWIyUB4Wi!;Al7Ie)4Kp#5}OKk73));^YyWl~RC7@tSyfci}rXbJ=*N)J^F# zb2q1qlqVe1ruk(&>Y^l2Pk3un?0$tkO`usiyR!f03gUhA;Kd^IzuKj@uI|$2LJN09 z`RQceqR4vl>s+sXeJ{Jk6)i+KWV+%H&>#NW)f+eR_h2id(sok%_Il#NA_wj>2kJM@ zfra)L+W-I3e(gru7sbl{S2^kLz3Y#J@14>Yg1$dNe|oi`W3EsaIll1EoRGu!ca{X4?PA0Z(hrDe&_7lCi zZaXKEX|(^(MR6E*(k<8InM4}2owG#-+*<~eBcXJ9J~T~)JNoYSB6rGR`6q;&P{|qZ z6JkHFfH9iv^Fy+kOW^Xua+YGkEpc)FDZcAjZRA+3CR9?`3Yasq(JT{Z6fZsck|9>8 zV!Ze`N9w~_e1;fY8xza9P)vTBGylU2(_;?Rq*g9v^Sun4g3bTMk8)f-O1Q9TvCP^3 M7qYWAc8@Lq0Clgs7XSbN literal 1989 zcmV;$2RiscRzVUZ5l2>grfm0m+&$Ob<7`+(LVO0qJNGsC2Jp-aPY4jNNJu;b-7~glk~s0j_Hql( zOU5(ZRllmPUsbuM{hLlZ6nY7AV)qgbo5My1Oy6;qr> zswcGi&K-+O5lq}JVm(?*XFwTu z{a9%+aJx+R;R!8Be$CWS{G*=r8PxjBoxy^GE|^Ym%x`uHRD~du%RPl zevo4a-~?T2paVu~0PS;dl897Jp>VK&3?7Y`H>`VBjF&$1rik&3e`pv|Gpeuv0nd&; zok*ZjlzXncYOTJxwe3;gN2QXLR|V&F)5#j$bjV3_n&D07^ul?AiU^@W;0~zj6VmOe zR(1R19o(!vuI<+R?cHi^e`lv!@gLP6)i-zcu)6c;qfKgNDb%irbrfshbbvpyGUpSK zwa{e&A&HUK4K-G%FzymEGAmg|Gn5X|RhnwN8?dVq@KwYlsy$6ety0}~D?4trdR(iK z>L#gHes(SO-m%mhFr^spx=DVT%DER?Sw`I}9-4#;5`ftEO(~^JIDdsJvcmm^8BM#WB=LFr-#Q!jn7&~KYhC2fK*xu2C>p6mnqbs z1r*=6@;@lv4JzcIW-{+|z$6E_bgL&bLhpw0dpV3__T2#SNe&{p;?rBb>Ai2%+|{XN z3piu9d&YFnMdi~71DE4j$T-eZ?$`gGD-eI0Rv_$3Oeqq&hv3IjBG;2i=ddxgUOY^b z``ydJT=ii2g1Z~Qgqia*TPSav82F|aFeLo=BteP+%KDdM)#Gjetz6whE;VB)wc zb(JiZ(k>=NIr(bWHQ-I;yT%N&1g=CC39fLSqWrrYxqiDob19}_n5UMx*=0lIkPy^S z1L5~W9C0dED3zDqyu^&hHlj>7lN6PQO1k#hR~nE8FR$AbpG#6&f07#)Ohjgr&QO9y(Is($P97-LjqcZ+O297&|=ocqud zq7NI3Hf+=}C6<{n6T9lwT~d8?2}T$7v61&!ia{guMdt3nLe}<7tXo%ZZ<1Q&l1kf- z9YrW@Sd?2GzA!&Tt~A0YHgD}1{qVW~VE7v=0$Y_zsQ{y1kl1Gc1Jpec5GWq(9~VpZ zRxCpT#h%uYBA(gmDksXzz8K6H^QojB(g39z=>pSiVx)=P84j6m$9h8^j5G}E@4Zyx z=>SDjMqJuOu8U^Y%|01VGtnR<`?-}*px8z#QNl@M|C7CskM}=0E!u$>$@qy!Y;Y1d zc^q>;nc5aH5A5wz*fXm*dIT4RRKO^CjjUXp`!20q)}JYKllsisO-Uog5yrG|KaB@% zlmw~?Zf%m?kFlc()C(6k_5itr_+|QlRcpTLE0)q%?B3j0mkus z*MD$-8Shp~T8OaEbjk0b-~W%PGq)aZ^>$jR>7<6+>yhzqVxR41)hpsIg}Bw3iMt}~ zim)rf{?`dxnTfDst^&LMj~rkB@}>_j{14G{^?K@UCfj>AlP%^7^*lT~&GGE%BDb3_ zQ7YL19uZ@;1H209Tu9qU9#@cgLi*C1+O%|BjpgM2By4A_8H|rlJR}k}#*w}{+_0)1 zUn#1&w^42G`ms7gw4&MnJz2qbHJ!|=G#&D~ z>DWV7=DO*eNv6^6A4G8&w$j%>$uo&GXgU|mXXj!tuK2waeitL5boyJ4l;#UMr|_bd zJ7xTRLe8k Date: Thu, 20 Mar 2025 12:57:47 -0700 Subject: [PATCH 07/18] log all requests for the main tests --- tests/main-repo-skew.test.js | 36 ++++++++++-------- ...-token-get-owner-set-fail-response.test.js | 8 ++-- ...n-get-owner-set-repo-fail-response.test.js | 10 ++--- ...ain-token-get-owner-set-repo-unset.test.js | 6 +-- ...n-token-get-owner-unset-repo-unset.test.js | 10 +++-- tests/main.js | 27 ++++++++----- tests/snapshots/index.js.md | 25 +++++++++++- tests/snapshots/index.js.snap | Bin 1926 -> 1957 bytes 8 files changed, 78 insertions(+), 44 deletions(-) diff --git a/tests/main-repo-skew.test.js b/tests/main-repo-skew.test.js index e35a531..e0bc921 100644 --- a/tests/main-repo-skew.test.js +++ b/tests/main-repo-skew.test.js @@ -1,13 +1,13 @@ -import { test } from "./main.js"; +import { test, getLogOnceOnPath } from "./main.js"; import { install } from "@sinonjs/fake-timers"; // Verify `main` retry when the clock has drifted. await test((mockPool) => { - process.env.INPUT_OWNER = 'actions' - process.env.INPUT_REPOSITORIES = 'failed-repo'; - const owner = process.env.INPUT_OWNER - const repo = process.env.INPUT_REPOSITORIES + process.env.INPUT_OWNER = "actions"; + process.env.INPUT_REPOSITORIES = "failed-repo"; + const owner = process.env.INPUT_OWNER; + const repo = process.env.INPUT_REPOSITORIES; const mockInstallationId = "123456"; const mockAppSlug = "github-actions"; @@ -15,7 +15,7 @@ await test((mockPool) => { mockPool .intercept({ - path: `/repos/${owner}/${repo}/installation`, + path: getLogOnceOnPath(`/repos/${owner}/${repo}/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -25,20 +25,23 @@ await test((mockPool) => { }) .reply(({ headers }) => { const [_, jwt] = (headers.authorization || "").split(" "); - const payload = JSON.parse(Buffer.from(jwt.split(".")[1], "base64").toString()); + const payload = JSON.parse( + Buffer.from(jwt.split(".")[1], "base64").toString(), + ); if (payload.iat < 0) { return { statusCode: 401, data: { - message: "'Issued at' claim ('iat') must be an Integer representing the time that the assertion was issued." + message: + "'Issued at' claim ('iat') must be an Integer representing the time that the assertion was issued.", }, responseOptions: { headers: { "content-type": "application/json", - "date": new Date(Date.now() + 30000).toUTCString() - } - } + date: new Date(Date.now() + 30000).toUTCString(), + }, + }, }; } @@ -46,13 +49,14 @@ await test((mockPool) => { statusCode: 200, data: { id: mockInstallationId, - "app_slug": mockAppSlug + app_slug: mockAppSlug, }, responseOptions: { headers: { - "content-type": "application/json" - } - } + "content-type": "application/json", + }, + }, }; - }).times(2); + }) + .times(2); }); diff --git a/tests/main-token-get-owner-set-fail-response.test.js b/tests/main-token-get-owner-set-fail-response.test.js index 90408ba..b07db09 100644 --- a/tests/main-token-get-owner-set-fail-response.test.js +++ b/tests/main-token-get-owner-set-fail-response.test.js @@ -1,4 +1,4 @@ -import { test } from "./main.js"; +import { test, getLogOnceOnPath } from "./main.js"; // Verify retries work when getting a token for a user or organization fails on the first attempt. await test((mockPool) => { @@ -10,7 +10,7 @@ await test((mockPool) => { const mockAppSlug = "github-actions"; mockPool .intercept({ - path: `/users/${process.env.INPUT_OWNER}/installation`, + path: getLogOnceOnPath(`/users/smockle/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -21,7 +21,7 @@ await test((mockPool) => { .reply(500, "GitHub API not available"); mockPool .intercept({ - path: `/users/${process.env.INPUT_OWNER}/installation`, + path: getLogOnceOnPath(`/users/smockle/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -32,6 +32,6 @@ await test((mockPool) => { .reply( 200, { id: mockInstallationId, app_slug: mockAppSlug }, - { headers: { "content-type": "application/json" } } + { headers: { "content-type": "application/json" } }, ); }); diff --git a/tests/main-token-get-owner-set-repo-fail-response.test.js b/tests/main-token-get-owner-set-repo-fail-response.test.js index f97cf26..23e0c5f 100644 --- a/tests/main-token-get-owner-set-repo-fail-response.test.js +++ b/tests/main-token-get-owner-set-repo-fail-response.test.js @@ -1,4 +1,4 @@ -import { test } from "./main.js"; +import { test, getLogOnceOnPath } from "./main.js"; // Verify `main` retry when the GitHub API returns a 500 error. await test((mockPool) => { @@ -11,7 +11,7 @@ await test((mockPool) => { mockPool .intercept({ - path: `/repos/${owner}/${repo}/installation`, + path: getLogOnceOnPath(`/repos/${owner}/${repo}/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -23,7 +23,7 @@ await test((mockPool) => { mockPool .intercept({ - path: `/repos/${owner}/${repo}/installation`, + path: getLogOnceOnPath(`/repos/${owner}/${repo}/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -33,7 +33,7 @@ await test((mockPool) => { }) .reply( 200, - { id: mockInstallationId, "app_slug": mockAppSlug }, - { headers: { "content-type": "application/json" } } + { id: mockInstallationId, app_slug: mockAppSlug }, + { headers: { "content-type": "application/json" } }, ); }); diff --git a/tests/main-token-get-owner-set-repo-unset.test.js b/tests/main-token-get-owner-set-repo-unset.test.js index 1c06512..fa11531 100644 --- a/tests/main-token-get-owner-set-repo-unset.test.js +++ b/tests/main-token-get-owner-set-repo-unset.test.js @@ -1,4 +1,4 @@ -import { test } from "./main.js"; +import { test, getLogOnceOnPath } from "./main.js"; // Verify `main` successfully obtains a token when the `owner` input is set, and the `repositories` input isn’t set. await test((mockPool) => { @@ -10,7 +10,7 @@ await test((mockPool) => { const mockAppSlug = "github-actions"; mockPool .intercept({ - path: `/users/${process.env.INPUT_OWNER}/installation`, + path: getLogOnceOnPath(`/users/${process.env.INPUT_OWNER}/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -21,6 +21,6 @@ await test((mockPool) => { .reply( 200, { id: mockInstallationId, app_slug: mockAppSlug }, - { headers: { "content-type": "application/json" } } + { headers: { "content-type": "application/json" } }, ); }); diff --git a/tests/main-token-get-owner-unset-repo-unset.test.js b/tests/main-token-get-owner-unset-repo-unset.test.js index e284aae..59c8adb 100644 --- a/tests/main-token-get-owner-unset-repo-unset.test.js +++ b/tests/main-token-get-owner-unset-repo-unset.test.js @@ -1,4 +1,4 @@ -import { test } from "./main.js"; +import { test, getLogOnceOnPath } from "./main.js"; // Verify `main` successfully obtains a token when neither the `owner` nor `repositories` input is set. await test((mockPool) => { @@ -10,7 +10,9 @@ await test((mockPool) => { const mockAppSlug = "github-actions"; mockPool .intercept({ - path: `/repos/${process.env.GITHUB_REPOSITORY}/installation`, + path: getLogOnceOnPath( + `/repos/${process.env.GITHUB_REPOSITORY}/installation`, + ), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -20,7 +22,7 @@ await test((mockPool) => { }) .reply( 200, - { id: mockInstallationId, "app_slug": mockAppSlug }, - { headers: { "content-type": "application/json" } } + { id: mockInstallationId, app_slug: mockAppSlug }, + { headers: { "content-type": "application/json" } }, ); }); diff --git a/tests/main.js b/tests/main.js index 4650978..1548823 100644 --- a/tests/main.js +++ b/tests/main.js @@ -63,17 +63,9 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { (env.INPUT_REPOSITORIES ?? currentRepoName).split(",")[0], ); - const getInstallationPath = `${basePath}/repos/${owner}/${repo}/installation`; - - const logGetInstallationRequest = once((pathString) => - console.log(`\nGET ${pathString}\n`), - ); mockPool .intercept({ - path(pathString) { - logGetInstallationRequest(pathString); - return pathString === getInstallationPath; - }, + path: getLogOnceOnPath(`${basePath}/repos/${owner}/${repo}/installation`), method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -93,7 +85,11 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { const mockExpiresAt = "2016-07-11T22:14:10Z"; const createInstallationAccessTokenPath = `${basePath}/app/installations/${mockInstallationId}/access_tokens`; const logCreateInstallationAccessTokenRequest = once((path, payload) => { - console.log(`\nPOST ${path}\n${JSON.stringify(payload, null, 2)}\n`); + console.log( + `\nPOST ${path}\n${ + payload ? JSON.stringify(payload, null, 2) : "" + }\n`, + ); }); mockPool .intercept({ @@ -140,3 +136,14 @@ export function once(fn) { } }; } + +export function getLogOnceOnPath(expectedPath) { + const logOnce = once((path) => { + console.log(`\nGET ${path}\n`); + }); + + return (path) => { + logOnce(path); + return path === expectedPath; + }; +} diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 1472fbd..3a1538e 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -122,6 +122,9 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/failed-repo/installation␊ ␊ ␊ + GET /repos/actions/failed-repo/installation␊ + ␊ + ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"failed-repo\\"]}"␊ ␊ @@ -147,10 +150,16 @@ Generated by [AVA](https://avajs.dev). ␊ GET /users/smockle/installation␊ ␊ + ␊ + GET /users/smockle/installation␊ + ␊ + ␊ + GET /users/smockle/installation␊ + ␊ Failed to create token for "smockle" (attempt 1): GitHub API not available␊ ␊ POST /app/installations/123456/access_tokens␊ - null␊ + ␊ ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ @@ -174,6 +183,12 @@ Generated by [AVA](https://avajs.dev). ␊ GET /repos/actions/failed-repo/installation␊ ␊ + ␊ + GET /repos/actions/failed-repo/installation␊ + ␊ + ␊ + GET /repos/actions/failed-repo/installation␊ + ␊ RequestError [HttpError]: GitHub API not available␊ at file:///Users/gregor/code/actions/create-github-app-token/node_modules/@octokit/request/dist-bundle/index.js:106:21␊ at process.processTicksAndRejections (node:internal/process/task_queues:95:5)␊ @@ -306,8 +321,11 @@ Generated by [AVA](https://avajs.dev). GET /users/actions/installation␊ ␊ ␊ + GET /users/actions/installation␊ + ␊ + ␊ POST /app/installations/123456/access_tokens␊ - null␊ + ␊ ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ @@ -358,6 +376,9 @@ Generated by [AVA](https://avajs.dev). GET /repos/actions/create-github-app-token/installation␊ ␊ ␊ + GET /repos/actions/create-github-app-token/installation␊ + ␊ + ␊ POST /app/installations/123456/access_tokens␊ "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ ␊ diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index d023c69ff99004d241d6ddc1dea8a9ef115d8152..4ffaf0bd3f9c16db6aefef95e5263ec6654017bf 100644 GIT binary patch literal 1957 zcmV;W2U_?+RzV@(=-Tf zN}57T9GUU%u|4(f%ywqhsi}gl0P)5P0^YfQ8V~#jyu-|{?cF3!(m3I^T<0a5-Pv=# zbLRWboXpNYx}8w?1NHYWP%|CkYoNYng1Z665`C&Ma2byit*RQ8uD(=EaT=?>(CYVJ z1Oe6b=U-d8yJUXue0}MgOBm7)hFzrtlrkOg;ttIZS>C@xz z1j++AW?={&1c{LtVgQT-g>Iq~i7-T|nBY}-rqJ4Otqra;(x6(3B^y$W?E#KbFS#4@ zxylT=siCnyHDGaDivjYs#Gx2q>h;X+`FtC5t~KXQ%w-6sX%~qe&t*BHjJtlKw20gu z)BU95(wMo44Ck25<)AQ|&z8k8M`=Tm7z@R;kPHQZuSlDm~eII<-LKxbR$g z^+t1bZQY~3k4mKzr%L5Ft#Tf7t4t1Cvv9Y{M+7Fx;A-Ph zW3%C}Z`K>z8yoeSf4_OZxw^51^^N7$@qx0OI2UL~(>QSTs6Ss*^>Krfsp@Na(0zUOg+#J_#tHxtT>En=iWqel*2C9*hAX|NL0vEhV~IO zix705YWo*e3Z+R498(3%8m^WOe226W2(S5^*BiLd3angaUC%dT$BM3E88l&uQ zi4d@E7cJ{MBWTt@p)Yu#s<4k*jtl}*%us1CsH>`6_7-kAwi7FOc z;XI4ZUkb$j!}67v8XAU0TAQ0aHbf4oILay#{vgCLpA&^rdD+c#IXvHpN0yal#ZMQN z9M%aGSfN^D6l_T=^dbs)2i%T_6$w0IH$OLL{E&J+sp6N$d&f`69qeyGbqr zY)2wULR8*l;m;OoFJMZ$orDKg=mEa2zEq@MTPKbB*mW$0(P1_FeZc&I+Ty`JzQoiu ztQa4JagCDG(8~sTnyNwjRe}jBvbjdq?u{){HR3+>g&4rfO$RpaXwt~cm}y+i`X;I0 zKLw+Q`oP$GBt^8JYv!*HEMy(e=*XsWeU&t7r(D{0X)i`;X;E!=`HkfvcBL^sjd^Xu z_=h(o08<+hMPRK~tCV2es}cJQAVS?20Rd-c`@pH#TZs$_IDM^SMLe_JQ%#*$eGy%e z^O>bS(g39z`vTJpVyubXa}1ep$9h8^j6DpSAH7tQ*8v=}Cb_hSTs!8ii*qu0&9Fg8 z_FHS8fYU)LQNrQ=_QS1D54Im3IduuXaSj1AF@jw#+P!AHhi} zGcYcU<0x+~eWzwFpU(`sDXV7gW|R?Uj4@l7KTDzxN&@v1w>E|JXV}#Qnx&Hq*Z4xQ zy^VE#(F}j79l++r9e}ye!i^{&jdx?_>5D%v^Z~DKWe>cfg$M^sSNuNuga3wluEc#YU)ldrbEW9MczszCA*J zbTOe5u29dzeZ+B-$tbX#sr+u0j;Ge#_S+ujdqT1HN)?L5?cQK05evod>@ zlj;2_{jOMF8J~OwO)acU7`yo3`4yzIdl{YQuC;$I5c+rT{%k0sM+|7VPoFl=Yry6H2CG-#Di z77DmE1vs%#Iy+gL3E_sm8$NFoPN)5VkYg%2<2^#`Cmb+N({BloZWt3d|CphLm|{yq zoPGZBa#ZUDR4XZz%xneBY2$dR#3{sc4-Msj%~dg;e^>zZ!8AVu3@*)y#XMI|epGP( r-80i;jw5AW&PDU>9GW@XhUecaVEIOhg-wcO!T)~%q-t3$$u9r^mIuS! literal 1926 zcmV;12YL8GRzV ztvK)(0C)CJ(laNk^fpsqFbXR}x zd#}FtUZuMJ((8u8AF4lpgPQ3O-vISB6Wk3jlIT;7fy;OlYgN^#boG^Diql99gjT=* zCJ3mezy4t9!IJq|{?5{OmoTJV40}okC}lF>0yMFwhAir6F+|>xI2J=ptX{ZX%(j7ZEu1@rOBu|?D% z58|#%Bj(03EHIlZL2fpmuZRA|xZ0*#{FbLG_= z&9(InkNQ3;l}wx}Id9uemUG)7N9}pM+s^TsQz{WcgTNh8H6)}zP@Ve57n``&*llbz z{Ee-8V`p=-Uh^L{A2ruDx3RwY=<_vd-cqPt5$h<{!08BoW-*IFWIc3QKuF@`WkZb@ zDvbMtOx#MMYlhM>x=K@xwxYd7sjrcG?YEZ-`eQ5T z5mSoszMEwITqVC)&+2r!yl=`FNPHbLnWi2W8dMxbA;W+`f_I7J=jB9(*$;BeY(~r{ zwwEKewYPuxvq)Bu9~4i0QS_^gc6YZX499C7kiwJz;v_qVj2k zfy?nEWE_h$(UoVpvio>m*|jqrA!`$tZYe_JZ=D;1l1pv&Ngl#O7u%&0CuoTeP*u+KI2(XIj{D&&bm2MC&t z5cGg*`xjLTr3nk1PzB5aS4&5~5WW^erac<#fziV;>@oc$?!xxd{RF}!ggR9kN9o@Z zAz-~8TGe+?p;-fkzTknXLJPG#H4IEKL#4rFttBvd#YdpNFJf+%Yds;Wm*!?87m81c zEs1)Rg&5cwxMCTUPsz+X_mGAe^hN63=K?2bBgqoKZ^#=RxyB7M1+GLD39hh68`;fC zb#vv$&4Y$vUa00~pN)}2B6mlPgg*>%qR?2OR9<@XoGN#%qD=oyN_@u76b4qQ);NkZ z)E|;;o*R~QOj$^~A^wK~=W!S=)Nh8^jQb;&@ zqIG01kFO9g007m{V<8gH^PbzZ=}YVj>G>kSYu8;|1lSpgAP!M^(-xVwG%sLEyWN-v zHVFfKQ+=gKy|zIb^@-_73X>z%^!Fk2hiaP#EqsNEX;?Kj2;&+hr=gb)^fXn&&g&Rs zRAg(NtUsI}QgzCG7zi5`f9ySP@vS)hZ>JtZImT z1~5WB5CMVm-p*mUVsFJVBv2k`9Vz0Ojge|%yy}b54K<%44Uh&X)x;KNF_=*YVADU{^D@w z@p0J>JWIyUB4Wi!;Al7Ie)4Kp#5}OKk73));^YyWl~RC7@tSyfci}rXbJ=*N)J^F# zb2q1qlqVe1ruk(&>Y^l2Pk3un?0$tkO`usiyR!f03gUhA;Kd^IzuKj@uI|$2LJN09 z`RQceqR4vl>s+sXeJ{Jk6)i+KWV+%H&>#NW)f+eR_h2id(sok%_Il#NA_wj>2kJM@ zfra)L+W-I3e(gru7sbl{S2^kLz3Y#J@14>Yg1$dNe|oi`W3EsaIll1EoRGu!ca{X4?PA0Z(hrDe&_7lCi zZaXKEX|(^(MR6E*(k<8InM4}2owG#-+*<~eBcXJ9J~T~)JNoYSB6rGR`6q;&P{|qZ z6JkHFfH9iv^Fy+kOW^Xua+YGkEpc)FDZcAjZRA+3CR9?`3Yasq(JT{Z6fZsck|9>8 zV!Ze`N9w~_e1;fY8xza9P)vTBGylU2(_;?Rq*g9v^Sun4g3bTMk8)f-O1Q9TvCP^3 M7qYWAc8@Lq0Clgs7XSbN From c486f3133f81ae2deabc9681e4e8e3d72ab7c584 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 12:59:37 -0700 Subject: [PATCH 08/18] remove left-over console.log --- lib/main.js | 1 - tests/snapshots/index.js.md | 26 -------------------------- tests/snapshots/index.js.snap | Bin 1957 -> 1541 bytes 3 files changed, 27 deletions(-) diff --git a/lib/main.js b/lib/main.js index b9cb759..3440d9a 100644 --- a/lib/main.js +++ b/lib/main.js @@ -91,7 +91,6 @@ export async function main( ), { onFailedAttempt: (error) => { - console.log(error); core.info( `Failed to create token for "${parsedRepositoryNames.join( ",", diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 3a1538e..287b2f4 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -189,32 +189,6 @@ Generated by [AVA](https://avajs.dev). ␊ GET /repos/actions/failed-repo/installation␊ ␊ - RequestError [HttpError]: GitHub API not available␊ - at file:///Users/gregor/code/actions/create-github-app-token/node_modules/@octokit/request/dist-bundle/index.js:106:21␊ - at process.processTicksAndRejections (node:internal/process/task_queues:95:5)␊ - at async hook (file:///Users/gregor/code/actions/create-github-app-token/node_modules/@octokit/auth-app/dist-node/index.js:319:18)␊ - at async getTokenFromRepository (file:///Users/gregor/code/actions/create-github-app-token/lib/main.js:164:20)␊ - at async RetryOperation._fn (file:///Users/gregor/code/actions/create-github-app-token/node_modules/p-retry/index.js:57:20) {␊ - status: 500,␊ - request: {␊ - method: 'GET',␊ - url: 'https://api.github.com/repos/actions/failed-repo/installation',␊ - headers: {␊ - accept: 'application/vnd.github.v3+json',␊ - 'user-agent': 'actions/create-github-app-token',␊ - authorization: 'bearer [REDACTED]'␊ - },␊ - request: { hook: [Function: bound hook] AsyncFunction }␊ - },␊ - response: {␊ - url: 'https://api.github.com/repos/actions/failed-repo/installation',␊ - status: 500,␊ - headers: {},␊ - data: 'GitHub API not available'␊ - },␊ - attemptNumber: 1,␊ - retriesLeft: 3␊ - }␊ Failed to create token for "failed-repo" (attempt 1): GitHub API not available␊ ␊ POST /app/installations/123456/access_tokens␊ diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 4ffaf0bd3f9c16db6aefef95e5263ec6654017bf..19144801c3994e06a69e55940a6541aef9707b4d 100644 GIT binary patch literal 1541 zcmV+g2KxCyRzVz955K<&0ctMCEI9Z@{5GPIAwW~EIHt4z{K}Xk) zj%5lL`WcUaC;u7n=I_i<1lOx5B>4zCsd4&i--s`?h|3^ zp+50_)C9yKU_I~z%j*(11w!8q+KlEbmI0!*mwMnbZ{ZWGyw znl=uJ9dSR$XfAlhXznerJ_W8r;Se%GB;y1G5+F;+<$xujZKP?V7UO0kOE-WqyCgsh zDO3+N2gr&QDXc<%))>B-bh#Fcp;_?E6@?DijJgwr`FRa2OibMWtF> zUb(PZ!LAEJ!~-V^)`Pm0=3KX&JM}Eyb?fd!t59$p?0I&8Mb~lK9nq++ezXQFwQIHY zn!CDQt!=EWRhQh0%NLhd)~-Nx?c&uHtnLyZZ5GKel8E8}KG2x?Akq=q#B-cD$Vp9A z6vB_%jx!7^&aP^TdteKRC7g`dK?JxT5)R^ube!5!b=6*4v#ZtJTFt4hIMt;uCkpzU z7IZ*_Ahd1AuFq8R{)Mzo=Zjmaj3Ey9BEl2vQ6`ay!q6w+IVi@PAo(m$q?o;7Fw>66 zCbnr1Ti@K;y}oy~v9obw`{vf}_Rj6b_7|UR?4Sg#gn~#&RUrgOBpE7R()gE)C!>lC zs;PRGP1rFAmyXP23iMjp*VKu(X$X62IV=A=n2Yr?6x?LLtm8-$BP z@N5cwpHRp%i7wnU%I?QmWmk_xM(LFuKyJi2P&vM7fEF{W@cE?X<|?+cD*H@T*`AiN z8Vg%=p`UHJzYIbCIak~gB2x807Ln^?5}?H*!LoRMWI0UH7M0Kj{S?4K0F4#e0VGKP zNOrK)|F96iRa#IV3q&+XnU+l5^P~-*uJtLHHibSj>NFpR;z=i75VRF}r8--Mp@zWbAVNk3 z%&mbkpM0#$;pWt&e!6aR;8Np<4GmO zbwmX%VksdAC90lx(v?L;ihG#&xaq@Fn&c8?D8vJwVej(H3RAMea;6pZM0RR^_}%cs zZ_jX{f2!7pna7A?8U~upGXJTy)(^LqI*`l`FdYn+Ie85B$S~Nwsk~e&NyhvxktMeS zZug&1kL|uQu<|L@t%SZl9)>XUz%)HjJ+=pC+Mj9v|E2w2LnqdkSYx z=`%r3PtfllF6f8~ka@KHuA$}EPIJxtglyyW?ohVbE8>h6vt{hFAx*8wQMJt@&D(}F zKS|2$K~2Wz$MQR7eI<0Xy$~ZTjuboFNq7$BY#$}(+_m-xL(t!x{Y|l%37$6-SSb^P z!1X>fqatr9|JhLf_h(=EQ`K*&Zl!Wtx10xcOYa)0{=L=?X;cF^SScQnPA zTO4Bcheb!TS~XZL##9p65>lV>g<~gWo1 r`!^2^kJ{%?dYQ=P^%R?&j}7~88C+h8xsXw@H2VJ=snMJQA}as@h_3I+ literal 1957 zcmV;W2U_?+RzV@(=-Tf zN}57T9GUU%u|4(f%ywqhsi}gl0P)5P0^YfQ8V~#jyu-|{?cF3!(m3I^T<0a5-Pv=# zbLRWboXpNYx}8w?1NHYWP%|CkYoNYng1Z665`C&Ma2byit*RQ8uD(=EaT=?>(CYVJ z1Oe6b=U-d8yJUXue0}MgOBm7)hFzrtlrkOg;ttIZS>C@xz z1j++AW?={&1c{LtVgQT-g>Iq~i7-T|nBY}-rqJ4Otqra;(x6(3B^y$W?E#KbFS#4@ zxylT=siCnyHDGaDivjYs#Gx2q>h;X+`FtC5t~KXQ%w-6sX%~qe&t*BHjJtlKw20gu z)BU95(wMo44Ck25<)AQ|&z8k8M`=Tm7z@R;kPHQZuSlDm~eII<-LKxbR$g z^+t1bZQY~3k4mKzr%L5Ft#Tf7t4t1Cvv9Y{M+7Fx;A-Ph zW3%C}Z`K>z8yoeSf4_OZxw^51^^N7$@qx0OI2UL~(>QSTs6Ss*^>Krfsp@Na(0zUOg+#J_#tHxtT>En=iWqel*2C9*hAX|NL0vEhV~IO zix705YWo*e3Z+R498(3%8m^WOe226W2(S5^*BiLd3angaUC%dT$BM3E88l&uQ zi4d@E7cJ{MBWTt@p)Yu#s<4k*jtl}*%us1CsH>`6_7-kAwi7FOc z;XI4ZUkb$j!}67v8XAU0TAQ0aHbf4oILay#{vgCLpA&^rdD+c#IXvHpN0yal#ZMQN z9M%aGSfN^D6l_T=^dbs)2i%T_6$w0IH$OLL{E&J+sp6N$d&f`69qeyGbqr zY)2wULR8*l;m;OoFJMZ$orDKg=mEa2zEq@MTPKbB*mW$0(P1_FeZc&I+Ty`JzQoiu ztQa4JagCDG(8~sTnyNwjRe}jBvbjdq?u{){HR3+>g&4rfO$RpaXwt~cm}y+i`X;I0 zKLw+Q`oP$GBt^8JYv!*HEMy(e=*XsWeU&t7r(D{0X)i`;X;E!=`HkfvcBL^sjd^Xu z_=h(o08<+hMPRK~tCV2es}cJQAVS?20Rd-c`@pH#TZs$_IDM^SMLe_JQ%#*$eGy%e z^O>bS(g39z`vTJpVyubXa}1ep$9h8^j6DpSAH7tQ*8v=}Cb_hSTs!8ii*qu0&9Fg8 z_FHS8fYU)LQNrQ=_QS1D54Im3IduuXaSj1AF@jw#+P!AHhi} zGcYcU<0x+~eWzwFpU(`sDXV7gW|R?Uj4@l7KTDzxN&@v1w>E|JXV}#Qnx&Hq*Z4xQ zy^VE#(F}j79l++r9e}ye!i^{&jdx?_>5D%v^Z~DKWe>cfg$M^sSNuNuga3wluEc#YU)ldrbEW9MczszCA*J zbTOe5u29dzeZ+B-$tbX#sr+u0j;Ge#_S+ujdqT1HN)?L5?cQK05evod>@ zlj;2_{jOMF8J~OwO)acU7`yo3`4yzIdl{YQuC;$I5c+rT{%k0sM+|7VPoFl=Yry6H2CG-#Di z77DmE1vs%#Iy+gL3E_sm8$NFoPN)5VkYg%2<2^#`Cmb+N({BloZWt3d|CphLm|{yq zoPGZBa#ZUDR4XZz%xneBY2$dR#3{sc4-Msj%~dg;e^>zZ!8AVu3@*)y#XMI|epGP( r-80i;jw5AW&PDU>9GW@XhUecaVEIOhg-wcO!T)~%q-t3$$u9r^mIuS! From 7415eca00a67bad83b83d20aa4fe6efabafddc41 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:27:06 -0700 Subject: [PATCH 09/18] docs(README): `permissions` --- README.md | 68 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a0518e7..25b4cb2 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ jobs: > [!TIP] > The `` is the numeric user ID of the app's bot user, which can be found under `https://api.github.com/users/%5Bbot%5D`. -> +> > For example, we can check at `https://api.github.com/users/dependabot[bot]` to see the user ID of Dependabot is 49699333. > > Alternatively, you can use the [octokit/request-action](https://github.com/octokit/request-action) to get the ID. @@ -195,6 +195,32 @@ jobs: body: "Hello, World!" ``` +### Create a token with specific permissions + +> [!NOTE] +> Selected permissions must be granted to the installation of the specified app and repository owner. Setting a permission that the installation does not have will result in an error. + +```yaml +on: [issues] + +jobs: + hello-world: + runs-on: ubuntu-latest + steps: + - uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: ${{ vars.APP_ID }} + private-key: ${{ secrets.PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + permission-issues: write + - uses: peter-evans/create-or-update-comment@v3 + with: + token: ${{ steps.app-token.outputs.token }} + issue-number: ${{ github.event.issue.number }} + body: "Hello, World!" +``` + ### Create tokens for multiple user or organization accounts You can use a matrix strategy to create tokens for multiple user or organization accounts. @@ -251,23 +277,23 @@ jobs: runs-on: self-hosted steps: - - name: Create GitHub App token - id: create_token - uses: actions/create-github-app-token@v1 - with: - app-id: ${{ vars.GHES_APP_ID }} - private-key: ${{ secrets.GHES_APP_PRIVATE_KEY }} - owner: ${{ vars.GHES_INSTALLATION_ORG }} - github-api-url: ${{ vars.GITHUB_API_URL }} - - - name: Create issue - uses: octokit/request-action@v2.x - with: - route: POST /repos/${{ github.repository }}/issues - title: "New issue from workflow" - body: "This is a new issue created from a GitHub Action workflow." - env: - GITHUB_TOKEN: ${{ steps.create_token.outputs.token }} + - name: Create GitHub App token + id: create_token + uses: actions/create-github-app-token@v1 + with: + app-id: ${{ vars.GHES_APP_ID }} + private-key: ${{ secrets.GHES_APP_PRIVATE_KEY }} + owner: ${{ vars.GHES_INSTALLATION_ORG }} + github-api-url: ${{ vars.GITHUB_API_URL }} + + - name: Create issue + uses: octokit/request-action@v2.x + with: + route: POST /repos/${{ github.repository }}/issues + title: "New issue from workflow" + body: "This is a new issue created from a GitHub Action workflow." + env: + GITHUB_TOKEN: ${{ steps.create_token.outputs.token }} ``` ## Inputs @@ -309,6 +335,12 @@ steps: > [!NOTE] > If `owner` is set and `repositories` is empty, access will be scoped to all repositories in the provided repository owner's installation. If `owner` and `repositories` are empty, access will be scoped to only the current repository. +### `permission-` + +**Optional:** The permission level to grant to the token. By default, the token inherits all the installation's permissions. We recommend to explicitly list the permissions that are required for a use case. This follow's GitHub's own recommendation to [control permissions of `GITHUB_TOKEN` in workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token). The documentation also lists all available permissions, just replace e.g. `pull-requests` with `permission-pull-requests`. + +The reason we define one `permision-` input per permission is to benefit from type intelligence and input validation built into GitHub's action runner. + ### `skip-token-revoke` **Optional:** If truthy, the token will not be revoked when the current job is complete. From ba95655bdf1e8c41340f563e70f0a0c1bb42d372 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:39:34 -0700 Subject: [PATCH 10/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 25b4cb2..56f9cc8 100644 --- a/README.md +++ b/README.md @@ -337,7 +337,7 @@ steps: ### `permission-` -**Optional:** The permission level to grant to the token. By default, the token inherits all the installation's permissions. We recommend to explicitly list the permissions that are required for a use case. This follow's GitHub's own recommendation to [control permissions of `GITHUB_TOKEN` in workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token). The documentation also lists all available permissions, just replace e.g. `pull-requests` with `permission-pull-requests`. +**Optional:** The permissions to grant to the token. By default, the token inherits all of the installation's permissions. We recommend to explicitly list the permissions that are required for a use case. This follows GitHub's own recommendation to [control permissions of `GITHUB_TOKEN` in workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token). The documentation also lists all available permissions, just replace e.g. `pull-requests` with `permission-pull-requests`. The reason we define one `permision-` input per permission is to benefit from type intelligence and input validation built into GitHub's action runner. From 6d291e55e794edd9a08a825fc8c74fbddd3d0506 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:11:29 -0700 Subject: [PATCH 11/18] use undici call history to log out mocked calls --- README.md | 4 + main.js | 2 +- package-lock.json | 12 +- package.json | 2 +- tests/README.md | 11 ++ tests/main-repo-skew.test.js | 4 +- ...-token-get-owner-set-fail-response.test.js | 6 +- ...n-get-owner-set-repo-fail-response.test.js | 6 +- ...ain-token-get-owner-set-repo-unset.test.js | 4 +- ...n-token-get-owner-unset-repo-unset.test.js | 6 +- tests/main.js | 63 ++---- tests/snapshots/index.js.md | 180 ++++++------------ tests/snapshots/index.js.snap | Bin 1541 -> 1511 bytes 13 files changed, 118 insertions(+), 182 deletions(-) diff --git a/README.md b/README.md index 56f9cc8..8f47f14 100644 --- a/README.md +++ b/README.md @@ -376,6 +376,10 @@ The action creates an installation access token using [the `POST /app/installati > [!NOTE] > Installation permissions can differ from the app's permissions they belong to. Installation permissions are set when an app is installed on an account. When the app adds more permissions after the installation, an account administrator will have to approve the new permissions before they are set on the installation. +## Contributing + +[CONTRIBUTING.md](CONTRIBUTING.md) + ## License [MIT](LICENSE) diff --git a/main.js b/main.js index 24b9968..8d8d8b7 100644 --- a/main.js +++ b/main.js @@ -55,7 +55,7 @@ function getPermissionsFromInputs(env) { const permissions = getPermissionsFromInputs(process.env); -main( +export default main( appId, privateKey, owner, diff --git a/package-lock.json b/package-lock.json index cae4ed5..6b79dc6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "create-github-app-token", - "version": "1.11.5", + "version": "1.11.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "create-github-app-token", - "version": "1.11.5", + "version": "1.11.6", "license": "MIT", "dependencies": { "@actions/core": "^1.11.1", "@octokit/auth-app": "^7.1.5", "@octokit/request": "^9.2.2", "p-retry": "^6.2.1", - "undici": "^7.4.0" + "undici": "^7.5.0" }, "devDependencies": { "@octokit/openapi": "^18.0.0", @@ -3650,9 +3650,9 @@ } }, "node_modules/undici": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.4.0.tgz", - "integrity": "sha512-PUQM3/es3noM24oUn10u3kNNap0AbxESOmnssmW+dOi9yGwlUSi5nTNYl3bNbTkWOF8YZDkx2tCmj9OtQ3iGGw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.5.0.tgz", + "integrity": "sha512-NFQG741e8mJ0fLQk90xKxFdaSM7z4+IQpAgsFI36bCDY9Z2+aXXZjVy2uUksMouWfMI9+w5ejOq5zYYTBCQJDQ==", "license": "MIT", "engines": { "node": ">=20.18.1" diff --git a/package.json b/package.json index 33e103f..eb074a0 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@octokit/auth-app": "^7.1.5", "@octokit/request": "^9.2.2", "p-retry": "^6.2.1", - "undici": "^7.4.0" + "undici": "^7.5.0" }, "devDependencies": { "@octokit/openapi": "^18.0.0", diff --git a/tests/README.md b/tests/README.md index b50533b..9e61bca 100644 --- a/tests/README.md +++ b/tests/README.md @@ -17,3 +17,14 @@ or with npm ``` npm test ``` + +## How the tests work + +The output from the tests is captured into a snapshot ([tests/snapshots/index.js.md](snapshots/index.js.md)). It includes all requests sent by our scripts to verify it's working correctly and to prevent regressions. + +## How to add a new test + +We have tests both for the `main.js` and `post.js` scripts. + +- If you do not expect an error, take [main-token-permissions-set.test.js](tests/main-token-permissions-set.test.js) as a starting point. +- If your test has an expected error, take [main-missing-app-id.test.js](tests/main-missing-app-id.test.js) as a starting point. diff --git a/tests/main-repo-skew.test.js b/tests/main-repo-skew.test.js index e0bc921..5905558 100644 --- a/tests/main-repo-skew.test.js +++ b/tests/main-repo-skew.test.js @@ -1,4 +1,4 @@ -import { test, getLogOnceOnPath } from "./main.js"; +import { test } from "./main.js"; import { install } from "@sinonjs/fake-timers"; @@ -15,7 +15,7 @@ await test((mockPool) => { mockPool .intercept({ - path: getLogOnceOnPath(`/repos/${owner}/${repo}/installation`), + path: `/repos/${owner}/${repo}/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", diff --git a/tests/main-token-get-owner-set-fail-response.test.js b/tests/main-token-get-owner-set-fail-response.test.js index b07db09..35f8908 100644 --- a/tests/main-token-get-owner-set-fail-response.test.js +++ b/tests/main-token-get-owner-set-fail-response.test.js @@ -1,4 +1,4 @@ -import { test, getLogOnceOnPath } from "./main.js"; +import { test } from "./main.js"; // Verify retries work when getting a token for a user or organization fails on the first attempt. await test((mockPool) => { @@ -10,7 +10,7 @@ await test((mockPool) => { const mockAppSlug = "github-actions"; mockPool .intercept({ - path: getLogOnceOnPath(`/users/smockle/installation`), + path: `/users/smockle/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -21,7 +21,7 @@ await test((mockPool) => { .reply(500, "GitHub API not available"); mockPool .intercept({ - path: getLogOnceOnPath(`/users/smockle/installation`), + path: `/users/smockle/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", diff --git a/tests/main-token-get-owner-set-repo-fail-response.test.js b/tests/main-token-get-owner-set-repo-fail-response.test.js index 23e0c5f..d54d1ab 100644 --- a/tests/main-token-get-owner-set-repo-fail-response.test.js +++ b/tests/main-token-get-owner-set-repo-fail-response.test.js @@ -1,4 +1,4 @@ -import { test, getLogOnceOnPath } from "./main.js"; +import { test } from "./main.js"; // Verify `main` retry when the GitHub API returns a 500 error. await test((mockPool) => { @@ -11,7 +11,7 @@ await test((mockPool) => { mockPool .intercept({ - path: getLogOnceOnPath(`/repos/${owner}/${repo}/installation`), + path: `/repos/${owner}/${repo}/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -23,7 +23,7 @@ await test((mockPool) => { mockPool .intercept({ - path: getLogOnceOnPath(`/repos/${owner}/${repo}/installation`), + path: `/repos/${owner}/${repo}/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", diff --git a/tests/main-token-get-owner-set-repo-unset.test.js b/tests/main-token-get-owner-set-repo-unset.test.js index fa11531..0ce2b18 100644 --- a/tests/main-token-get-owner-set-repo-unset.test.js +++ b/tests/main-token-get-owner-set-repo-unset.test.js @@ -1,4 +1,4 @@ -import { test, getLogOnceOnPath } from "./main.js"; +import { test } from "./main.js"; // Verify `main` successfully obtains a token when the `owner` input is set, and the `repositories` input isn’t set. await test((mockPool) => { @@ -10,7 +10,7 @@ await test((mockPool) => { const mockAppSlug = "github-actions"; mockPool .intercept({ - path: getLogOnceOnPath(`/users/${process.env.INPUT_OWNER}/installation`), + path: `/users/${process.env.INPUT_OWNER}/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", diff --git a/tests/main-token-get-owner-unset-repo-unset.test.js b/tests/main-token-get-owner-unset-repo-unset.test.js index 59c8adb..697f193 100644 --- a/tests/main-token-get-owner-unset-repo-unset.test.js +++ b/tests/main-token-get-owner-unset-repo-unset.test.js @@ -1,4 +1,4 @@ -import { test, getLogOnceOnPath } from "./main.js"; +import { test } from "./main.js"; // Verify `main` successfully obtains a token when neither the `owner` nor `repositories` input is set. await test((mockPool) => { @@ -10,9 +10,7 @@ await test((mockPool) => { const mockAppSlug = "github-actions"; mockPool .intercept({ - path: getLogOnceOnPath( - `/repos/${process.env.GITHUB_REPOSITORY}/installation`, - ), + path: `/repos/${process.env.GITHUB_REPOSITORY}/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", diff --git a/tests/main.js b/tests/main.js index 1548823..d0f5849 100644 --- a/tests/main.js +++ b/tests/main.js @@ -47,7 +47,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { // Set up mocking const baseUrl = new URL(env["INPUT_GITHUB-API-URL"]); const basePath = baseUrl.pathname === "/" ? "" : baseUrl.pathname; - const mockAgent = new MockAgent(); + const mockAgent = new MockAgent({ enableCallHistory: true }); mockAgent.disableNetConnect(); setGlobalDispatcher(mockAgent); const mockPool = mockAgent.get(baseUrl.origin); @@ -65,7 +65,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { mockPool .intercept({ - path: getLogOnceOnPath(`${basePath}/repos/${owner}/${repo}/installation`), + path: `${basePath}/repos/${owner}/${repo}/installation`, method: "GET", headers: { accept: "application/vnd.github.v3+json", @@ -83,31 +83,16 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { const mockInstallationAccessToken = "ghs_16C7e42F292c6912E7710c838347Ae178B4a"; // This token is invalidated. It’s from https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app. const mockExpiresAt = "2016-07-11T22:14:10Z"; - const createInstallationAccessTokenPath = `${basePath}/app/installations/${mockInstallationId}/access_tokens`; - const logCreateInstallationAccessTokenRequest = once((path, payload) => { - console.log( - `\nPOST ${path}\n${ - payload ? JSON.stringify(payload, null, 2) : "" - }\n`, - ); - }); + mockPool .intercept({ - path: createInstallationAccessTokenPath, + path: `${basePath}/app/installations/${mockInstallationId}/access_tokens`, method: "POST", headers: { accept: "application/vnd.github.v3+json", "user-agent": "actions/create-github-app-token", // Note: Intentionally omitting the `authorization` header, since JWT creation is not idempotent. }, - // log out payload for output snapshot testing - body(payload) { - logCreateInstallationAccessTokenRequest( - createInstallationAccessTokenPath, - payload, - ); - return true; - }, }) .reply( 201, @@ -119,31 +104,23 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { cb(mockPool); // Run the main script - await import("../main.js"); -} + const { default: promise } = await import("../main.js"); + try { + await promise; + } catch (errer) { + throw error; + } -/** - * Undici seems to invoke the `path()` and `body()` callbacks twice, - * which results in us logging the requests twice. This helper ensures - * we only log the request once. - */ -export function once(fn) { - let called = false; - return (...args) => { - if (!called) { - called = true; - return fn(...args); - } - }; -} + console.log("--- REQUESTS ---"); + const calls = mockAgent + .getCallHistory() + .calls() + .map((call) => { + const route = `${call.method} ${call.path}`; + if (call.method === "GET") return route; -export function getLogOnceOnPath(expectedPath) { - const logOnce = once((path) => { - console.log(`\nGET ${path}\n`); - }); + return `${route}\n${call.body}`; + }); - return (path) => { - logOnce(path); - return path === expectedPath; - }; + console.log(calls.join("\n")); } diff --git a/tests/snapshots/index.js.md b/tests/snapshots/index.js.md index 287b2f4..f085f87 100644 --- a/tests/snapshots/index.js.md +++ b/tests/snapshots/index.js.md @@ -25,13 +25,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ - ␊ - GET /api/v3/repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /api/v3/app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -40,7 +33,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /api/v3/repos/actions/create-github-app-token/installation␊ + POST /api/v3/app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token"]}` ## main-missing-app-id.test.js @@ -91,13 +88,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -106,7 +96,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token"]}` ## main-repo-skew.test.js @@ -118,16 +112,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ - ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ - ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"failed-repo\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -136,7 +120,12 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/failed-repo/installation␊ + GET /repos/actions/failed-repo/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["failed-repo"]}` ## main-token-get-owner-set-fail-response.test.js @@ -147,20 +136,7 @@ Generated by [AVA](https://avajs.dev). > stdout `repositories not set, creating token for all repositories for given owner "smockle"␊ - ␊ - GET /users/smockle/installation␊ - ␊ - ␊ - GET /users/smockle/installation␊ - ␊ - ␊ - GET /users/smockle/installation␊ - ␊ Failed to create token for "smockle" (attempt 1): GitHub API not available␊ - ␊ - POST /app/installations/123456/access_tokens␊ - ␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -169,7 +145,12 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /users/smockle/installation␊ + GET /users/smockle/installation␊ + POST /app/installations/123456/access_tokens␊ + null` ## main-token-get-owner-set-repo-fail-response.test.js @@ -180,20 +161,7 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories set, creating token for repositories "failed-repo" owned by "actions"␊ - ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ - ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ - ␊ - GET /repos/actions/failed-repo/installation␊ - ␊ Failed to create token for "failed-repo" (attempt 1): GitHub API not available␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"failed-repo\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -202,7 +170,12 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/failed-repo/installation␊ + GET /repos/actions/failed-repo/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["failed-repo"]}` ## main-token-get-owner-set-repo-set-to-many-newline.test.js @@ -213,13 +186,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -228,7 +194,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token","toolkit","checkout"]}` ## main-token-get-owner-set-repo-set-to-many.test.js @@ -239,13 +209,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories set, creating token for repositories "create-github-app-token,toolkit,checkout" owned by "actions"␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\",\\"toolkit\\",\\"checkout\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -254,7 +217,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token","toolkit","checkout"]}` ## main-token-get-owner-set-repo-set-to-one.test.js @@ -265,13 +232,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories set, creating token for repositories "create-github-app-token" owned by "actions"␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -280,7 +240,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token"]}` ## main-token-get-owner-set-repo-unset.test.js @@ -291,16 +255,6 @@ Generated by [AVA](https://avajs.dev). > stdout `repositories not set, creating token for all repositories for given owner "actions"␊ - ␊ - GET /users/actions/installation␊ - ␊ - ␊ - GET /users/actions/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - ␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -309,7 +263,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /users/actions/installation␊ + POST /app/installations/123456/access_tokens␊ + null` ## main-token-get-owner-unset-repo-set.test.js @@ -320,13 +278,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner not set, creating owner for given repositories "create-github-app-token" in current owner ("actions")␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -335,7 +286,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token"]}` ## main-token-get-owner-unset-repo-unset.test.js @@ -346,16 +301,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"]}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -364,7 +309,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token"]}` ## main-token-permissions-set.test.js @@ -375,13 +324,6 @@ Generated by [AVA](https://avajs.dev). > stdout `owner and repositories not set, creating token for the current repository ("create-github-app-token")␊ - ␊ - GET /repos/actions/create-github-app-token/installation␊ - ␊ - ␊ - POST /app/installations/123456/access_tokens␊ - "{\\"repositories\\":[\\"create-github-app-token\\"],\\"permissions\\":{\\"issues\\":\\"write\\",\\"pull_requests\\":\\"read\\"}}"␊ - ␊ ::add-mask::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ ␊ ::set-output name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ @@ -390,7 +332,11 @@ Generated by [AVA](https://avajs.dev). ␊ ::set-output name=app-slug::github-actions␊ ::save-state name=token::ghs_16C7e42F292c6912E7710c838347Ae178B4a␊ - ::save-state name=expiresAt::2016-07-11T22:14:10Z` + ::save-state name=expiresAt::2016-07-11T22:14:10Z␊ + --- REQUESTS ---␊ + GET /repos/actions/create-github-app-token/installation␊ + POST /app/installations/123456/access_tokens␊ + {"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull_requests":"read"}}` ## post-revoke-token-fail-response.test.js diff --git a/tests/snapshots/index.js.snap b/tests/snapshots/index.js.snap index 19144801c3994e06a69e55940a6541aef9707b4d..2291b3afed0274a2edb7b728e95da7287556f135 100644 GIT binary patch literal 1511 zcmVR~0A_R(r1n&?-aI%onK`v?1u3fEx*ihG1h;_6b zbQ@E+*iVup&YijEoUEEAA@&Ur;ysi227Dr3@C|suJGir(*lOH%bvq>Hyh@z&bN_qp z_kYgz`PXhIklp})c?O#603H$MX)XozAynWo4L;=}j5O9Ypss(190d!pFE#%7%=ejQ zU%WE++MM~!zdHBU90aTbK^L_TO2rNC&9iiqg`Ig8hHdVXKYsX`RO9be!jVk-Buw~Z z%!7b*fG8Ns5%`1)!bmsLkpeOTgpkjTfs;UAnx_Z;bMK8aMXsQlW>WGY1(C^59iVuGA^hWp_W71cd1))T)rQ(1DLDz_kXeuKeMw$pVgpX|x#X^|8vmjvBE8KV8W@~xn%Id79W=t4FJ=Z-PWIP_z zl#PI*W*W{W>}Ujd6mkW4UAt~;skus*)@ZZ2*J`=V6}P!`zd|V`I~!l#-PqmRC6v<2 z=Efdru#h)K%MCj-jYM7}XJ#7dp;zu~?@rHWVVLNOkx zlj_-|l8n?;S<4sfW(3zx%w#I)*)+bN(Kw;z7>Tzs65S&?Ju#b&Yo?pCCbez_r^Zdk zT=yxU$3pO_fN{VD6j@6b?q{m+=XurF&O}ZH)_oveq!b7}J?Vff=KAn*S$Z$3^cJYO zFQnLxEYT(g#Q}`-o%dIU%RlF;TZoY<3%W|Yfbk(&ta7HSmnY6+f@}#5J+RjV3J^pL zY9EN^Lm;}(wEe{pL7734F+;*_;Cki3r_$4Mz;%N~x^G7EkZf{&E9#KzcedgX#us>i z8ivVl1;ppwE?D?G2V{APAb3*vSSLH6)qzo9Y8s#>#=KU*;VB*v=6Ny_=Hjg@Reh#K zA(M))id`Ue84tj>Gf-X>{ddkxO+(g=&(pS`bJHl~TpGm-P<)TjGdVZtQImahGF5<~ z6bMBYAk5J1FPwVWVL^~(+Z^oi5eO1H#KEET1_3ygn|7pTU5=|&D$1l0S!7znFw~@Z z*-abYXka781J((k^v6Z{BSKKvNM>V(Cyx35xqKj^AehPeaxUw3xjHxCf6oB_+r^gi zy4$r$ftRL?f^F>QKWa8lPR;7qk!LwYaZZge(%7P?7YEkfV78T!6V3hGhp;^R}oPFYF0m~08e z5f&#fff^&LMzTe8cd+~wmj+qi% z^jvq(GHyEcY*I-4tkNa3U!t)RV{P&5<-gr?vZ~dLs>N7J61GOnD|O-2hEs_%_rg=c z3YClfOBqpbO!G4U|HPbF&4qIEVW#_ck4%r*WlwsUspjpJnt~Sq`|oA6ycuiZlS-NC N{~wy7L-4LD002Tg_Xz+1 literal 1541 zcmV+g2KxCyRzVz955K<&0ctMCEI9Z@{5GPIAwW~EIHt4z{K}Xk) zj%5lL`WcUaC;u7n=I_i<1lOx5B>4zCsd4&i--s`?h|3^ zp+50_)C9yKU_I~z%j*(11w!8q+KlEbmI0!*mwMnbZ{ZWGyw znl=uJ9dSR$XfAlhXznerJ_W8r;Se%GB;y1G5+F;+<$xujZKP?V7UO0kOE-WqyCgsh zDO3+N2gr&QDXc<%))>B-bh#Fcp;_?E6@?DijJgwr`FRa2OibMWtF> zUb(PZ!LAEJ!~-V^)`Pm0=3KX&JM}Eyb?fd!t59$p?0I&8Mb~lK9nq++ezXQFwQIHY zn!CDQt!=EWRhQh0%NLhd)~-Nx?c&uHtnLyZZ5GKel8E8}KG2x?Akq=q#B-cD$Vp9A z6vB_%jx!7^&aP^TdteKRC7g`dK?JxT5)R^ube!5!b=6*4v#ZtJTFt4hIMt;uCkpzU z7IZ*_Ahd1AuFq8R{)Mzo=Zjmaj3Ey9BEl2vQ6`ay!q6w+IVi@PAo(m$q?o;7Fw>66 zCbnr1Ti@K;y}oy~v9obw`{vf}_Rj6b_7|UR?4Sg#gn~#&RUrgOBpE7R()gE)C!>lC zs;PRGP1rFAmyXP23iMjp*VKu(X$X62IV=A=n2Yr?6x?LLtm8-$BP z@N5cwpHRp%i7wnU%I?QmWmk_xM(LFuKyJi2P&vM7fEF{W@cE?X<|?+cD*H@T*`AiN z8Vg%=p`UHJzYIbCIak~gB2x807Ln^?5}?H*!LoRMWI0UH7M0Kj{S?4K0F4#e0VGKP zNOrK)|F96iRa#IV3q&+XnU+l5^P~-*uJtLHHibSj>NFpR;z=i75VRF}r8--Mp@zWbAVNk3 z%&mbkpM0#$;pWt&e!6aR;8Np<4GmO zbwmX%VksdAC90lx(v?L;ihG#&xaq@Fn&c8?D8vJwVej(H3RAMea;6pZM0RR^_}%cs zZ_jX{f2!7pna7A?8U~upGXJTy)(^LqI*`l`FdYn+Ie85B$S~Nwsk~e&NyhvxktMeS zZug&1kL|uQu<|L@t%SZl9)>XUz%)HjJ+=pC+Mj9v|E2w2LnqdkSYx z=`%r3PtfllF6f8~ka@KHuA$}EPIJxtglyyW?ohVbE8>h6vt{hFAx*8wQMJt@&D(}F zKS|2$K~2Wz$MQR7eI<0Xy$~ZTjuboFNq7$BY#$}(+_m-xL(t!x{Y|l%37$6-SSb^P z!1X>fqatr9|JhLf_h(=EQ`K*&Zl!Wtx10xcOYa)0{=L=?X;cF^SScQnPA zTO4Bcheb!TS~XZL##9p65>lV>g<~gWo1 r`!^2^kJ{%?dYQ=P^%R?&j}7~88C+h8xsXw@H2VJ=snMJQA}as@h_3I+ From 295849324d2c740cba3ee92fcf2e89a4f5dd034c Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:11:41 -0700 Subject: [PATCH 12/18] docs(CONTRIBUTING); initial version --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..498c372 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +# Contributing + +Initial setup + +``` +npm install +``` + +Run tests locally + +``` +npm test +``` From 1ac56bb62b4e8629665d1cc3cb09b35f309459a4 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:13:35 -0700 Subject: [PATCH 13/18] remove debug code that would notk even work lol --- tests/main.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/main.js b/tests/main.js index d0f5849..2172752 100644 --- a/tests/main.js +++ b/tests/main.js @@ -105,11 +105,7 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) { // Run the main script const { default: promise } = await import("../main.js"); - try { - await promise; - } catch (errer) { - throw error; - } + await promise; console.log("--- REQUESTS ---"); const calls = mockAgent From 12f3940b8953c78633b3a030ab8eb7d1bff85b65 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:15:28 -0700 Subject: [PATCH 14/18] docs(CONTRIBUTING): add link to test/README.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 498c372..d7975ad 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,3 +11,5 @@ Run tests locally ``` npm test ``` + +Learn more about how the tests work in [test/README.md](test/README.md). From ade198147ce92845108e6c247f13ec832c8c7284 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Fri, 21 Mar 2025 15:21:24 -0700 Subject: [PATCH 15/18] refactor: move `getPermissionsFromInputs` into its own file --- lib/get-permissions-from-inputs.js | 23 +++++++++++++++++++++++ main.js | 19 +------------------ 2 files changed, 24 insertions(+), 18 deletions(-) create mode 100644 lib/get-permissions-from-inputs.js diff --git a/lib/get-permissions-from-inputs.js b/lib/get-permissions-from-inputs.js new file mode 100644 index 0000000..7458155 --- /dev/null +++ b/lib/get-permissions-from-inputs.js @@ -0,0 +1,23 @@ +/** + * Finds all permissions passed via `permision-*` inputs and turns them into an object. + * + * @see https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#inputs + * @param {NodeJS.ProcessEnv} env + * @returns {undefined | Record} + */ +export function getPermissionsFromInputs(env) { + return Object.entries(env).reduce((permissions, [key, value]) => { + if (!key.startsWith("INPUT_PERMISSION_")) return permissions; + + const permission = key.slice("INPUT_PERMISSION_".length).toLowerCase(); + if (permissions === undefined) { + return { [permission]: value }; + } + + return { + // @ts-expect-error - needs to be typed correctly + ...permissions, + [permission]: value, + }; + }, undefined); +} diff --git a/main.js b/main.js index 8d8d8b7..d96203d 100644 --- a/main.js +++ b/main.js @@ -5,6 +5,7 @@ import { createAppAuth } from "@octokit/auth-app"; import { main } from "./lib/main.js"; import request from "./lib/request.js"; +import { getPermissionsFromInputs } from "./lib/get-permissions-from-inputs.js"; if (!process.env.GITHUB_REPOSITORY) { throw new Error("GITHUB_REPOSITORY missing, must be set to '/'"); @@ -35,24 +36,6 @@ const skipTokenRevoke = Boolean( core.getInput("skip-token-revoke") || core.getInput("skip_token_revoke"), ); -// @see https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#inputs -function getPermissionsFromInputs(env) { - return Object.entries(env).reduce((permissions, [key, value]) => { - if (!key.startsWith("INPUT_PERMISSION_")) return permissions; - - const permission = key.slice("INPUT_PERMISSION_".length).toLowerCase(); - if (permissions === undefined) { - return { [permission]: value }; - } - - return { - // @ts-expect-error - needs to be typed correctly - ...permissions, - [permission]: value, - }; - }, undefined); -} - const permissions = getPermissionsFromInputs(process.env); export default main( From a4c5901d85227f6b0fa8e89d224668f2f8adf35f Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:59:01 -0700 Subject: [PATCH 16/18] Update README.md Co-authored-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f47f14..91efed1 100644 --- a/README.md +++ b/README.md @@ -337,7 +337,7 @@ steps: ### `permission-` -**Optional:** The permissions to grant to the token. By default, the token inherits all of the installation's permissions. We recommend to explicitly list the permissions that are required for a use case. This follows GitHub's own recommendation to [control permissions of `GITHUB_TOKEN` in workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token). The documentation also lists all available permissions, just replace e.g. `pull-requests` with `permission-pull-requests`. +**Optional:** The permissions to grant to the token. By default, the token inherits all of the installation's permissions. We recommend to explicitly list the permissions that are required for a use case. This follows GitHub's own recommendation to [control permissions of `GITHUB_TOKEN` in workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token). The documentation also lists all available permissions, just prefix the permission key with `permission-` (e.g., `pull-requests` → `permission-pull-requests`). The reason we define one `permision-` input per permission is to benefit from type intelligence and input validation built into GitHub's action runner. From c49eac1d0c46b3cb06b14f4934e9bc30481b35d0 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:59:17 -0700 Subject: [PATCH 17/18] Update CONTRIBUTING.md Co-authored-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7975ad..0257125 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Initial setup -``` +```console npm install ``` From a872a8b5d620e25fed4f5050ba695dcaa00e88c5 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:59:24 -0700 Subject: [PATCH 18/18] Update CONTRIBUTING.md Co-authored-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0257125..566a8fe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ npm install Run tests locally -``` +```console npm test ```