dce3be8b28
Bumps [p-retry](https://github.com/sindresorhus/p-retry) from 6.2.1 to 7.1.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/sindresorhus/p-retry/releases">p-retry's releases</a>.</em></p> <blockquote> <h2>v7.0.0</h2> <h3>Breaking</h3> <ul> <li>Require Node.js 20 3bdb53a</li> <li><code>onFailedAttempt</code> and <code>shouldRetry</code> now receive a <code>context</code> object instead of a decorated <code>error</code> bff36bb <ul> <li>You must now must access the error as <code>object.error</code> instead of <code>object</code>.</li> <li>The use of <code>.attemptNumber</code> and <code>.retriesLeft</code> did not change.</li> </ul> </li> <li>Remove the <code>forever</code> option (<a href="https://redirect.github.com/sindresorhus/p-retry/issues/79">#79</a>) 6a89827 <ul> <li>Many use-cases can use <code>{retries: Infinity}</code> instead for infinite retries.</li> </ul> </li> </ul> <h3>Improvements</h3> <ul> <li>Rewrite the package to not depend on the <code>retry</code> package (<a href="https://redirect.github.com/sindresorhus/p-retry/issues/79">#79</a>) 6a89827 <ul> <li>This is a full rewrite, so test carefully.</li> </ul> </li> <li>Add <a href="https://github.com/sindresorhus/p-retry#makeretriablefunction-options"><code>makeRetriable</code></a> method 1a81c1e</li> </ul> <hr /> <p><a href="https://github.com/sindresorhus/p-retry/compare/v6.2.1...v7.0.0">https://github.com/sindresorhus/p-retry/compare/v6.2.1...v7.0.0</a></p> <h2>v7.0.0-0</h2> <h3>Breaking</h3> <ul> <li>Require Node.js 20 3bdb53a</li> <li><code>onFailedAttempt</code> and <code>shouldRetry</code> now receive a <code>context</code> object instead of a decorated <code>error</code> bff36bb <ul> <li>You must now must access the error as <code>object.error</code> instead of <code>object</code>.</li> <li>The use of <code>.attemptNumber</code> and <code>.retriesLeft</code> did not change.</li> </ul> </li> <li>Remove the <code>forever</code> option (<a href="https://redirect.github.com/sindresorhus/p-retry/issues/79">#79</a>) 6a89827 <ul> <li>Many use-cases can use <code>{retries: Infinity}</code> instead for infinite retries.</li> </ul> </li> </ul> <h3>Improvements</h3> <ul> <li>Rewrite the package to not depend on the <code>retry</code> package (<a href="https://redirect.github.com/sindresorhus/p-retry/issues/79">#79</a>) 6a89827 <ul> <li>This is a full rewrite, so test carefully.</li> </ul> </li> <li>Add <a href="https://github.com/sindresorhus/p-retry?tab=readme-ov-file#makeretriablefunction-options"><code>makeRetriable</code></a> method 1a81c1e</li> </ul> <hr /> <p><a href="https://github.com/sindresorhus/p-retry/compare/v6.2.1...v7.0.0-0">https://github.com/sindresorhus/p-retry/compare/v6.2.1...v7.0.0-0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/sindresorhus/p-retry/commit/e11ca9c9c4a8032182403871593a67a49e948568"><code>e11ca9c</code></a> 7.0.0</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/81608ce107e17b388721ec6377b58e29c52ea55c"><code>81608ce</code></a> Minor tweaks</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/9ef6a73d71c875c06de0090774806eb5ef1b4a7d"><code>9ef6a73</code></a> Clarify <code>shouldRetry</code> documentation (<a href="https://redirect.github.com/sindresorhus/p-retry/issues/93">#93</a>)</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/e05b1017e183db72962fbc8edb5fa1c86d33bc3c"><code>e05b101</code></a> Fix code example typo (<a href="https://redirect.github.com/sindresorhus/p-retry/issues/91">#91</a>)</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/157d06eabbcae7066e8cbf430ad0da759a4ca9a1"><code>157d06e</code></a> 7.0.0-0</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/bff36bb860a8ea8551982cd6bce5a2aaed4135fb"><code>bff36bb</code></a> Stop decorating errors</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/1a81c1e2d25718119d59ce33f9feeceb47a7436a"><code>1a81c1e</code></a> Add <code>makeRetriable</code> method</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/481105165809e0dd47679f5f576a0734bce7bcb9"><code>4811051</code></a> Document mocking</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/777d98f331affb8782eb50bee7d48e7c825224ca"><code>777d98f</code></a> Document signal handling</li> <li><a href="https://github.com/sindresorhus/p-retry/commit/b4e52fcafab4592d353e1901c697f49605193496"><code>b4e52fc</code></a> Add test for async stack traces</li> <li>Additional commits viewable in <a href="https://github.com/sindresorhus/p-retry/compare/v6.2.1...v7.0.0">compare view</a></li> </ul> </details> <br /> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) You can trigger a rebase of this PR by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> > **Note** > Automatic rebases have been disabled on this pull request as it has been open for over 30 days. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com>
184 lines
5.3 KiB
JavaScript
184 lines
5.3 KiB
JavaScript
import pRetry from "p-retry";
|
|
// @ts-check
|
|
|
|
/**
|
|
* @param {string} appId
|
|
* @param {string} privateKey
|
|
* @param {string} owner
|
|
* @param {string[]} repositories
|
|
* @param {undefined | Record<string, string>} permissions
|
|
* @param {import("@actions/core")} core
|
|
* @param {import("@octokit/auth-app").createAppAuth} createAppAuth
|
|
* @param {import("@octokit/request").request} request
|
|
* @param {boolean} skipTokenRevoke
|
|
*/
|
|
export async function main(
|
|
appId,
|
|
privateKey,
|
|
owner,
|
|
repositories,
|
|
permissions,
|
|
core,
|
|
createAppAuth,
|
|
request,
|
|
skipTokenRevoke
|
|
) {
|
|
let parsedOwner = "";
|
|
let parsedRepositoryNames = [];
|
|
|
|
// If neither owner nor repositories are set, default to current repository
|
|
if (!owner && repositories.length === 0) {
|
|
const [owner, repo] = String(process.env.GITHUB_REPOSITORY).split("/");
|
|
parsedOwner = owner;
|
|
parsedRepositoryNames = [repo];
|
|
|
|
core.info(
|
|
`Inputs 'owner' and 'repositories' are not set. Creating token for this repository (${owner}/${repo}).`
|
|
);
|
|
}
|
|
|
|
// If only an owner is set, default to all repositories from that owner
|
|
if (owner && repositories.length === 0) {
|
|
parsedOwner = owner;
|
|
|
|
core.info(
|
|
`Input 'repositories' is not set. Creating token for all repositories owned by ${owner}.`
|
|
);
|
|
}
|
|
|
|
// If repositories are set, but no owner, default to `GITHUB_REPOSITORY_OWNER`
|
|
if (!owner && repositories.length > 0) {
|
|
parsedOwner = String(process.env.GITHUB_REPOSITORY_OWNER);
|
|
parsedRepositoryNames = repositories;
|
|
|
|
core.info(
|
|
`No 'owner' input provided. Using default owner '${parsedOwner}' to create token for the following repositories:${repositories
|
|
.map((repo) => `\n- ${parsedOwner}/${repo}`)
|
|
.join("")}`
|
|
);
|
|
}
|
|
|
|
// If both owner and repositories are set, use those values
|
|
if (owner && repositories.length > 0) {
|
|
parsedOwner = owner;
|
|
parsedRepositoryNames = repositories;
|
|
|
|
core.info(
|
|
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
|
|
${repositories.map((repo) => `\n- ${parsedOwner}/${repo}`).join("")}`
|
|
);
|
|
}
|
|
|
|
const auth = createAppAuth({
|
|
appId,
|
|
privateKey,
|
|
request,
|
|
});
|
|
|
|
let authentication, installationId, appSlug;
|
|
// If at least one repository is set, get installation ID from that repository
|
|
|
|
if (parsedRepositoryNames.length > 0) {
|
|
({ authentication, installationId, appSlug } = await pRetry(
|
|
() =>
|
|
getTokenFromRepository(
|
|
request,
|
|
auth,
|
|
parsedOwner,
|
|
parsedRepositoryNames,
|
|
permissions
|
|
),
|
|
{
|
|
shouldRetry: ({ error }) => error.status >= 500,
|
|
onFailedAttempt: (context) => {
|
|
core.info(
|
|
`Failed to create token for "${parsedRepositoryNames.join(
|
|
","
|
|
)}" (attempt ${context.attemptNumber}): ${context.error.message}`
|
|
);
|
|
},
|
|
retries: 3,
|
|
}
|
|
));
|
|
} 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, permissions),
|
|
{
|
|
onFailedAttempt: (context) => {
|
|
core.info(
|
|
`Failed to create token for "${parsedOwner}" (attempt ${context.attemptNumber}): ${context.error.message}`
|
|
);
|
|
},
|
|
retries: 3,
|
|
}
|
|
));
|
|
}
|
|
|
|
// Register the token with the runner as a secret to ensure it is masked in logs
|
|
core.setSecret(authentication.token);
|
|
|
|
core.setOutput("token", authentication.token);
|
|
core.setOutput("installation-id", installationId);
|
|
core.setOutput("app-slug", appSlug);
|
|
|
|
// Make token accessible to post function (so we can invalidate it)
|
|
if (!skipTokenRevoke) {
|
|
core.saveState("token", authentication.token);
|
|
core.saveState("expiresAt", authentication.expiresAt);
|
|
}
|
|
}
|
|
|
|
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", {
|
|
username: parsedOwner,
|
|
request: {
|
|
hook: auth.hook,
|
|
},
|
|
});
|
|
|
|
// Get token for for all repositories of the given installation
|
|
const authentication = await auth({
|
|
type: "installation",
|
|
installationId: response.data.id,
|
|
permissions,
|
|
});
|
|
|
|
const installationId = response.data.id;
|
|
const appSlug = response.data["app_slug"];
|
|
|
|
return { authentication, installationId, appSlug };
|
|
}
|
|
|
|
async function getTokenFromRepository(
|
|
request,
|
|
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", {
|
|
owner: parsedOwner,
|
|
repo: parsedRepositoryNames[0],
|
|
request: {
|
|
hook: auth.hook,
|
|
},
|
|
});
|
|
|
|
// Get token for given repositories
|
|
const authentication = await auth({
|
|
type: "installation",
|
|
installationId: response.data.id,
|
|
repositoryNames: parsedRepositoryNames,
|
|
permissions,
|
|
});
|
|
|
|
const installationId = response.data.id;
|
|
const appSlug = response.data["app_slug"];
|
|
|
|
return { authentication, installationId, appSlug };
|
|
}
|