Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d72941d797 | |||
| 0e0aa99a86 | |||
| f577941506 | |||
| af35edadc0 | |||
| a24b46a462 | |||
| 21cfef2b49 | |||
| 1ff1dea6a9 |
+1
-1
@@ -1 +1 @@
|
||||
* @gr2m @parkerbxyz @actions/create-github-app-token-maintainers
|
||||
* @actions/create-github-app-token-maintainers
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Contributing
|
||||
|
||||
Initial setup
|
||||
|
||||
```console
|
||||
npm install
|
||||
```
|
||||
|
||||
Run tests locally
|
||||
|
||||
```console
|
||||
npm test
|
||||
```
|
||||
|
||||
Learn more about how the tests work in [test/README.md](test/README.md).
|
||||
@@ -121,7 +121,7 @@ jobs:
|
||||
|
||||
> [!TIP]
|
||||
> The `<BOT USER ID>` is the numeric user ID of the app's bot user, which can be found under `https://api.github.com/users/<app-slug>%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 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 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-<permission name>`
|
||||
|
||||
**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-<permission name>` 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.
|
||||
@@ -344,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)
|
||||
|
||||
+98
@@ -37,6 +37,104 @@ inputs:
|
||||
github-api-url:
|
||||
description: The URL of the GitHub REST API.
|
||||
default: ${{ github.api_url }}
|
||||
# <START GENERATED PERMISSIONS INPUTS>
|
||||
permission-actions:
|
||||
description: "The level of permission to grant the access token for GitHub Actions workflows, workflow runs, and artifacts. Can be set to 'read' or 'write'."
|
||||
permission-administration:
|
||||
description: "The level of permission to grant the access token for repository creation, deletion, settings, teams, and collaborators creation. Can be set to 'read' or 'write'."
|
||||
permission-checks:
|
||||
description: "The level of permission to grant the access token for checks on code. Can be set to 'read' or 'write'."
|
||||
permission-codespaces:
|
||||
description: "The level of permission to grant the access token to create, edit, delete, and list Codespaces. Can be set to 'read' or 'write'."
|
||||
permission-contents:
|
||||
description: "The level of permission to grant the access token for repository contents, commits, branches, downloads, releases, and merges. Can be set to 'read' or 'write'."
|
||||
permission-dependabot-secrets:
|
||||
description: "The leve of permission to grant the access token to manage Dependabot secrets. Can be set to 'read' or 'write'."
|
||||
permission-deployments:
|
||||
description: "The level of permission to grant the access token for deployments and deployment statuses. Can be set to 'read' or 'write'."
|
||||
permission-email-addresses:
|
||||
description: "The level of permission to grant the access token to manage the email addresses belonging to a user. Can be set to 'read' or 'write'."
|
||||
permission-environments:
|
||||
description: "The level of permission to grant the access token for managing repository environments. Can be set to 'read' or 'write'."
|
||||
permission-followers:
|
||||
description: "The level of permission to grant the access token to manage the followers belonging to a user. Can be set to 'read' or 'write'."
|
||||
permission-git-ssh-keys:
|
||||
description: "The level of permission to grant the access token to manage git SSH keys. Can be set to 'read' or 'write'."
|
||||
permission-gpg-keys:
|
||||
description: "The level of permission to grant the access token to view and manage GPG keys belonging to a user. Can be set to 'read' or 'write'."
|
||||
permission-interaction-limits:
|
||||
description: "The level of permission to grant the access token to view and manage interaction limits on a repository. Can be set to 'read' or 'write'."
|
||||
permission-issues:
|
||||
description: "The level of permission to grant the access token for issues and related comments, assignees, labels, and milestones. Can be set to 'read' or 'write'."
|
||||
permission-members:
|
||||
description: "The level of permission to grant the access token for organization teams and members. Can be set to 'read' or 'write'."
|
||||
permission-metadata:
|
||||
description: "The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata. Can be set to 'read' or 'write'."
|
||||
permission-organization-administration:
|
||||
description: "The level of permission to grant the access token to manage access to an organization. Can be set to 'read' or 'write'."
|
||||
permission-organization-announcement-banners:
|
||||
description: "The level of permission to grant the access token to view and manage announcement banners for an organization. Can be set to 'read' or 'write'."
|
||||
permission-organization-copilot-seat-management:
|
||||
description: "The level of permission to grant the access token for managing access to GitHub Copilot for members of an organization with a Copilot Business subscription. This property is in public preview and is subject to change. Can be set to 'write'."
|
||||
permission-organization-custom-org-roles:
|
||||
description: "The level of permission to grant the access token for custom organization roles management. Can be set to 'read' or 'write'."
|
||||
permission-organization-custom-properties:
|
||||
description: "The level of permission to grant the access token for custom property management. Can be set to 'read', 'write', or 'admin'."
|
||||
permission-organization-custom-roles:
|
||||
description: "The level of permission to grant the access token for custom repository roles management. Can be set to 'read' or 'write'."
|
||||
permission-organization-events:
|
||||
description: "The level of permission to grant the access token to view events triggered by an activity in an organization. Can be set to 'read'."
|
||||
permission-organization-hooks:
|
||||
description: "The level of permission to grant the access token to manage the post-receive hooks for an organization. Can be set to 'read' or 'write'."
|
||||
permission-organization-packages:
|
||||
description: "The level of permission to grant the access token for organization packages published to GitHub Packages. Can be set to 'read' or 'write'."
|
||||
permission-organization-personal-access-token-requests:
|
||||
description: "The level of permission to grant the access token for viewing and managing fine-grained personal access tokens that have been approved by an organization. Can be set to 'read' or 'write'."
|
||||
permission-organization-personal-access-tokens:
|
||||
description: "The level of permission to grant the access token for viewing and managing fine-grained personal access token requests to an organization. Can be set to 'read' or 'write'."
|
||||
permission-organization-plan:
|
||||
description: "The level of permission to grant the access token for viewing an organization's plan. Can be set to 'read'."
|
||||
permission-organization-projects:
|
||||
description: "The level of permission to grant the access token to manage organization projects and projects public preview (where available). Can be set to 'read', 'write', or 'admin'."
|
||||
permission-organization-secrets:
|
||||
description: "The level of permission to grant the access token to manage organization secrets. Can be set to 'read' or 'write'."
|
||||
permission-organization-self-hosted-runners:
|
||||
description: "The level of permission to grant the access token to view and manage GitHub Actions self-hosted runners available to an organization. Can be set to 'read' or 'write'."
|
||||
permission-organization-user-blocking:
|
||||
description: "The level of permission to grant the access token to view and manage users blocked by the organization. Can be set to 'read' or 'write'."
|
||||
permission-packages:
|
||||
description: "The level of permission to grant the access token for packages published to GitHub Packages. Can be set to 'read' or 'write'."
|
||||
permission-pages:
|
||||
description: "The level of permission to grant the access token to retrieve Pages statuses, configuration, and builds, as well as create new builds. Can be set to 'read' or 'write'."
|
||||
permission-profile:
|
||||
description: "The level of permission to grant the access token to manage the profile settings belonging to a user. Can be set to 'write'."
|
||||
permission-pull-requests:
|
||||
description: "The level of permission to grant the access token for pull requests and related comments, assignees, labels, milestones, and merges. Can be set to 'read' or 'write'."
|
||||
permission-repository-custom-properties:
|
||||
description: "The level of permission to grant the access token to view and edit custom properties for a repository, when allowed by the property. Can be set to 'read' or 'write'."
|
||||
permission-repository-hooks:
|
||||
description: "The level of permission to grant the access token to manage the post-receive hooks for a repository. Can be set to 'read' or 'write'."
|
||||
permission-repository-projects:
|
||||
description: "The level of permission to grant the access token to manage repository projects, columns, and cards. Can be set to 'read', 'write', or 'admin'."
|
||||
permission-secret-scanning-alerts:
|
||||
description: "The level of permission to grant the access token to view and manage secret scanning alerts. Can be set to 'read' or 'write'."
|
||||
permission-secrets:
|
||||
description: "The level of permission to grant the access token to manage repository secrets. Can be set to 'read' or 'write'."
|
||||
permission-security-events:
|
||||
description: "The level of permission to grant the access token to view and manage security events like code scanning alerts. Can be set to 'read' or 'write'."
|
||||
permission-single-file:
|
||||
description: "The level of permission to grant the access token to manage just a single file. Can be set to 'read' or 'write'."
|
||||
permission-starring:
|
||||
description: "The level of permission to grant the access token to list and manage repositories a user is starring. Can be set to 'read' or 'write'."
|
||||
permission-statuses:
|
||||
description: "The level of permission to grant the access token for commit statuses. Can be set to 'read' or 'write'."
|
||||
permission-team-discussions:
|
||||
description: "The level of permission to grant the access token to manage team discussions and related comments. Can be set to 'read' or 'write'."
|
||||
permission-vulnerability-alerts:
|
||||
description: "The level of permission to grant the access token to manage Dependabot alerts. Can be set to 'read' or 'write'."
|
||||
permission-workflows:
|
||||
description: "The level of permission to grant the access token to update GitHub Actions workflow files. Can be set to 'write'."
|
||||
# <END GENERATED PERMISSIONS INPUTS>
|
||||
outputs:
|
||||
token:
|
||||
description: "GitHub installation access token"
|
||||
|
||||
Vendored
+390
-106
@@ -28,6 +28,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
||||
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
||||
mod
|
||||
));
|
||||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
||||
|
||||
// node_modules/@actions/core/lib/utils.js
|
||||
var require_utils = __commonJS({
|
||||
@@ -5260,6 +5261,13 @@ var require_body = __commonJS({
|
||||
var { isUint8Array, isArrayBuffer } = require("util/types");
|
||||
var { File: UndiciFile } = require_file();
|
||||
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
||||
var random;
|
||||
try {
|
||||
const crypto = require("node:crypto");
|
||||
random = (max) => crypto.randomInt(0, max);
|
||||
} catch {
|
||||
random = (max) => Math.floor(Math.random(max));
|
||||
}
|
||||
var ReadableStream2 = globalThis.ReadableStream;
|
||||
var File = NativeFile ?? UndiciFile;
|
||||
var textEncoder = new TextEncoder();
|
||||
@@ -5302,7 +5310,7 @@ var require_body = __commonJS({
|
||||
} else if (ArrayBuffer.isView(object)) {
|
||||
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength));
|
||||
} else if (util.isFormDataLike(object)) {
|
||||
const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, "0")}`;
|
||||
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`;
|
||||
const prefix = `--${boundary}\r
|
||||
Content-Disposition: form-data`;
|
||||
const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
|
||||
@@ -8858,6 +8866,14 @@ var require_pool = __commonJS({
|
||||
this[kOptions] = { ...util.deepClone(options), connect, allowH2 };
|
||||
this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0;
|
||||
this[kFactory] = factory;
|
||||
this.on("connectionError", (origin2, targets, error) => {
|
||||
for (const target of targets) {
|
||||
const idx = this[kClients].indexOf(target);
|
||||
if (idx !== -1) {
|
||||
this[kClients].splice(idx, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
[kGetDispatcher]() {
|
||||
let dispatcher = this[kClients].find((dispatcher2) => !dispatcher2[kNeedDrain]);
|
||||
@@ -11528,6 +11544,7 @@ var require_headers = __commonJS({
|
||||
isValidHeaderName,
|
||||
isValidHeaderValue
|
||||
} = require_util2();
|
||||
var util = require("util");
|
||||
var { webidl } = require_webidl();
|
||||
var assert = require("assert");
|
||||
var kHeadersMap = Symbol("headers map");
|
||||
@@ -11879,6 +11896,9 @@ var require_headers = __commonJS({
|
||||
[Symbol.toStringTag]: {
|
||||
value: "Headers",
|
||||
configurable: true
|
||||
},
|
||||
[util.inspect.custom]: {
|
||||
enumerable: false
|
||||
}
|
||||
});
|
||||
webidl.converters.HeadersInit = function(V) {
|
||||
@@ -15468,8 +15488,6 @@ var require_constants4 = __commonJS({
|
||||
var require_util6 = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/cookies/util.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var assert = require("assert");
|
||||
var { kHeadersList } = require_symbols();
|
||||
function isCTLExcludingHtab(value) {
|
||||
if (value.length === 0) {
|
||||
return false;
|
||||
@@ -15600,25 +15618,13 @@ var require_util6 = __commonJS({
|
||||
}
|
||||
return out.join("; ");
|
||||
}
|
||||
var kHeadersListNode;
|
||||
function getHeadersList(headers) {
|
||||
if (headers[kHeadersList]) {
|
||||
return headers[kHeadersList];
|
||||
}
|
||||
if (!kHeadersListNode) {
|
||||
kHeadersListNode = Object.getOwnPropertySymbols(headers).find(
|
||||
(symbol) => symbol.description === "headers list"
|
||||
);
|
||||
assert(kHeadersListNode, "Headers cannot be parsed");
|
||||
}
|
||||
const headersList = headers[kHeadersListNode];
|
||||
assert(headersList);
|
||||
return headersList;
|
||||
}
|
||||
module2.exports = {
|
||||
isCTLExcludingHtab,
|
||||
stringify,
|
||||
getHeadersList
|
||||
validateCookieName,
|
||||
validateCookiePath,
|
||||
validateCookieValue,
|
||||
toIMFDate,
|
||||
stringify
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -15768,7 +15774,7 @@ var require_cookies = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/cookies/index.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var { parseSetCookie } = require_parse();
|
||||
var { stringify, getHeadersList } = require_util6();
|
||||
var { stringify } = require_util6();
|
||||
var { webidl } = require_webidl();
|
||||
var { Headers } = require_headers();
|
||||
function getCookies(headers) {
|
||||
@@ -15800,11 +15806,11 @@ var require_cookies = __commonJS({
|
||||
function getSetCookies(headers) {
|
||||
webidl.argumentLengthCheck(arguments, 1, { header: "getSetCookies" });
|
||||
webidl.brandCheck(headers, Headers, { strict: false });
|
||||
const cookies = getHeadersList(headers).cookies;
|
||||
const cookies = headers.getSetCookie();
|
||||
if (!cookies) {
|
||||
return [];
|
||||
}
|
||||
return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair));
|
||||
return cookies.map((pair) => parseSetCookie(pair));
|
||||
}
|
||||
function setCookie(headers, cookie) {
|
||||
webidl.argumentLengthCheck(arguments, 2, { header: "setCookie" });
|
||||
@@ -25550,7 +25556,7 @@ var require_body2 = __commonJS({
|
||||
const crypto = require("node:crypto");
|
||||
random = (max) => crypto.randomInt(0, max);
|
||||
} catch {
|
||||
random = (max) => Math.floor(Math.random(max));
|
||||
random = (max) => Math.floor(Math.random() * max);
|
||||
}
|
||||
var textEncoder = new TextEncoder();
|
||||
function noop() {
|
||||
@@ -27754,7 +27760,7 @@ var require_client2 = __commonJS({
|
||||
allowH2,
|
||||
socketPath,
|
||||
timeout: connectTimeout,
|
||||
...autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...connect2
|
||||
});
|
||||
}
|
||||
@@ -28390,7 +28396,7 @@ var require_pool2 = __commonJS({
|
||||
allowH2,
|
||||
socketPath,
|
||||
timeout: connectTimeout,
|
||||
...autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...connect
|
||||
});
|
||||
}
|
||||
@@ -28399,6 +28405,14 @@ var require_pool2 = __commonJS({
|
||||
this[kOptions] = { ...util.deepClone(options), connect, allowH2 };
|
||||
this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0;
|
||||
this[kFactory] = factory;
|
||||
this.on("connectionError", (origin2, targets, error) => {
|
||||
for (const target of targets) {
|
||||
const idx = this[kClients].indexOf(target);
|
||||
if (idx !== -1) {
|
||||
this[kClients].splice(idx, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
[kGetDispatcher]() {
|
||||
for (const client of this[kClients]) {
|
||||
@@ -28815,7 +28829,6 @@ var require_env_http_proxy_agent = __commonJS({
|
||||
"http:": 80,
|
||||
"https:": 443
|
||||
};
|
||||
var experimentalWarned = false;
|
||||
var EnvHttpProxyAgent = class extends DispatcherBase {
|
||||
#noProxyValue = null;
|
||||
#noProxyEntries = null;
|
||||
@@ -28823,12 +28836,6 @@ var require_env_http_proxy_agent = __commonJS({
|
||||
constructor(opts = {}) {
|
||||
super();
|
||||
this.#opts = opts;
|
||||
if (!experimentalWarned) {
|
||||
experimentalWarned = true;
|
||||
process.emitWarning("EnvHttpProxyAgent is experimental, expect them to change at any time.", {
|
||||
code: "UNDICI-EHPA"
|
||||
});
|
||||
}
|
||||
const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts;
|
||||
this[kNoProxyAgent] = new Agent(agentOpts);
|
||||
const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY;
|
||||
@@ -28953,8 +28960,8 @@ var require_retry_handler = __commonJS({
|
||||
wrapRequestBody
|
||||
} = require_util8();
|
||||
function calculateRetryAfterHeader(retryAfter) {
|
||||
const current = Date.now();
|
||||
return new Date(retryAfter).getTime() - current;
|
||||
const retryTime = new Date(retryAfter).getTime();
|
||||
return isNaN(retryTime) ? 0 : retryTime - Date.now();
|
||||
}
|
||||
var RetryHandler = class _RetryHandler {
|
||||
constructor(opts, { dispatch, handler }) {
|
||||
@@ -29048,7 +29055,7 @@ var require_retry_handler = __commonJS({
|
||||
let retryAfterHeader = headers?.["retry-after"];
|
||||
if (retryAfterHeader) {
|
||||
retryAfterHeader = Number(retryAfterHeader);
|
||||
retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(retryAfterHeader) : retryAfterHeader * 1e3;
|
||||
retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(headers["retry-after"]) : retryAfterHeader * 1e3;
|
||||
}
|
||||
const retryTimeout = retryAfterHeader > 0 ? Math.min(retryAfterHeader, maxTimeout) : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout);
|
||||
setTimeout(() => cb(null), retryTimeout);
|
||||
@@ -30465,7 +30472,12 @@ var require_mock_symbols2 = __commonJS({
|
||||
kNetConnect: Symbol("net connect"),
|
||||
kGetNetConnect: Symbol("get net connect"),
|
||||
kConnected: Symbol("connected"),
|
||||
kIgnoreTrailingSlash: Symbol("ignore trailing slash")
|
||||
kIgnoreTrailingSlash: Symbol("ignore trailing slash"),
|
||||
kMockAgentMockCallHistoryInstance: Symbol("mock agent mock call history name"),
|
||||
kMockAgentRegisterCallHistory: Symbol("mock agent register mock call history"),
|
||||
kMockAgentAddCallHistoryLog: Symbol("mock agent add call history log"),
|
||||
kMockAgentIsCallHistoryEnabled: Symbol("mock agent is call history enabled"),
|
||||
kMockCallHistoryAddLog: Symbol("mock call history add log")
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -30489,6 +30501,7 @@ var require_mock_utils2 = __commonJS({
|
||||
isPromise
|
||||
}
|
||||
} = require("node:util");
|
||||
var { InvalidArgumentError } = require_errors2();
|
||||
function matchValue(match, value) {
|
||||
if (typeof match === "string") {
|
||||
return match === value;
|
||||
@@ -30579,8 +30592,10 @@ var require_mock_utils2 = __commonJS({
|
||||
return data;
|
||||
} else if (typeof data === "object") {
|
||||
return JSON.stringify(data);
|
||||
} else {
|
||||
} else if (data) {
|
||||
return data.toString();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
function getMockDispatch(mockDispatches, key) {
|
||||
@@ -30752,9 +30767,12 @@ var require_mock_utils2 = __commonJS({
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function buildMockOptions(opts) {
|
||||
function buildAndValidateMockOptions(opts) {
|
||||
if (opts) {
|
||||
const { agent, ...mockOptions } = opts;
|
||||
if ("enableCallHistory" in mockOptions && typeof mockOptions.enableCallHistory !== "boolean") {
|
||||
throw new InvalidArgumentError("options.enableCallHistory must to be a boolean");
|
||||
}
|
||||
return mockOptions;
|
||||
}
|
||||
}
|
||||
@@ -30771,7 +30789,7 @@ var require_mock_utils2 = __commonJS({
|
||||
mockDispatch,
|
||||
buildMockDispatch,
|
||||
checkNetConnect,
|
||||
buildMockOptions,
|
||||
buildAndValidateMockOptions,
|
||||
getHeaderByName,
|
||||
buildHeadersFromArray
|
||||
};
|
||||
@@ -31000,6 +31018,206 @@ var require_mock_client2 = __commonJS({
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/undici/lib/mock/mock-call-history.js
|
||||
var require_mock_call_history = __commonJS({
|
||||
"node_modules/undici/lib/mock/mock-call-history.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var { kMockCallHistoryAddLog } = require_mock_symbols2();
|
||||
var { InvalidArgumentError } = require_errors2();
|
||||
function handleFilterCallsWithOptions(criteria, options, handler, store) {
|
||||
switch (options.operator) {
|
||||
case "OR":
|
||||
store.push(...handler(criteria));
|
||||
return store;
|
||||
case "AND":
|
||||
return handler.call({ logs: store }, criteria);
|
||||
default:
|
||||
throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'");
|
||||
}
|
||||
}
|
||||
function buildAndValidateFilterCallsOptions(options = {}) {
|
||||
const finalOptions = {};
|
||||
if ("operator" in options) {
|
||||
if (typeof options.operator !== "string" || options.operator.toUpperCase() !== "OR" && options.operator.toUpperCase() !== "AND") {
|
||||
throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'");
|
||||
}
|
||||
return {
|
||||
...finalOptions,
|
||||
operator: options.operator.toUpperCase()
|
||||
};
|
||||
}
|
||||
return finalOptions;
|
||||
}
|
||||
function makeFilterCalls(parameterName) {
|
||||
return (parameterValue) => {
|
||||
if (typeof parameterValue === "string" || parameterValue == null) {
|
||||
return this.logs.filter((log) => {
|
||||
return log[parameterName] === parameterValue;
|
||||
});
|
||||
}
|
||||
if (parameterValue instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return parameterValue.test(log[parameterName]);
|
||||
});
|
||||
}
|
||||
throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`);
|
||||
};
|
||||
}
|
||||
function computeUrlWithMaybeSearchParameters(requestInit) {
|
||||
try {
|
||||
const url = new URL(requestInit.path, requestInit.origin);
|
||||
if (url.search.length !== 0) {
|
||||
return url;
|
||||
}
|
||||
url.search = new URLSearchParams(requestInit.query).toString();
|
||||
return url;
|
||||
} catch (error) {
|
||||
throw new InvalidArgumentError("An error occurred when computing MockCallHistoryLog.url", { cause: error });
|
||||
}
|
||||
}
|
||||
var MockCallHistoryLog = class {
|
||||
constructor(requestInit = {}) {
|
||||
this.body = requestInit.body;
|
||||
this.headers = requestInit.headers;
|
||||
this.method = requestInit.method;
|
||||
const url = computeUrlWithMaybeSearchParameters(requestInit);
|
||||
this.fullUrl = url.toString();
|
||||
this.origin = url.origin;
|
||||
this.path = url.pathname;
|
||||
this.searchParams = Object.fromEntries(url.searchParams);
|
||||
this.protocol = url.protocol;
|
||||
this.host = url.host;
|
||||
this.port = url.port;
|
||||
this.hash = url.hash;
|
||||
}
|
||||
toMap() {
|
||||
return /* @__PURE__ */ new Map(
|
||||
[
|
||||
["protocol", this.protocol],
|
||||
["host", this.host],
|
||||
["port", this.port],
|
||||
["origin", this.origin],
|
||||
["path", this.path],
|
||||
["hash", this.hash],
|
||||
["searchParams", this.searchParams],
|
||||
["fullUrl", this.fullUrl],
|
||||
["method", this.method],
|
||||
["body", this.body],
|
||||
["headers", this.headers]
|
||||
]
|
||||
);
|
||||
}
|
||||
toString() {
|
||||
const options = { betweenKeyValueSeparator: "->", betweenPairSeparator: "|" };
|
||||
let result = "";
|
||||
this.toMap().forEach((value, key) => {
|
||||
if (typeof value === "string" || value === void 0 || value === null) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}`;
|
||||
}
|
||||
if (typeof value === "object" && value !== null || Array.isArray(value)) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}`;
|
||||
}
|
||||
});
|
||||
return result.slice(0, -1);
|
||||
}
|
||||
};
|
||||
var MockCallHistory = class {
|
||||
logs = [];
|
||||
calls() {
|
||||
return this.logs;
|
||||
}
|
||||
firstCall() {
|
||||
return this.logs.at(0);
|
||||
}
|
||||
lastCall() {
|
||||
return this.logs.at(-1);
|
||||
}
|
||||
nthCall(number) {
|
||||
if (typeof number !== "number") {
|
||||
throw new InvalidArgumentError("nthCall must be called with a number");
|
||||
}
|
||||
if (!Number.isInteger(number)) {
|
||||
throw new InvalidArgumentError("nthCall must be called with an integer");
|
||||
}
|
||||
if (Math.sign(number) !== 1) {
|
||||
throw new InvalidArgumentError("nthCall must be called with a positive value. use firstCall or lastCall instead");
|
||||
}
|
||||
return this.logs.at(number - 1);
|
||||
}
|
||||
filterCalls(criteria, options) {
|
||||
if (this.logs.length === 0) {
|
||||
return this.logs;
|
||||
}
|
||||
if (typeof criteria === "function") {
|
||||
return this.logs.filter(criteria);
|
||||
}
|
||||
if (criteria instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return criteria.test(log.toString());
|
||||
});
|
||||
}
|
||||
if (typeof criteria === "object" && criteria !== null) {
|
||||
if (Object.keys(criteria).length === 0) {
|
||||
return this.logs;
|
||||
}
|
||||
const finalOptions = { operator: "OR", ...buildAndValidateFilterCallsOptions(options) };
|
||||
let maybeDuplicatedLogsFiltered = [];
|
||||
if ("protocol" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("host" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("port" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("origin" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("path" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("hash" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("fullUrl" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("method" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)];
|
||||
return uniqLogsFiltered;
|
||||
}
|
||||
throw new InvalidArgumentError("criteria parameter should be one of function, regexp, or object");
|
||||
}
|
||||
filterCallsByProtocol = makeFilterCalls.call(this, "protocol");
|
||||
filterCallsByHost = makeFilterCalls.call(this, "host");
|
||||
filterCallsByPort = makeFilterCalls.call(this, "port");
|
||||
filterCallsByOrigin = makeFilterCalls.call(this, "origin");
|
||||
filterCallsByPath = makeFilterCalls.call(this, "path");
|
||||
filterCallsByHash = makeFilterCalls.call(this, "hash");
|
||||
filterCallsByFullUrl = makeFilterCalls.call(this, "fullUrl");
|
||||
filterCallsByMethod = makeFilterCalls.call(this, "method");
|
||||
clear() {
|
||||
this.logs = [];
|
||||
}
|
||||
[kMockCallHistoryAddLog](requestInit) {
|
||||
const log = new MockCallHistoryLog(requestInit);
|
||||
this.logs.push(log);
|
||||
return log;
|
||||
}
|
||||
*[Symbol.iterator]() {
|
||||
for (const log of this.calls()) {
|
||||
yield log;
|
||||
}
|
||||
}
|
||||
};
|
||||
module2.exports.MockCallHistory = MockCallHistory;
|
||||
module2.exports.MockCallHistoryLog = MockCallHistoryLog;
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/undici/lib/mock/mock-pool.js
|
||||
var require_mock_pool2 = __commonJS({
|
||||
"node_modules/undici/lib/mock/mock-pool.js"(exports2, module2) {
|
||||
@@ -31114,26 +31332,37 @@ var require_mock_agent2 = __commonJS({
|
||||
kNetConnect,
|
||||
kGetNetConnect,
|
||||
kOptions,
|
||||
kFactory
|
||||
kFactory,
|
||||
kMockAgentRegisterCallHistory,
|
||||
kMockAgentIsCallHistoryEnabled,
|
||||
kMockAgentAddCallHistoryLog,
|
||||
kMockAgentMockCallHistoryInstance,
|
||||
kMockCallHistoryAddLog
|
||||
} = require_mock_symbols2();
|
||||
var MockClient = require_mock_client2();
|
||||
var MockPool = require_mock_pool2();
|
||||
var { matchValue, buildMockOptions } = require_mock_utils2();
|
||||
var { matchValue, buildAndValidateMockOptions } = require_mock_utils2();
|
||||
var { InvalidArgumentError, UndiciError } = require_errors2();
|
||||
var Dispatcher = require_dispatcher2();
|
||||
var PendingInterceptorsFormatter = require_pending_interceptors_formatter2();
|
||||
var { MockCallHistory } = require_mock_call_history();
|
||||
var MockAgent = class extends Dispatcher {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
const mockOptions = buildAndValidateMockOptions(opts);
|
||||
this[kNetConnect] = true;
|
||||
this[kIsMockActive] = true;
|
||||
this[kMockAgentIsCallHistoryEnabled] = mockOptions?.enableCallHistory ?? false;
|
||||
if (opts?.agent && typeof opts.agent.dispatch !== "function") {
|
||||
throw new InvalidArgumentError("Argument opts.agent must implement Agent");
|
||||
}
|
||||
const agent = opts?.agent ? opts.agent : new Agent(opts);
|
||||
this[kAgent] = agent;
|
||||
this[kClients] = agent[kClients];
|
||||
this[kOptions] = buildMockOptions(opts);
|
||||
this[kOptions] = mockOptions;
|
||||
if (this[kMockAgentIsCallHistoryEnabled]) {
|
||||
this[kMockAgentRegisterCallHistory]();
|
||||
}
|
||||
}
|
||||
get(origin) {
|
||||
let dispatcher = this[kMockAgentGet](origin);
|
||||
@@ -31145,9 +31374,11 @@ var require_mock_agent2 = __commonJS({
|
||||
}
|
||||
dispatch(opts, handler) {
|
||||
this.get(opts.origin);
|
||||
this[kMockAgentAddCallHistoryLog](opts);
|
||||
return this[kAgent].dispatch(opts, handler);
|
||||
}
|
||||
async close() {
|
||||
this.clearCallHistory();
|
||||
await this[kAgent].close();
|
||||
this[kClients].clear();
|
||||
}
|
||||
@@ -31173,11 +31404,38 @@ var require_mock_agent2 = __commonJS({
|
||||
disableNetConnect() {
|
||||
this[kNetConnect] = false;
|
||||
}
|
||||
enableCallHistory() {
|
||||
this[kMockAgentIsCallHistoryEnabled] = true;
|
||||
return this;
|
||||
}
|
||||
disableCallHistory() {
|
||||
this[kMockAgentIsCallHistoryEnabled] = false;
|
||||
return this;
|
||||
}
|
||||
getCallHistory() {
|
||||
return this[kMockAgentMockCallHistoryInstance];
|
||||
}
|
||||
clearCallHistory() {
|
||||
if (this[kMockAgentMockCallHistoryInstance] !== void 0) {
|
||||
this[kMockAgentMockCallHistoryInstance].clear();
|
||||
}
|
||||
}
|
||||
// This is required to bypass issues caused by using global symbols - see:
|
||||
// https://github.com/nodejs/undici/issues/1447
|
||||
get isMockActive() {
|
||||
return this[kIsMockActive];
|
||||
}
|
||||
[kMockAgentRegisterCallHistory]() {
|
||||
if (this[kMockAgentMockCallHistoryInstance] === void 0) {
|
||||
this[kMockAgentMockCallHistoryInstance] = new MockCallHistory();
|
||||
}
|
||||
}
|
||||
[kMockAgentAddCallHistoryLog](opts) {
|
||||
if (this[kMockAgentIsCallHistoryEnabled]) {
|
||||
this[kMockAgentRegisterCallHistory]();
|
||||
this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts);
|
||||
}
|
||||
}
|
||||
[kMockAgentSet](origin, dispatcher) {
|
||||
this[kClients].set(origin, dispatcher);
|
||||
}
|
||||
@@ -32043,10 +32301,13 @@ var require_cache2 = __commonJS({
|
||||
if (typeof key !== "string" || typeof val !== "string") {
|
||||
throw new Error("opts.headers is not a valid header map");
|
||||
}
|
||||
headers[key] = val;
|
||||
headers[key.toLowerCase()] = val;
|
||||
}
|
||||
} else if (typeof opts.headers === "object") {
|
||||
headers = opts.headers;
|
||||
headers = {};
|
||||
for (const key of Object.keys(opts.headers)) {
|
||||
headers[key.toLowerCase()] = opts.headers[key];
|
||||
}
|
||||
} else {
|
||||
throw new Error("opts.headers is not an object");
|
||||
}
|
||||
@@ -32201,17 +32462,13 @@ var require_cache2 = __commonJS({
|
||||
return headers;
|
||||
}
|
||||
const output = (
|
||||
/** @type {Record<string, string | string[]>} */
|
||||
/** @type {Record<string, string | string[] | null>} */
|
||||
{}
|
||||
);
|
||||
const varyingHeaders = typeof varyHeader === "string" ? varyHeader.split(",") : varyHeader;
|
||||
for (const header of varyingHeaders) {
|
||||
const trimmedHeader = header.trim().toLowerCase();
|
||||
if (headers[trimmedHeader]) {
|
||||
output[trimmedHeader] = headers[trimmedHeader];
|
||||
} else {
|
||||
return void 0;
|
||||
}
|
||||
output[trimmedHeader] = headers[trimmedHeader] ?? null;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -32793,7 +33050,12 @@ var require_memory_cache_store = __commonJS({
|
||||
assertCacheKey(key);
|
||||
const topLevelKey = `${key.origin}:${key.path}`;
|
||||
const now = Date.now();
|
||||
const entry = this.#entries.get(topLevelKey)?.find((entry2) => entry2.deleteAt > now && entry2.method === key.method && (entry2.vary == null || Object.keys(entry2.vary).every((headerName) => entry2.vary[headerName] === key.headers?.[headerName])));
|
||||
const entry = this.#entries.get(topLevelKey)?.find((entry2) => entry2.deleteAt > now && entry2.method === key.method && (entry2.vary == null || Object.keys(entry2.vary).every((headerName) => {
|
||||
if (entry2.vary[headerName] === null) {
|
||||
return key.headers[headerName] === void 0;
|
||||
}
|
||||
return entry2.vary[headerName] === key.headers[headerName];
|
||||
})));
|
||||
return entry == null ? void 0 : {
|
||||
statusMessage: entry.statusMessage,
|
||||
statusCode: entry.statusCode,
|
||||
@@ -33379,7 +33641,7 @@ var require_sqlite_cache_store = __commonJS({
|
||||
assertCacheKey(key);
|
||||
const value = this.#findValue(key);
|
||||
return value ? {
|
||||
body: value.body ? Buffer.from(value.body.buffer) : void 0,
|
||||
body: value.body ? Buffer.from(value.body.buffer, value.body.byteOffset, value.body.byteLength) : void 0,
|
||||
statusCode: value.statusCode,
|
||||
statusMessage: value.statusMessage,
|
||||
headers: value.headers ? JSON.parse(value.headers) : void 0,
|
||||
@@ -33524,9 +33786,6 @@ var require_sqlite_cache_store = __commonJS({
|
||||
}
|
||||
let matches = true;
|
||||
if (value.vary) {
|
||||
if (!headers) {
|
||||
return void 0;
|
||||
}
|
||||
const vary = JSON.parse(value.vary);
|
||||
for (const header in vary) {
|
||||
if (!headerValueEquals(headers[header], vary[header])) {
|
||||
@@ -33543,16 +33802,17 @@ var require_sqlite_cache_store = __commonJS({
|
||||
}
|
||||
};
|
||||
function headerValueEquals(lhs, rhs) {
|
||||
if (lhs == null && rhs == null) {
|
||||
return true;
|
||||
}
|
||||
if (lhs == null && rhs != null || lhs != null && rhs == null) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(lhs) && Array.isArray(rhs)) {
|
||||
if (lhs.length !== rhs.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < lhs.length; i++) {
|
||||
if (rhs.includes(lhs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return lhs.every((x, i) => x === rhs[i]);
|
||||
}
|
||||
return lhs === rhs;
|
||||
}
|
||||
@@ -34518,6 +34778,12 @@ var require_request4 = __commonJS({
|
||||
signal.removeEventListener("abort", abort);
|
||||
});
|
||||
var dependentControllerMap = /* @__PURE__ */ new WeakMap();
|
||||
var abortSignalHasEventHandlerLeakWarning;
|
||||
try {
|
||||
abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0;
|
||||
} catch {
|
||||
abortSignalHasEventHandlerLeakWarning = false;
|
||||
}
|
||||
function buildAbort(acRef) {
|
||||
return abort;
|
||||
function abort() {
|
||||
@@ -34745,11 +35011,8 @@ var require_request4 = __commonJS({
|
||||
this[kAbortController] = ac;
|
||||
const acRef = new WeakRef(ac);
|
||||
const abort = buildAbort(acRef);
|
||||
try {
|
||||
if (typeof getMaxListeners === "function" && getMaxListeners(signal) === defaultMaxListeners) {
|
||||
setMaxListeners(1500, signal);
|
||||
}
|
||||
} catch {
|
||||
if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) {
|
||||
setMaxListeners(1500, signal);
|
||||
}
|
||||
util.addAbortListener(signal, abort);
|
||||
requestFinalizer.register(ac, { signal, abort }, abort);
|
||||
@@ -40035,6 +40298,7 @@ var require_undici2 = __commonJS({
|
||||
var api = require_api2();
|
||||
var buildConnector = require_connect2();
|
||||
var MockClient = require_mock_client2();
|
||||
var { MockCallHistory, MockCallHistoryLog } = require_mock_call_history();
|
||||
var MockAgent = require_mock_agent2();
|
||||
var MockPool = require_mock_pool2();
|
||||
var mockErrors = require_mock_errors2();
|
||||
@@ -40157,6 +40421,8 @@ var require_undici2 = __commonJS({
|
||||
module2.exports.connect = makeDispatcher(api.connect);
|
||||
module2.exports.upgrade = makeDispatcher(api.upgrade);
|
||||
module2.exports.MockClient = MockClient;
|
||||
module2.exports.MockCallHistory = MockCallHistory;
|
||||
module2.exports.MockCallHistoryLog = MockCallHistoryLog;
|
||||
module2.exports.MockPool = MockPool;
|
||||
module2.exports.MockAgent = MockAgent;
|
||||
module2.exports.mockErrors = mockErrors;
|
||||
@@ -40166,6 +40432,11 @@ var require_undici2 = __commonJS({
|
||||
});
|
||||
|
||||
// main.js
|
||||
var main_exports = {};
|
||||
__export(main_exports, {
|
||||
default: () => main_default
|
||||
});
|
||||
module.exports = __toCommonJS(main_exports);
|
||||
var import_core2 = __toESM(require_core(), 1);
|
||||
|
||||
// node_modules/universal-user-agent/index.js
|
||||
@@ -40739,8 +41010,7 @@ async function oauthRequest(request2, route, parameters) {
|
||||
return response;
|
||||
}
|
||||
async function exchangeWebFlowCode(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const response = await oauthRequest(
|
||||
request2,
|
||||
"POST /login/oauth/access_token",
|
||||
@@ -40777,8 +41047,7 @@ function toTimestamp(apiTimeInMs, expirationInSeconds) {
|
||||
return new Date(apiTimeInMs + expirationInSeconds * 1e3).toISOString();
|
||||
}
|
||||
async function createDeviceCode(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const parameters = {
|
||||
client_id: options.clientId
|
||||
};
|
||||
@@ -40788,8 +41057,7 @@ async function createDeviceCode(options) {
|
||||
return oauthRequest(request2, "POST /login/device/code", parameters);
|
||||
}
|
||||
async function exchangeDeviceCode(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const response = await oauthRequest(
|
||||
request2,
|
||||
"POST /login/oauth/access_token",
|
||||
@@ -40827,8 +41095,7 @@ function toTimestamp2(apiTimeInMs, expirationInSeconds) {
|
||||
return new Date(apiTimeInMs + expirationInSeconds * 1e3).toISOString();
|
||||
}
|
||||
async function checkToken(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const response = await request2("POST /applications/{client_id}/token", {
|
||||
headers: {
|
||||
authorization: `basic ${btoa(
|
||||
@@ -40853,8 +41120,7 @@ async function checkToken(options) {
|
||||
return { ...response, authentication };
|
||||
}
|
||||
async function refreshToken(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const response = await oauthRequest(
|
||||
request2,
|
||||
"POST /login/oauth/access_token",
|
||||
@@ -40884,8 +41150,7 @@ function toTimestamp3(apiTimeInMs, expirationInSeconds) {
|
||||
return new Date(apiTimeInMs + expirationInSeconds * 1e3).toISOString();
|
||||
}
|
||||
async function resetToken(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const auth5 = btoa(`${options.clientId}:${options.clientSecret}`);
|
||||
const response = await request2(
|
||||
"PATCH /applications/{client_id}/token",
|
||||
@@ -40912,8 +41177,7 @@ async function resetToken(options) {
|
||||
return { ...response, authentication };
|
||||
}
|
||||
async function deleteToken(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const auth5 = btoa(`${options.clientId}:${options.clientSecret}`);
|
||||
return request2(
|
||||
"DELETE /applications/{client_id}/token",
|
||||
@@ -40927,8 +41191,7 @@ async function deleteToken(options) {
|
||||
);
|
||||
}
|
||||
async function deleteAuthorization(options) {
|
||||
const request2 = options.request || /* istanbul ignore next: we always pass a custom request in tests */
|
||||
request;
|
||||
const request2 = options.request || request;
|
||||
const auth5 = btoa(`${options.clientId}:${options.clientSecret}`);
|
||||
return request2(
|
||||
"DELETE /applications/{client_id}/grant",
|
||||
@@ -41633,19 +41896,19 @@ async function get(cache, options) {
|
||||
permissionsString,
|
||||
singleFileName
|
||||
] = result.split("|");
|
||||
const permissions = options.permissions || permissionsString.split(/,/).reduce((permissions2, string) => {
|
||||
const permissions2 = options.permissions || permissionsString.split(/,/).reduce((permissions22, string) => {
|
||||
if (/!$/.test(string)) {
|
||||
permissions2[string.slice(0, -1)] = "write";
|
||||
permissions22[string.slice(0, -1)] = "write";
|
||||
} else {
|
||||
permissions2[string] = "read";
|
||||
permissions22[string] = "read";
|
||||
}
|
||||
return permissions2;
|
||||
return permissions22;
|
||||
}, {});
|
||||
return {
|
||||
token,
|
||||
createdAt,
|
||||
expiresAt,
|
||||
permissions,
|
||||
permissions: permissions2,
|
||||
repositoryIds: options.repositoryIds,
|
||||
repositoryNames: options.repositoryNames,
|
||||
singleFileName,
|
||||
@@ -41669,11 +41932,11 @@ async function set(cache, options, data) {
|
||||
}
|
||||
function optionsToCacheKey({
|
||||
installationId,
|
||||
permissions = {},
|
||||
permissions: permissions2 = {},
|
||||
repositoryIds = [],
|
||||
repositoryNames = []
|
||||
}) {
|
||||
const permissionsString = Object.keys(permissions).sort().map((name) => permissions[name] === "read" ? name : `${name}!`).join(",");
|
||||
const permissionsString = Object.keys(permissions2).sort().map((name) => permissions2[name] === "read" ? name : `${name}!`).join(",");
|
||||
const repositoryIdsString = repositoryIds.sort().join(",");
|
||||
const repositoryNamesString = repositoryNames.join(",");
|
||||
return [
|
||||
@@ -41689,7 +41952,7 @@ function toTokenAuthentication({
|
||||
createdAt,
|
||||
expiresAt,
|
||||
repositorySelection,
|
||||
permissions,
|
||||
permissions: permissions2,
|
||||
repositoryIds,
|
||||
repositoryNames,
|
||||
singleFileName
|
||||
@@ -41700,7 +41963,7 @@ function toTokenAuthentication({
|
||||
tokenType: "installation",
|
||||
token,
|
||||
installationId,
|
||||
permissions,
|
||||
permissions: permissions2,
|
||||
createdAt,
|
||||
expiresAt,
|
||||
repositorySelection
|
||||
@@ -41738,7 +42001,7 @@ async function getInstallationAuthentication(state, options, customRequest) {
|
||||
token: token2,
|
||||
createdAt: createdAt2,
|
||||
expiresAt: expiresAt2,
|
||||
permissions: permissions2,
|
||||
permissions: permissions22,
|
||||
repositoryIds: repositoryIds2,
|
||||
repositoryNames: repositoryNames2,
|
||||
singleFileName: singleFileName2,
|
||||
@@ -41749,7 +42012,7 @@ async function getInstallationAuthentication(state, options, customRequest) {
|
||||
token: token2,
|
||||
createdAt: createdAt2,
|
||||
expiresAt: expiresAt2,
|
||||
permissions: permissions2,
|
||||
permissions: permissions22,
|
||||
repositorySelection: repositorySelection2,
|
||||
repositoryIds: repositoryIds2,
|
||||
repositoryNames: repositoryNames2,
|
||||
@@ -41792,7 +42055,7 @@ async function getInstallationAuthentication(state, options, customRequest) {
|
||||
"POST /app/installations/{installation_id}/access_tokens",
|
||||
payload
|
||||
);
|
||||
const permissions = permissionsOptional || {};
|
||||
const permissions2 = permissionsOptional || {};
|
||||
const repositorySelection = repositorySelectionOptional || "all";
|
||||
const repositoryIds = repositories2 ? repositories2.map((r) => r.id) : void 0;
|
||||
const repositoryNames = repositories2 ? repositories2.map((repo) => repo.name) : void 0;
|
||||
@@ -41802,7 +42065,7 @@ async function getInstallationAuthentication(state, options, customRequest) {
|
||||
createdAt,
|
||||
expiresAt,
|
||||
repositorySelection,
|
||||
permissions,
|
||||
permissions: permissions2,
|
||||
repositoryIds,
|
||||
repositoryNames
|
||||
};
|
||||
@@ -41816,7 +42079,7 @@ async function getInstallationAuthentication(state, options, customRequest) {
|
||||
createdAt,
|
||||
expiresAt,
|
||||
repositorySelection,
|
||||
permissions,
|
||||
permissions: permissions2,
|
||||
repositoryIds,
|
||||
repositoryNames
|
||||
};
|
||||
@@ -41962,7 +42225,7 @@ async function sendRequestWithRetries(state, request2, options, createdAt, retri
|
||||
return sendRequestWithRetries(state, request2, options, createdAt, retries);
|
||||
}
|
||||
}
|
||||
var VERSION6 = "7.1.4";
|
||||
var VERSION6 = "7.1.5";
|
||||
function createAppAuth(options) {
|
||||
if (!options.appId) {
|
||||
throw new Error("[@octokit/auth-app] appId option is required");
|
||||
@@ -42119,7 +42382,7 @@ async function pRetry(input, options) {
|
||||
}
|
||||
|
||||
// lib/main.js
|
||||
async function main(appId2, privateKey2, owner2, repositories2, core3, createAppAuth2, request2, skipTokenRevoke2) {
|
||||
async function main(appId2, privateKey2, owner2, repositories2, permissions2, core3, createAppAuth2, request2, skipTokenRevoke2) {
|
||||
let parsedOwner = "";
|
||||
let parsedRepositoryNames = [];
|
||||
if (!owner2 && repositories2.length === 0) {
|
||||
@@ -42166,7 +42429,8 @@ async function main(appId2, privateKey2, owner2, repositories2, core3, createApp
|
||||
request2,
|
||||
auth5,
|
||||
parsedOwner,
|
||||
parsedRepositoryNames
|
||||
parsedRepositoryNames,
|
||||
permissions2
|
||||
),
|
||||
{
|
||||
onFailedAttempt: (error) => {
|
||||
@@ -42181,7 +42445,7 @@ async function main(appId2, privateKey2, owner2, repositories2, core3, createApp
|
||||
));
|
||||
} else {
|
||||
({ authentication, installationId, appSlug } = await pRetry(
|
||||
() => getTokenFromOwner(request2, auth5, parsedOwner),
|
||||
() => getTokenFromOwner(request2, auth5, parsedOwner, permissions2),
|
||||
{
|
||||
onFailedAttempt: (error) => {
|
||||
core3.info(
|
||||
@@ -42201,7 +42465,7 @@ async function main(appId2, privateKey2, owner2, repositories2, core3, createApp
|
||||
core3.saveState("expiresAt", authentication.expiresAt);
|
||||
}
|
||||
}
|
||||
async function getTokenFromOwner(request2, auth5, parsedOwner) {
|
||||
async function getTokenFromOwner(request2, auth5, parsedOwner, permissions2) {
|
||||
const response = await request2("GET /users/{username}/installation", {
|
||||
username: parsedOwner,
|
||||
request: {
|
||||
@@ -42210,13 +42474,14 @@ async function getTokenFromOwner(request2, auth5, parsedOwner) {
|
||||
});
|
||||
const authentication = await auth5({
|
||||
type: "installation",
|
||||
installationId: response.data.id
|
||||
installationId: response.data.id,
|
||||
permissions: permissions2
|
||||
});
|
||||
const installationId = response.data.id;
|
||||
const appSlug = response.data["app_slug"];
|
||||
return { authentication, installationId, appSlug };
|
||||
}
|
||||
async function getTokenFromRepository(request2, auth5, parsedOwner, parsedRepositoryNames) {
|
||||
async function getTokenFromRepository(request2, auth5, parsedOwner, parsedRepositoryNames, permissions2) {
|
||||
const response = await request2("GET /repos/{owner}/{repo}/installation", {
|
||||
owner: parsedOwner,
|
||||
repo: parsedRepositoryNames[0],
|
||||
@@ -42227,7 +42492,8 @@ async function getTokenFromRepository(request2, auth5, parsedOwner, parsedReposi
|
||||
const authentication = await auth5({
|
||||
type: "installation",
|
||||
installationId: response.data.id,
|
||||
repositoryNames: parsedRepositoryNames
|
||||
repositoryNames: parsedRepositoryNames,
|
||||
permissions: permissions2
|
||||
});
|
||||
const installationId = response.data.id;
|
||||
const appSlug = response.data["app_slug"];
|
||||
@@ -42261,6 +42527,22 @@ var request_default = request.defaults({
|
||||
request: proxyUrl ? { fetch: proxyFetch } : {}
|
||||
});
|
||||
|
||||
// lib/get-permissions-from-inputs.js
|
||||
function getPermissionsFromInputs(env) {
|
||||
return Object.entries(env).reduce((permissions2, [key, value]) => {
|
||||
if (!key.startsWith("INPUT_PERMISSION_")) return permissions2;
|
||||
const permission = key.slice("INPUT_PERMISSION_".length).toLowerCase();
|
||||
if (permissions2 === void 0) {
|
||||
return { [permission]: value };
|
||||
}
|
||||
return {
|
||||
// @ts-expect-error - needs to be typed correctly
|
||||
...permissions2,
|
||||
[permission]: value
|
||||
};
|
||||
}, void 0);
|
||||
}
|
||||
|
||||
// main.js
|
||||
if (!process.env.GITHUB_REPOSITORY) {
|
||||
throw new Error("GITHUB_REPOSITORY missing, must be set to '<owner>/<repo>'");
|
||||
@@ -42281,11 +42563,13 @@ var repositories = import_core2.default.getInput("repositories").split(/[\n,]+/)
|
||||
var skipTokenRevoke = Boolean(
|
||||
import_core2.default.getInput("skip-token-revoke") || import_core2.default.getInput("skip_token_revoke")
|
||||
);
|
||||
main(
|
||||
var permissions = getPermissionsFromInputs(process.env);
|
||||
var main_default = main(
|
||||
appId,
|
||||
privateKey,
|
||||
owner,
|
||||
repositories,
|
||||
permissions,
|
||||
import_core2.default,
|
||||
createAppAuth,
|
||||
request_default,
|
||||
|
||||
Vendored
+332
-67
@@ -5255,6 +5255,13 @@ var require_body = __commonJS({
|
||||
var { isUint8Array, isArrayBuffer } = require("util/types");
|
||||
var { File: UndiciFile } = require_file();
|
||||
var { parseMIMEType, serializeAMimeType } = require_dataURL();
|
||||
var random;
|
||||
try {
|
||||
const crypto = require("node:crypto");
|
||||
random = (max) => crypto.randomInt(0, max);
|
||||
} catch {
|
||||
random = (max) => Math.floor(Math.random(max));
|
||||
}
|
||||
var ReadableStream2 = globalThis.ReadableStream;
|
||||
var File = NativeFile ?? UndiciFile;
|
||||
var textEncoder = new TextEncoder();
|
||||
@@ -5297,7 +5304,7 @@ var require_body = __commonJS({
|
||||
} else if (ArrayBuffer.isView(object)) {
|
||||
source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength));
|
||||
} else if (util.isFormDataLike(object)) {
|
||||
const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, "0")}`;
|
||||
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`;
|
||||
const prefix = `--${boundary}\r
|
||||
Content-Disposition: form-data`;
|
||||
const escape = (str) => str.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
|
||||
@@ -8853,6 +8860,14 @@ var require_pool = __commonJS({
|
||||
this[kOptions] = { ...util.deepClone(options), connect, allowH2 };
|
||||
this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0;
|
||||
this[kFactory] = factory;
|
||||
this.on("connectionError", (origin2, targets, error) => {
|
||||
for (const target of targets) {
|
||||
const idx = this[kClients].indexOf(target);
|
||||
if (idx !== -1) {
|
||||
this[kClients].splice(idx, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
[kGetDispatcher]() {
|
||||
let dispatcher = this[kClients].find((dispatcher2) => !dispatcher2[kNeedDrain]);
|
||||
@@ -11523,6 +11538,7 @@ var require_headers = __commonJS({
|
||||
isValidHeaderName,
|
||||
isValidHeaderValue
|
||||
} = require_util2();
|
||||
var util = require("util");
|
||||
var { webidl } = require_webidl();
|
||||
var assert = require("assert");
|
||||
var kHeadersMap = Symbol("headers map");
|
||||
@@ -11874,6 +11890,9 @@ var require_headers = __commonJS({
|
||||
[Symbol.toStringTag]: {
|
||||
value: "Headers",
|
||||
configurable: true
|
||||
},
|
||||
[util.inspect.custom]: {
|
||||
enumerable: false
|
||||
}
|
||||
});
|
||||
webidl.converters.HeadersInit = function(V) {
|
||||
@@ -15463,8 +15482,6 @@ var require_constants4 = __commonJS({
|
||||
var require_util6 = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/cookies/util.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var assert = require("assert");
|
||||
var { kHeadersList } = require_symbols();
|
||||
function isCTLExcludingHtab(value) {
|
||||
if (value.length === 0) {
|
||||
return false;
|
||||
@@ -15595,25 +15612,13 @@ var require_util6 = __commonJS({
|
||||
}
|
||||
return out.join("; ");
|
||||
}
|
||||
var kHeadersListNode;
|
||||
function getHeadersList(headers) {
|
||||
if (headers[kHeadersList]) {
|
||||
return headers[kHeadersList];
|
||||
}
|
||||
if (!kHeadersListNode) {
|
||||
kHeadersListNode = Object.getOwnPropertySymbols(headers).find(
|
||||
(symbol) => symbol.description === "headers list"
|
||||
);
|
||||
assert(kHeadersListNode, "Headers cannot be parsed");
|
||||
}
|
||||
const headersList = headers[kHeadersListNode];
|
||||
assert(headersList);
|
||||
return headersList;
|
||||
}
|
||||
module2.exports = {
|
||||
isCTLExcludingHtab,
|
||||
stringify,
|
||||
getHeadersList
|
||||
validateCookieName,
|
||||
validateCookiePath,
|
||||
validateCookieValue,
|
||||
toIMFDate,
|
||||
stringify
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -15763,7 +15768,7 @@ var require_cookies = __commonJS({
|
||||
"node_modules/@actions/http-client/node_modules/undici/lib/cookies/index.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var { parseSetCookie } = require_parse();
|
||||
var { stringify, getHeadersList } = require_util6();
|
||||
var { stringify } = require_util6();
|
||||
var { webidl } = require_webidl();
|
||||
var { Headers } = require_headers();
|
||||
function getCookies(headers) {
|
||||
@@ -15795,11 +15800,11 @@ var require_cookies = __commonJS({
|
||||
function getSetCookies(headers) {
|
||||
webidl.argumentLengthCheck(arguments, 1, { header: "getSetCookies" });
|
||||
webidl.brandCheck(headers, Headers, { strict: false });
|
||||
const cookies = getHeadersList(headers).cookies;
|
||||
const cookies = headers.getSetCookie();
|
||||
if (!cookies) {
|
||||
return [];
|
||||
}
|
||||
return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair));
|
||||
return cookies.map((pair) => parseSetCookie(pair));
|
||||
}
|
||||
function setCookie(headers, cookie) {
|
||||
webidl.argumentLengthCheck(arguments, 2, { header: "setCookie" });
|
||||
@@ -25317,7 +25322,7 @@ var require_body2 = __commonJS({
|
||||
const crypto = require("node:crypto");
|
||||
random = (max) => crypto.randomInt(0, max);
|
||||
} catch {
|
||||
random = (max) => Math.floor(Math.random(max));
|
||||
random = (max) => Math.floor(Math.random() * max);
|
||||
}
|
||||
var textEncoder = new TextEncoder();
|
||||
function noop() {
|
||||
@@ -27521,7 +27526,7 @@ var require_client2 = __commonJS({
|
||||
allowH2,
|
||||
socketPath,
|
||||
timeout: connectTimeout,
|
||||
...autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...connect2
|
||||
});
|
||||
}
|
||||
@@ -28157,7 +28162,7 @@ var require_pool2 = __commonJS({
|
||||
allowH2,
|
||||
socketPath,
|
||||
timeout: connectTimeout,
|
||||
...autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...typeof autoSelectFamily === "boolean" ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : void 0,
|
||||
...connect
|
||||
});
|
||||
}
|
||||
@@ -28166,6 +28171,14 @@ var require_pool2 = __commonJS({
|
||||
this[kOptions] = { ...util.deepClone(options), connect, allowH2 };
|
||||
this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0;
|
||||
this[kFactory] = factory;
|
||||
this.on("connectionError", (origin2, targets, error) => {
|
||||
for (const target of targets) {
|
||||
const idx = this[kClients].indexOf(target);
|
||||
if (idx !== -1) {
|
||||
this[kClients].splice(idx, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
[kGetDispatcher]() {
|
||||
for (const client of this[kClients]) {
|
||||
@@ -28582,7 +28595,6 @@ var require_env_http_proxy_agent = __commonJS({
|
||||
"http:": 80,
|
||||
"https:": 443
|
||||
};
|
||||
var experimentalWarned = false;
|
||||
var EnvHttpProxyAgent = class extends DispatcherBase {
|
||||
#noProxyValue = null;
|
||||
#noProxyEntries = null;
|
||||
@@ -28590,12 +28602,6 @@ var require_env_http_proxy_agent = __commonJS({
|
||||
constructor(opts = {}) {
|
||||
super();
|
||||
this.#opts = opts;
|
||||
if (!experimentalWarned) {
|
||||
experimentalWarned = true;
|
||||
process.emitWarning("EnvHttpProxyAgent is experimental, expect them to change at any time.", {
|
||||
code: "UNDICI-EHPA"
|
||||
});
|
||||
}
|
||||
const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts;
|
||||
this[kNoProxyAgent] = new Agent(agentOpts);
|
||||
const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY;
|
||||
@@ -28720,8 +28726,8 @@ var require_retry_handler = __commonJS({
|
||||
wrapRequestBody
|
||||
} = require_util8();
|
||||
function calculateRetryAfterHeader(retryAfter) {
|
||||
const current = Date.now();
|
||||
return new Date(retryAfter).getTime() - current;
|
||||
const retryTime = new Date(retryAfter).getTime();
|
||||
return isNaN(retryTime) ? 0 : retryTime - Date.now();
|
||||
}
|
||||
var RetryHandler = class _RetryHandler {
|
||||
constructor(opts, { dispatch, handler }) {
|
||||
@@ -28815,7 +28821,7 @@ var require_retry_handler = __commonJS({
|
||||
let retryAfterHeader = headers?.["retry-after"];
|
||||
if (retryAfterHeader) {
|
||||
retryAfterHeader = Number(retryAfterHeader);
|
||||
retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(retryAfterHeader) : retryAfterHeader * 1e3;
|
||||
retryAfterHeader = Number.isNaN(retryAfterHeader) ? calculateRetryAfterHeader(headers["retry-after"]) : retryAfterHeader * 1e3;
|
||||
}
|
||||
const retryTimeout = retryAfterHeader > 0 ? Math.min(retryAfterHeader, maxTimeout) : Math.min(minTimeout * timeoutFactor ** (counter - 1), maxTimeout);
|
||||
setTimeout(() => cb(null), retryTimeout);
|
||||
@@ -30232,7 +30238,12 @@ var require_mock_symbols2 = __commonJS({
|
||||
kNetConnect: Symbol("net connect"),
|
||||
kGetNetConnect: Symbol("get net connect"),
|
||||
kConnected: Symbol("connected"),
|
||||
kIgnoreTrailingSlash: Symbol("ignore trailing slash")
|
||||
kIgnoreTrailingSlash: Symbol("ignore trailing slash"),
|
||||
kMockAgentMockCallHistoryInstance: Symbol("mock agent mock call history name"),
|
||||
kMockAgentRegisterCallHistory: Symbol("mock agent register mock call history"),
|
||||
kMockAgentAddCallHistoryLog: Symbol("mock agent add call history log"),
|
||||
kMockAgentIsCallHistoryEnabled: Symbol("mock agent is call history enabled"),
|
||||
kMockCallHistoryAddLog: Symbol("mock call history add log")
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -30256,6 +30267,7 @@ var require_mock_utils2 = __commonJS({
|
||||
isPromise
|
||||
}
|
||||
} = require("node:util");
|
||||
var { InvalidArgumentError } = require_errors2();
|
||||
function matchValue(match, value) {
|
||||
if (typeof match === "string") {
|
||||
return match === value;
|
||||
@@ -30346,8 +30358,10 @@ var require_mock_utils2 = __commonJS({
|
||||
return data;
|
||||
} else if (typeof data === "object") {
|
||||
return JSON.stringify(data);
|
||||
} else {
|
||||
} else if (data) {
|
||||
return data.toString();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
function getMockDispatch(mockDispatches, key) {
|
||||
@@ -30519,9 +30533,12 @@ var require_mock_utils2 = __commonJS({
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function buildMockOptions(opts) {
|
||||
function buildAndValidateMockOptions(opts) {
|
||||
if (opts) {
|
||||
const { agent, ...mockOptions } = opts;
|
||||
if ("enableCallHistory" in mockOptions && typeof mockOptions.enableCallHistory !== "boolean") {
|
||||
throw new InvalidArgumentError("options.enableCallHistory must to be a boolean");
|
||||
}
|
||||
return mockOptions;
|
||||
}
|
||||
}
|
||||
@@ -30538,7 +30555,7 @@ var require_mock_utils2 = __commonJS({
|
||||
mockDispatch,
|
||||
buildMockDispatch,
|
||||
checkNetConnect,
|
||||
buildMockOptions,
|
||||
buildAndValidateMockOptions,
|
||||
getHeaderByName,
|
||||
buildHeadersFromArray
|
||||
};
|
||||
@@ -30767,6 +30784,206 @@ var require_mock_client2 = __commonJS({
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/undici/lib/mock/mock-call-history.js
|
||||
var require_mock_call_history = __commonJS({
|
||||
"node_modules/undici/lib/mock/mock-call-history.js"(exports2, module2) {
|
||||
"use strict";
|
||||
var { kMockCallHistoryAddLog } = require_mock_symbols2();
|
||||
var { InvalidArgumentError } = require_errors2();
|
||||
function handleFilterCallsWithOptions(criteria, options, handler, store) {
|
||||
switch (options.operator) {
|
||||
case "OR":
|
||||
store.push(...handler(criteria));
|
||||
return store;
|
||||
case "AND":
|
||||
return handler.call({ logs: store }, criteria);
|
||||
default:
|
||||
throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'");
|
||||
}
|
||||
}
|
||||
function buildAndValidateFilterCallsOptions(options = {}) {
|
||||
const finalOptions = {};
|
||||
if ("operator" in options) {
|
||||
if (typeof options.operator !== "string" || options.operator.toUpperCase() !== "OR" && options.operator.toUpperCase() !== "AND") {
|
||||
throw new InvalidArgumentError("options.operator must to be a case insensitive string equal to 'OR' or 'AND'");
|
||||
}
|
||||
return {
|
||||
...finalOptions,
|
||||
operator: options.operator.toUpperCase()
|
||||
};
|
||||
}
|
||||
return finalOptions;
|
||||
}
|
||||
function makeFilterCalls(parameterName) {
|
||||
return (parameterValue) => {
|
||||
if (typeof parameterValue === "string" || parameterValue == null) {
|
||||
return this.logs.filter((log) => {
|
||||
return log[parameterName] === parameterValue;
|
||||
});
|
||||
}
|
||||
if (parameterValue instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return parameterValue.test(log[parameterName]);
|
||||
});
|
||||
}
|
||||
throw new InvalidArgumentError(`${parameterName} parameter should be one of string, regexp, undefined or null`);
|
||||
};
|
||||
}
|
||||
function computeUrlWithMaybeSearchParameters(requestInit) {
|
||||
try {
|
||||
const url = new URL(requestInit.path, requestInit.origin);
|
||||
if (url.search.length !== 0) {
|
||||
return url;
|
||||
}
|
||||
url.search = new URLSearchParams(requestInit.query).toString();
|
||||
return url;
|
||||
} catch (error) {
|
||||
throw new InvalidArgumentError("An error occurred when computing MockCallHistoryLog.url", { cause: error });
|
||||
}
|
||||
}
|
||||
var MockCallHistoryLog = class {
|
||||
constructor(requestInit = {}) {
|
||||
this.body = requestInit.body;
|
||||
this.headers = requestInit.headers;
|
||||
this.method = requestInit.method;
|
||||
const url = computeUrlWithMaybeSearchParameters(requestInit);
|
||||
this.fullUrl = url.toString();
|
||||
this.origin = url.origin;
|
||||
this.path = url.pathname;
|
||||
this.searchParams = Object.fromEntries(url.searchParams);
|
||||
this.protocol = url.protocol;
|
||||
this.host = url.host;
|
||||
this.port = url.port;
|
||||
this.hash = url.hash;
|
||||
}
|
||||
toMap() {
|
||||
return /* @__PURE__ */ new Map(
|
||||
[
|
||||
["protocol", this.protocol],
|
||||
["host", this.host],
|
||||
["port", this.port],
|
||||
["origin", this.origin],
|
||||
["path", this.path],
|
||||
["hash", this.hash],
|
||||
["searchParams", this.searchParams],
|
||||
["fullUrl", this.fullUrl],
|
||||
["method", this.method],
|
||||
["body", this.body],
|
||||
["headers", this.headers]
|
||||
]
|
||||
);
|
||||
}
|
||||
toString() {
|
||||
const options = { betweenKeyValueSeparator: "->", betweenPairSeparator: "|" };
|
||||
let result = "";
|
||||
this.toMap().forEach((value, key) => {
|
||||
if (typeof value === "string" || value === void 0 || value === null) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${value}${options.betweenPairSeparator}`;
|
||||
}
|
||||
if (typeof value === "object" && value !== null || Array.isArray(value)) {
|
||||
result = `${result}${key}${options.betweenKeyValueSeparator}${JSON.stringify(value)}${options.betweenPairSeparator}`;
|
||||
}
|
||||
});
|
||||
return result.slice(0, -1);
|
||||
}
|
||||
};
|
||||
var MockCallHistory = class {
|
||||
logs = [];
|
||||
calls() {
|
||||
return this.logs;
|
||||
}
|
||||
firstCall() {
|
||||
return this.logs.at(0);
|
||||
}
|
||||
lastCall() {
|
||||
return this.logs.at(-1);
|
||||
}
|
||||
nthCall(number) {
|
||||
if (typeof number !== "number") {
|
||||
throw new InvalidArgumentError("nthCall must be called with a number");
|
||||
}
|
||||
if (!Number.isInteger(number)) {
|
||||
throw new InvalidArgumentError("nthCall must be called with an integer");
|
||||
}
|
||||
if (Math.sign(number) !== 1) {
|
||||
throw new InvalidArgumentError("nthCall must be called with a positive value. use firstCall or lastCall instead");
|
||||
}
|
||||
return this.logs.at(number - 1);
|
||||
}
|
||||
filterCalls(criteria, options) {
|
||||
if (this.logs.length === 0) {
|
||||
return this.logs;
|
||||
}
|
||||
if (typeof criteria === "function") {
|
||||
return this.logs.filter(criteria);
|
||||
}
|
||||
if (criteria instanceof RegExp) {
|
||||
return this.logs.filter((log) => {
|
||||
return criteria.test(log.toString());
|
||||
});
|
||||
}
|
||||
if (typeof criteria === "object" && criteria !== null) {
|
||||
if (Object.keys(criteria).length === 0) {
|
||||
return this.logs;
|
||||
}
|
||||
const finalOptions = { operator: "OR", ...buildAndValidateFilterCallsOptions(options) };
|
||||
let maybeDuplicatedLogsFiltered = [];
|
||||
if ("protocol" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.protocol, finalOptions, this.filterCallsByProtocol, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("host" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.host, finalOptions, this.filterCallsByHost, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("port" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.port, finalOptions, this.filterCallsByPort, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("origin" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.origin, finalOptions, this.filterCallsByOrigin, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("path" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.path, finalOptions, this.filterCallsByPath, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("hash" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.hash, finalOptions, this.filterCallsByHash, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("fullUrl" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.fullUrl, finalOptions, this.filterCallsByFullUrl, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
if ("method" in criteria) {
|
||||
maybeDuplicatedLogsFiltered = handleFilterCallsWithOptions(criteria.method, finalOptions, this.filterCallsByMethod, maybeDuplicatedLogsFiltered);
|
||||
}
|
||||
const uniqLogsFiltered = [...new Set(maybeDuplicatedLogsFiltered)];
|
||||
return uniqLogsFiltered;
|
||||
}
|
||||
throw new InvalidArgumentError("criteria parameter should be one of function, regexp, or object");
|
||||
}
|
||||
filterCallsByProtocol = makeFilterCalls.call(this, "protocol");
|
||||
filterCallsByHost = makeFilterCalls.call(this, "host");
|
||||
filterCallsByPort = makeFilterCalls.call(this, "port");
|
||||
filterCallsByOrigin = makeFilterCalls.call(this, "origin");
|
||||
filterCallsByPath = makeFilterCalls.call(this, "path");
|
||||
filterCallsByHash = makeFilterCalls.call(this, "hash");
|
||||
filterCallsByFullUrl = makeFilterCalls.call(this, "fullUrl");
|
||||
filterCallsByMethod = makeFilterCalls.call(this, "method");
|
||||
clear() {
|
||||
this.logs = [];
|
||||
}
|
||||
[kMockCallHistoryAddLog](requestInit) {
|
||||
const log = new MockCallHistoryLog(requestInit);
|
||||
this.logs.push(log);
|
||||
return log;
|
||||
}
|
||||
*[Symbol.iterator]() {
|
||||
for (const log of this.calls()) {
|
||||
yield log;
|
||||
}
|
||||
}
|
||||
};
|
||||
module2.exports.MockCallHistory = MockCallHistory;
|
||||
module2.exports.MockCallHistoryLog = MockCallHistoryLog;
|
||||
}
|
||||
});
|
||||
|
||||
// node_modules/undici/lib/mock/mock-pool.js
|
||||
var require_mock_pool2 = __commonJS({
|
||||
"node_modules/undici/lib/mock/mock-pool.js"(exports2, module2) {
|
||||
@@ -30881,26 +31098,37 @@ var require_mock_agent2 = __commonJS({
|
||||
kNetConnect,
|
||||
kGetNetConnect,
|
||||
kOptions,
|
||||
kFactory
|
||||
kFactory,
|
||||
kMockAgentRegisterCallHistory,
|
||||
kMockAgentIsCallHistoryEnabled,
|
||||
kMockAgentAddCallHistoryLog,
|
||||
kMockAgentMockCallHistoryInstance,
|
||||
kMockCallHistoryAddLog
|
||||
} = require_mock_symbols2();
|
||||
var MockClient = require_mock_client2();
|
||||
var MockPool = require_mock_pool2();
|
||||
var { matchValue, buildMockOptions } = require_mock_utils2();
|
||||
var { matchValue, buildAndValidateMockOptions } = require_mock_utils2();
|
||||
var { InvalidArgumentError, UndiciError } = require_errors2();
|
||||
var Dispatcher = require_dispatcher2();
|
||||
var PendingInterceptorsFormatter = require_pending_interceptors_formatter2();
|
||||
var { MockCallHistory } = require_mock_call_history();
|
||||
var MockAgent = class extends Dispatcher {
|
||||
constructor(opts) {
|
||||
super(opts);
|
||||
const mockOptions = buildAndValidateMockOptions(opts);
|
||||
this[kNetConnect] = true;
|
||||
this[kIsMockActive] = true;
|
||||
this[kMockAgentIsCallHistoryEnabled] = mockOptions?.enableCallHistory ?? false;
|
||||
if (opts?.agent && typeof opts.agent.dispatch !== "function") {
|
||||
throw new InvalidArgumentError("Argument opts.agent must implement Agent");
|
||||
}
|
||||
const agent = opts?.agent ? opts.agent : new Agent(opts);
|
||||
this[kAgent] = agent;
|
||||
this[kClients] = agent[kClients];
|
||||
this[kOptions] = buildMockOptions(opts);
|
||||
this[kOptions] = mockOptions;
|
||||
if (this[kMockAgentIsCallHistoryEnabled]) {
|
||||
this[kMockAgentRegisterCallHistory]();
|
||||
}
|
||||
}
|
||||
get(origin) {
|
||||
let dispatcher = this[kMockAgentGet](origin);
|
||||
@@ -30912,9 +31140,11 @@ var require_mock_agent2 = __commonJS({
|
||||
}
|
||||
dispatch(opts, handler) {
|
||||
this.get(opts.origin);
|
||||
this[kMockAgentAddCallHistoryLog](opts);
|
||||
return this[kAgent].dispatch(opts, handler);
|
||||
}
|
||||
async close() {
|
||||
this.clearCallHistory();
|
||||
await this[kAgent].close();
|
||||
this[kClients].clear();
|
||||
}
|
||||
@@ -30940,11 +31170,38 @@ var require_mock_agent2 = __commonJS({
|
||||
disableNetConnect() {
|
||||
this[kNetConnect] = false;
|
||||
}
|
||||
enableCallHistory() {
|
||||
this[kMockAgentIsCallHistoryEnabled] = true;
|
||||
return this;
|
||||
}
|
||||
disableCallHistory() {
|
||||
this[kMockAgentIsCallHistoryEnabled] = false;
|
||||
return this;
|
||||
}
|
||||
getCallHistory() {
|
||||
return this[kMockAgentMockCallHistoryInstance];
|
||||
}
|
||||
clearCallHistory() {
|
||||
if (this[kMockAgentMockCallHistoryInstance] !== void 0) {
|
||||
this[kMockAgentMockCallHistoryInstance].clear();
|
||||
}
|
||||
}
|
||||
// This is required to bypass issues caused by using global symbols - see:
|
||||
// https://github.com/nodejs/undici/issues/1447
|
||||
get isMockActive() {
|
||||
return this[kIsMockActive];
|
||||
}
|
||||
[kMockAgentRegisterCallHistory]() {
|
||||
if (this[kMockAgentMockCallHistoryInstance] === void 0) {
|
||||
this[kMockAgentMockCallHistoryInstance] = new MockCallHistory();
|
||||
}
|
||||
}
|
||||
[kMockAgentAddCallHistoryLog](opts) {
|
||||
if (this[kMockAgentIsCallHistoryEnabled]) {
|
||||
this[kMockAgentRegisterCallHistory]();
|
||||
this[kMockAgentMockCallHistoryInstance][kMockCallHistoryAddLog](opts);
|
||||
}
|
||||
}
|
||||
[kMockAgentSet](origin, dispatcher) {
|
||||
this[kClients].set(origin, dispatcher);
|
||||
}
|
||||
@@ -31810,10 +32067,13 @@ var require_cache2 = __commonJS({
|
||||
if (typeof key !== "string" || typeof val !== "string") {
|
||||
throw new Error("opts.headers is not a valid header map");
|
||||
}
|
||||
headers[key] = val;
|
||||
headers[key.toLowerCase()] = val;
|
||||
}
|
||||
} else if (typeof opts.headers === "object") {
|
||||
headers = opts.headers;
|
||||
headers = {};
|
||||
for (const key of Object.keys(opts.headers)) {
|
||||
headers[key.toLowerCase()] = opts.headers[key];
|
||||
}
|
||||
} else {
|
||||
throw new Error("opts.headers is not an object");
|
||||
}
|
||||
@@ -31968,17 +32228,13 @@ var require_cache2 = __commonJS({
|
||||
return headers;
|
||||
}
|
||||
const output = (
|
||||
/** @type {Record<string, string | string[]>} */
|
||||
/** @type {Record<string, string | string[] | null>} */
|
||||
{}
|
||||
);
|
||||
const varyingHeaders = typeof varyHeader === "string" ? varyHeader.split(",") : varyHeader;
|
||||
for (const header of varyingHeaders) {
|
||||
const trimmedHeader = header.trim().toLowerCase();
|
||||
if (headers[trimmedHeader]) {
|
||||
output[trimmedHeader] = headers[trimmedHeader];
|
||||
} else {
|
||||
return void 0;
|
||||
}
|
||||
output[trimmedHeader] = headers[trimmedHeader] ?? null;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -32560,7 +32816,12 @@ var require_memory_cache_store = __commonJS({
|
||||
assertCacheKey(key);
|
||||
const topLevelKey = `${key.origin}:${key.path}`;
|
||||
const now = Date.now();
|
||||
const entry = this.#entries.get(topLevelKey)?.find((entry2) => entry2.deleteAt > now && entry2.method === key.method && (entry2.vary == null || Object.keys(entry2.vary).every((headerName) => entry2.vary[headerName] === key.headers?.[headerName])));
|
||||
const entry = this.#entries.get(topLevelKey)?.find((entry2) => entry2.deleteAt > now && entry2.method === key.method && (entry2.vary == null || Object.keys(entry2.vary).every((headerName) => {
|
||||
if (entry2.vary[headerName] === null) {
|
||||
return key.headers[headerName] === void 0;
|
||||
}
|
||||
return entry2.vary[headerName] === key.headers[headerName];
|
||||
})));
|
||||
return entry == null ? void 0 : {
|
||||
statusMessage: entry.statusMessage,
|
||||
statusCode: entry.statusCode,
|
||||
@@ -33146,7 +33407,7 @@ var require_sqlite_cache_store = __commonJS({
|
||||
assertCacheKey(key);
|
||||
const value = this.#findValue(key);
|
||||
return value ? {
|
||||
body: value.body ? Buffer.from(value.body.buffer) : void 0,
|
||||
body: value.body ? Buffer.from(value.body.buffer, value.body.byteOffset, value.body.byteLength) : void 0,
|
||||
statusCode: value.statusCode,
|
||||
statusMessage: value.statusMessage,
|
||||
headers: value.headers ? JSON.parse(value.headers) : void 0,
|
||||
@@ -33291,9 +33552,6 @@ var require_sqlite_cache_store = __commonJS({
|
||||
}
|
||||
let matches = true;
|
||||
if (value.vary) {
|
||||
if (!headers) {
|
||||
return void 0;
|
||||
}
|
||||
const vary = JSON.parse(value.vary);
|
||||
for (const header in vary) {
|
||||
if (!headerValueEquals(headers[header], vary[header])) {
|
||||
@@ -33310,16 +33568,17 @@ var require_sqlite_cache_store = __commonJS({
|
||||
}
|
||||
};
|
||||
function headerValueEquals(lhs, rhs) {
|
||||
if (lhs == null && rhs == null) {
|
||||
return true;
|
||||
}
|
||||
if (lhs == null && rhs != null || lhs != null && rhs == null) {
|
||||
return false;
|
||||
}
|
||||
if (Array.isArray(lhs) && Array.isArray(rhs)) {
|
||||
if (lhs.length !== rhs.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < lhs.length; i++) {
|
||||
if (rhs.includes(lhs[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return lhs.every((x, i) => x === rhs[i]);
|
||||
}
|
||||
return lhs === rhs;
|
||||
}
|
||||
@@ -34285,6 +34544,12 @@ var require_request4 = __commonJS({
|
||||
signal.removeEventListener("abort", abort);
|
||||
});
|
||||
var dependentControllerMap = /* @__PURE__ */ new WeakMap();
|
||||
var abortSignalHasEventHandlerLeakWarning;
|
||||
try {
|
||||
abortSignalHasEventHandlerLeakWarning = getMaxListeners(new AbortController().signal) > 0;
|
||||
} catch {
|
||||
abortSignalHasEventHandlerLeakWarning = false;
|
||||
}
|
||||
function buildAbort(acRef) {
|
||||
return abort;
|
||||
function abort() {
|
||||
@@ -34512,11 +34777,8 @@ var require_request4 = __commonJS({
|
||||
this[kAbortController] = ac;
|
||||
const acRef = new WeakRef(ac);
|
||||
const abort = buildAbort(acRef);
|
||||
try {
|
||||
if (typeof getMaxListeners === "function" && getMaxListeners(signal) === defaultMaxListeners) {
|
||||
setMaxListeners(1500, signal);
|
||||
}
|
||||
} catch {
|
||||
if (abortSignalHasEventHandlerLeakWarning && getMaxListeners(signal) === defaultMaxListeners) {
|
||||
setMaxListeners(1500, signal);
|
||||
}
|
||||
util.addAbortListener(signal, abort);
|
||||
requestFinalizer.register(ac, { signal, abort }, abort);
|
||||
@@ -39802,6 +40064,7 @@ var require_undici2 = __commonJS({
|
||||
var api = require_api2();
|
||||
var buildConnector = require_connect2();
|
||||
var MockClient = require_mock_client2();
|
||||
var { MockCallHistory, MockCallHistoryLog } = require_mock_call_history();
|
||||
var MockAgent = require_mock_agent2();
|
||||
var MockPool = require_mock_pool2();
|
||||
var mockErrors = require_mock_errors2();
|
||||
@@ -39924,6 +40187,8 @@ var require_undici2 = __commonJS({
|
||||
module2.exports.connect = makeDispatcher(api.connect);
|
||||
module2.exports.upgrade = makeDispatcher(api.upgrade);
|
||||
module2.exports.MockClient = MockClient;
|
||||
module2.exports.MockCallHistory = MockCallHistory;
|
||||
module2.exports.MockCallHistoryLog = MockCallHistoryLog;
|
||||
module2.exports.MockPool = MockPool;
|
||||
module2.exports.MockAgent = MockAgent;
|
||||
module2.exports.mockErrors = mockErrors;
|
||||
|
||||
@@ -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<string, string>}
|
||||
*/
|
||||
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);
|
||||
}
|
||||
+22
-16
@@ -6,6 +6,7 @@ import pRetry from "p-retry";
|
||||
* @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
|
||||
@@ -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,31 +86,32 @@ export async function main(
|
||||
request,
|
||||
auth,
|
||||
parsedOwner,
|
||||
parsedRepositoryNames
|
||||
parsedRepositoryNames,
|
||||
permissions,
|
||||
),
|
||||
{
|
||||
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
|
||||
({ authentication, installationId, appSlug } = await pRetry(
|
||||
() => getTokenFromOwner(request, auth, parsedOwner),
|
||||
() => getTokenFromOwner(request, auth, parsedOwner, permissions),
|
||||
{
|
||||
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 +129,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 +143,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 +156,8 @@ async function getTokenFromRepository(
|
||||
request,
|
||||
auth,
|
||||
parsedOwner,
|
||||
parsedRepositoryNames
|
||||
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", {
|
||||
@@ -168,6 +173,7 @@ async function getTokenFromRepository(
|
||||
type: "installation",
|
||||
installationId: response.data.id,
|
||||
repositoryNames: parsedRepositoryNames,
|
||||
permissions,
|
||||
});
|
||||
|
||||
const installationId = response.data.id;
|
||||
|
||||
+1
-1
@@ -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)) {
|
||||
|
||||
@@ -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 '<owner>/<repo>'");
|
||||
@@ -25,24 +26,29 @@ 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"),
|
||||
);
|
||||
|
||||
main(
|
||||
const permissions = getPermissionsFromInputs(process.env);
|
||||
|
||||
// Export promise for testing
|
||||
export default main(
|
||||
appId,
|
||||
privateKey,
|
||||
owner,
|
||||
repositories,
|
||||
permissions,
|
||||
core,
|
||||
createAppAuth,
|
||||
request,
|
||||
skipTokenRevoke
|
||||
skipTokenRevoke,
|
||||
).catch((error) => {
|
||||
/* c8 ignore next 3 */
|
||||
console.error(error);
|
||||
|
||||
Generated
+61
-47
@@ -1,21 +1,22 @@
|
||||
{
|
||||
"name": "create-github-app-token",
|
||||
"version": "1.11.4",
|
||||
"version": "1.11.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "create-github-app-token",
|
||||
"version": "1.11.4",
|
||||
"version": "1.11.6",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@octokit/auth-app": "^7.1.4",
|
||||
"@octokit/auth-app": "^7.1.5",
|
||||
"@octokit/request": "^9.2.2",
|
||||
"p-retry": "^6.2.1",
|
||||
"undici": "^7.3.0"
|
||||
"undici": "^7.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/openapi": "^18.0.0",
|
||||
"@sinonjs/fake-timers": "^14.0.0",
|
||||
"ava": "^6.2.0",
|
||||
"c8": "^10.1.3",
|
||||
@@ -53,9 +54,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client/node_modules/undici": {
|
||||
"version": "5.28.4",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
|
||||
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
|
||||
"version": "5.29.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz",
|
||||
"integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
@@ -670,16 +672,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-app": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.1.4.tgz",
|
||||
"integrity": "sha512-5F+3l/maq9JfWQ4bV28jT2G/K8eu9OJ317yzXPTGe4Kw+lKDhFaS4dQ3Ltmb6xImKxfCQdqDqMXODhc9YLipLw==",
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-app/-/auth-app-7.1.5.tgz",
|
||||
"integrity": "sha512-boklS4E6LpbA3nRx+SU2fRKRGZJdOGoSZne/i3Y0B5rfHOcGwFgcXrwDLdtbv4igfDSnAkZaoNBv1GYjPDKRNw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-oauth-app": "^8.1.2",
|
||||
"@octokit/auth-oauth-user": "^5.1.2",
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/request-error": "^6.1.6",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"@octokit/auth-oauth-app": "^8.1.3",
|
||||
"@octokit/auth-oauth-user": "^5.1.3",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.8.0",
|
||||
"toad-cache": "^3.7.0",
|
||||
"universal-github-app-jwt": "^2.2.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
@@ -689,14 +691,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-oauth-app": {
|
||||
"version": "8.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.2.tgz",
|
||||
"integrity": "sha512-3woNZgq5/S6RS+9ZTq+JdymxVr7E0s4EYxF20ugQvgX3pomdPUL5r/XdTY9wALoBM2eHVy4ettr5fKpatyTyHw==",
|
||||
"version": "8.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-oauth-app/-/auth-oauth-app-8.1.3.tgz",
|
||||
"integrity": "sha512-4e6OjVe5rZ8yBe8w7byBjpKtSXFuro7gqeGAAZc7QYltOF8wB93rJl2FE0a4U1Mt88xxPv/mS+25/0DuLk0Ewg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-oauth-device": "^7.1.2",
|
||||
"@octokit/auth-oauth-user": "^5.1.2",
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/auth-oauth-device": "^7.1.3",
|
||||
"@octokit/auth-oauth-user": "^5.1.3",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
@@ -705,13 +707,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-oauth-device": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.2.tgz",
|
||||
"integrity": "sha512-gTOIzDeV36OhVfxCl69FmvJix7tJIiU6dlxuzLVAzle7fYfO8UDyddr9B+o4CFQVaMBLMGZ9ak2CWMYcGeZnPw==",
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-oauth-device/-/auth-oauth-device-7.1.3.tgz",
|
||||
"integrity": "sha512-BECO/N4B/Uikj0w3GCvjf/odMujtYTP3q82BJSjxC2J3rxTEiZIJ+z2xnRlDb0IE9dQSaTgRqUPVOieSbFcVzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/oauth-methods": "^5.1.3",
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/oauth-methods": "^5.1.4",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
@@ -720,14 +722,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-oauth-user": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.2.tgz",
|
||||
"integrity": "sha512-PgVDDPJgZYb3qSEXK4moksA23tfn68zwSAsQKZ1uH6IV9IaNEYx35OXXI80STQaLYnmEE86AgU0tC1YkM4WjsA==",
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-oauth-user/-/auth-oauth-user-5.1.3.tgz",
|
||||
"integrity": "sha512-zNPByPn9K7TC+OOHKGxU+MxrE9SZAN11UHYEFLsK2NRn3akJN2LHRl85q+Eypr3tuB2GrKx3rfj2phJdkYCvzw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-oauth-device": "^7.1.2",
|
||||
"@octokit/oauth-methods": "^5.1.2",
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/auth-oauth-device": "^7.1.3",
|
||||
"@octokit/oauth-methods": "^5.1.3",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/types": "^13.6.2",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
@@ -758,24 +760,35 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/oauth-methods": {
|
||||
"version": "5.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.3.tgz",
|
||||
"integrity": "sha512-M+bDBi5H8FnH0xhCTg0m9hvcnppdDnxUqbZyOkxlLblKpLAR+eT2nbDPvJDp0eLrvJWA1I8OX0KHf/sBMQARRA==",
|
||||
"version": "5.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/oauth-methods/-/oauth-methods-5.1.4.tgz",
|
||||
"integrity": "sha512-Jc/ycnePClOvO1WL7tlC+TRxOFtyJBGuTDsL4dzXNiVZvzZdrPuNw7zHI3qJSUX2n6RLXE5L0SkFmYyNaVUFoQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/oauth-authorization-url": "^7.0.0",
|
||||
"@octokit/request": "^9.1.4",
|
||||
"@octokit/request-error": "^6.1.6",
|
||||
"@octokit/request": "^9.2.1",
|
||||
"@octokit/request-error": "^6.1.7",
|
||||
"@octokit/types": "^13.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi": {
|
||||
"version": "18.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi/-/openapi-18.0.0.tgz",
|
||||
"integrity": "sha512-N1khK+uLrWkyJ6J/kjYfhD4NnTsgU+xf1av6Ui9an5Z7Now5ZzUvUkKgymbmfGb+yjPHM/jQG2Ql4RWKw/AkpA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "22.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz",
|
||||
"integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg=="
|
||||
"version": "23.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
|
||||
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "9.2.2",
|
||||
@@ -806,11 +819,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "13.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz",
|
||||
"integrity": "sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==",
|
||||
"version": "13.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
|
||||
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^22.2.0"
|
||||
"@octokit/openapi-types": "^23.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
@@ -3637,9 +3651,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-7.3.0.tgz",
|
||||
"integrity": "sha512-Qy96NND4Dou5jKoSJ2gm8ax8AJM/Ey9o9mz7KN1bb9GP+G0l20Zw8afxTnY2f4b7hmhn/z8aC2kfArVQlAhFBw==",
|
||||
"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"
|
||||
|
||||
+4
-3
@@ -2,7 +2,7 @@
|
||||
"name": "create-github-app-token",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"version": "1.11.5",
|
||||
"version": "1.12.0",
|
||||
"description": "GitHub Action for creating a GitHub App Installation Access Token",
|
||||
"scripts": {
|
||||
"build": "esbuild main.js post.js --bundle --outdir=dist --out-extension:.js=.cjs --platform=node --target=node20.0.0 --packages=bundle",
|
||||
@@ -13,12 +13,13 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@octokit/auth-app": "^7.1.4",
|
||||
"@octokit/auth-app": "^7.1.5",
|
||||
"@octokit/request": "^9.2.2",
|
||||
"p-retry": "^6.2.1",
|
||||
"undici": "^7.3.0"
|
||||
"undici": "^7.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@octokit/openapi": "^18.0.0",
|
||||
"@sinonjs/fake-timers": "^14.0.0",
|
||||
"ava": "^6.2.0",
|
||||
"c8": "^10.1.3",
|
||||
|
||||
@@ -0,0 +1,395 @@
|
||||
{
|
||||
"title": "App Permissions",
|
||||
"type": "object",
|
||||
"description": "The permissions granted to the user access token.",
|
||||
"properties": {
|
||||
"actions": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for GitHub Actions workflows, workflow runs, and artifacts.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"administration": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for repository creation, deletion, settings, teams, and collaborators creation.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"checks": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for checks on code.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"codespaces": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to create, edit, delete, and list Codespaces.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"contents": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for repository contents, commits, branches, downloads, releases, and merges.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"dependabot_secrets": {
|
||||
"type": "string",
|
||||
"description": "The leve of permission to grant the access token to manage Dependabot secrets.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"deployments": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for deployments and deployment statuses.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"environments": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for managing repository environments.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"issues": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for issues and related comments, assignees, labels, and milestones.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"metadata": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"packages": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for packages published to GitHub Packages.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"pages": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to retrieve Pages statuses, configuration, and builds, as well as create new builds.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"pull_requests": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for pull requests and related comments, assignees, labels, milestones, and merges.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"repository_custom_properties": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and edit custom properties for a repository, when allowed by the property.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"repository_hooks": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage the post-receive hooks for a repository.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"repository_projects": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage repository projects, columns, and cards.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write",
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
"secret_scanning_alerts": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage secret scanning alerts.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"secrets": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage repository secrets.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"security_events": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage security events like code scanning alerts.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"single_file": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage just a single file.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"statuses": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for commit statuses.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"vulnerability_alerts": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage Dependabot alerts.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"workflows": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to update GitHub Actions workflow files.",
|
||||
"enum": [
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"members": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for organization teams and members.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_administration": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage access to an organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_custom_roles": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for custom repository roles management.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_custom_org_roles": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for custom organization roles management.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_custom_properties": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for custom property management.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write",
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
"organization_copilot_seat_management": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for managing access to GitHub Copilot for members of an organization with a Copilot Business subscription. This property is in public preview and is subject to change.",
|
||||
"enum": [
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_announcement_banners": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage announcement banners for an organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_events": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view events triggered by an activity in an organization.",
|
||||
"enum": [
|
||||
"read"
|
||||
]
|
||||
},
|
||||
"organization_hooks": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage the post-receive hooks for an organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_personal_access_tokens": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for viewing and managing fine-grained personal access token requests to an organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_personal_access_token_requests": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for viewing and managing fine-grained personal access tokens that have been approved by an organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_plan": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for viewing an organization's plan.",
|
||||
"enum": [
|
||||
"read"
|
||||
]
|
||||
},
|
||||
"organization_projects": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage organization projects and projects public preview (where available).",
|
||||
"enum": [
|
||||
"read",
|
||||
"write",
|
||||
"admin"
|
||||
]
|
||||
},
|
||||
"organization_packages": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token for organization packages published to GitHub Packages.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_secrets": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage organization secrets.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_self_hosted_runners": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage GitHub Actions self-hosted runners available to an organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"organization_user_blocking": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage users blocked by the organization.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"team_discussions": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage team discussions and related comments.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"email_addresses": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage the email addresses belonging to a user.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"followers": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage the followers belonging to a user.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"git_ssh_keys": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage git SSH keys.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"gpg_keys": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage GPG keys belonging to a user.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"interaction_limits": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to view and manage interaction limits on a repository.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"profile": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to manage the profile settings belonging to a user.",
|
||||
"enum": [
|
||||
"write"
|
||||
]
|
||||
},
|
||||
"starring": {
|
||||
"type": "string",
|
||||
"description": "The level of permission to grant the access token to list and manage repositories a user is starring.",
|
||||
"enum": [
|
||||
"read",
|
||||
"write"
|
||||
]
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"contents": "read",
|
||||
"issues": "read",
|
||||
"deployments": "write",
|
||||
"single_file": "read"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
|
||||
import OctokitOpenapi from "@octokit/openapi";
|
||||
|
||||
const appPermissionsSchema =
|
||||
OctokitOpenapi.schemas["api.github.com"].components.schemas[
|
||||
"app-permissions"
|
||||
];
|
||||
|
||||
await writeFile(
|
||||
`scripts/generated/app-permissions.json`,
|
||||
JSON.stringify(appPermissionsSchema, null, 2) + "\n",
|
||||
"utf8"
|
||||
);
|
||||
|
||||
const permissionsInputs = Object.entries(appPermissionsSchema.properties)
|
||||
.sort((a, b) => a[0].localeCompare(b[0]))
|
||||
.reduce((result, [key, value]) => {
|
||||
const formatter = new Intl.ListFormat("en", {
|
||||
style: "long",
|
||||
type: "disjunction",
|
||||
});
|
||||
const permissionAccessValues = formatter.format(
|
||||
value.enum.map((p) => `'${p}'`)
|
||||
);
|
||||
|
||||
const description = `${value.description} Can be set to ${permissionAccessValues}.`;
|
||||
return `${result}
|
||||
permission-${key.replace(/_/g, "-")}:
|
||||
description: "${description}"`;
|
||||
}, "");
|
||||
|
||||
const actionsYamlContent = await readFile("action.yml", "utf8");
|
||||
|
||||
// In the action.yml file, replace the content between the `<START GENERATED PERMISSIONS INPUTS>` and `<END GENERATED PERMISSIONS INPUTS>` comments with the new content
|
||||
const updatedActionsYamlContent = actionsYamlContent.replace(
|
||||
/(?<=# <START GENERATED PERMISSIONS INPUTS>)(.|\n)*(?=# <END GENERATED PERMISSIONS INPUTS>)/,
|
||||
permissionsInputs + "\n "
|
||||
);
|
||||
|
||||
await writeFile("action.yml", updatedActionsYamlContent, "utf8");
|
||||
console.log("Updated action.yml with new permissions inputs");
|
||||
@@ -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.
|
||||
|
||||
@@ -4,10 +4,10 @@ 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";
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ await test((mockPool) => {
|
||||
const mockAppSlug = "github-actions";
|
||||
mockPool
|
||||
.intercept({
|
||||
path: `/users/${process.env.INPUT_OWNER}/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: `/users/${process.env.INPUT_OWNER}/installation`,
|
||||
path: `/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" } },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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" } },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -21,6 +21,6 @@ await test((mockPool) => {
|
||||
.reply(
|
||||
200,
|
||||
{ id: mockInstallationId, app_slug: mockAppSlug },
|
||||
{ headers: { "content-type": "application/json" } }
|
||||
{ headers: { "content-type": "application/json" } },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -20,7 +20,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" } },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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`;
|
||||
});
|
||||
+21
-5
@@ -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);
|
||||
@@ -60,8 +60,9 @@ 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],
|
||||
);
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: `${basePath}/repos/${owner}/${repo}/installation`,
|
||||
@@ -75,13 +76,14 @@ 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";
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: `${basePath}/app/installations/${mockInstallationId}/access_tokens`,
|
||||
@@ -95,12 +97,26 @@ export async function test(cb = (_mockPool) => {}, env = DEFAULT_ENV) {
|
||||
.reply(
|
||||
201,
|
||||
{ token: mockInstallationAccessToken, expires_at: mockExpiresAt },
|
||||
{ headers: { "content-type": "application/json" } }
|
||||
{ headers: { "content-type": "application/json" } },
|
||||
);
|
||||
|
||||
// Run the callback
|
||||
cb(mockPool);
|
||||
|
||||
// Run the main script
|
||||
await import("../main.js");
|
||||
const { default: promise } = await import("../main.js");
|
||||
await promise;
|
||||
|
||||
console.log("--- REQUESTS ---");
|
||||
const calls = mockAgent
|
||||
.getCallHistory()
|
||||
.calls()
|
||||
.map((call) => {
|
||||
const route = `${call.method} ${call.path}`;
|
||||
if (call.method === "GET") return route;
|
||||
|
||||
return `${route}\n${call.body}`;
|
||||
});
|
||||
|
||||
console.log(calls.join("\n"));
|
||||
}
|
||||
|
||||
+81
-11
@@ -33,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
|
||||
|
||||
@@ -92,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
|
||||
|
||||
@@ -112,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
|
||||
|
||||
@@ -132,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
|
||||
|
||||
@@ -152,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
|
||||
|
||||
@@ -171,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
|
||||
|
||||
@@ -190,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
|
||||
|
||||
@@ -209,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
|
||||
|
||||
@@ -228,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
|
||||
|
||||
@@ -247,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
|
||||
|
||||
@@ -266,7 +309,34 @@ 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
|
||||
|
||||
> stderr
|
||||
|
||||
''
|
||||
|
||||
> stdout
|
||||
|
||||
`owner and repositories not set, creating token for the current repository ("create-github-app-token")␊
|
||||
::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␊
|
||||
--- 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
|
||||
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user