fix: require NODE_USE_ENV_PROXY for proxy support (#342)
This PR switches proxy support to Node's native env-proxy handling and makes the required configuration explicit. ## What changed - fail fast in both `main` and `post` when proxy configuration is present without `NODE_USE_ENV_PROXY=1` - document the supported proxy configuration in `README.md` - add regression tests for the proxy guard in both entrypoints - keep the existing successful end-to-end coverage and add a smaller proxy-specific workflow check that enables native proxy support, points `https_proxy` at an unreachable proxy, and asserts the action fails - update the test workflow so the same checks also run on pushes to `beta` ## Proxy configuration When using `HTTP_PROXY` or `HTTPS_PROXY`, set `NODE_USE_ENV_PROXY=1` on the action step. If you need bypass rules, set `NO_PROXY` alongside them. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
- beta
|
||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ jobs:
|
|||||||
name: End-to-End
|
name: End-to-End
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# do not run from forks, as forks don’t have access to repository secrets
|
# do not run from forks, as forks don’t have access to repository secrets
|
||||||
if: github.event.pull_request.head.repo.owner.login == github.event.pull_request.base.repo.owner.login
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.event.pull_request.base.repo.owner.login
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
@@ -54,3 +55,28 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
route: GET /installation/repositories
|
route: GET /installation/repositories
|
||||||
- run: echo '${{ steps.get-repository.outputs.data }}'
|
- run: echo '${{ steps.get-repository.outputs.data }}'
|
||||||
|
|
||||||
|
end-to-end-proxy:
|
||||||
|
name: End-to-End with unreachable proxy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# do not run from forks, as forks don’t have access to repository secrets
|
||||||
|
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.owner.login == github.event.pull_request.base.repo.owner.login
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: package.json
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build
|
||||||
|
- uses: ./ # Uses the action in the root directory
|
||||||
|
continue-on-error: true
|
||||||
|
id: test
|
||||||
|
env:
|
||||||
|
NODE_USE_ENV_PROXY: "1"
|
||||||
|
https_proxy: http://127.0.0.1:9
|
||||||
|
with:
|
||||||
|
app-id: ${{ vars.TEST_APP_ID }}
|
||||||
|
private-key: ${{ secrets.TEST_APP_PRIVATE_KEY }}
|
||||||
|
- name: Assert action failed through unreachable proxy
|
||||||
|
run: test "${{ steps.test.outcome }}" = "failure"
|
||||||
|
|||||||
@@ -296,6 +296,24 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ steps.create_token.outputs.token }}
|
GITHUB_TOKEN: ${{ steps.create_token.outputs.token }}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Proxy support
|
||||||
|
|
||||||
|
This action relies on Node.js native proxy support.
|
||||||
|
|
||||||
|
If you set `HTTP_PROXY` or `HTTPS_PROXY`, also set `NODE_USE_ENV_PROXY: "1"` on the action step so Node.js honors those variables. If you need proxy bypass rules, set `NO_PROXY` alongside them.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/create-github-app-token@v3
|
||||||
|
id: app-token
|
||||||
|
env:
|
||||||
|
HTTPS_PROXY: http://proxy.example.com:8080
|
||||||
|
NO_PROXY: github.example.com
|
||||||
|
NODE_USE_ENV_PROXY: "1"
|
||||||
|
with:
|
||||||
|
app-id: ${{ vars.APP_ID }}
|
||||||
|
private-key: ${{ secrets.PRIVATE_KEY }}
|
||||||
|
```
|
||||||
|
|
||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
### `app-id`
|
### `app-id`
|
||||||
|
|||||||
Vendored
+103
-79
@@ -21294,11 +21294,11 @@ function createOAuthAppAuth(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// node_modules/universal-github-app-jwt/lib/utils.js
|
// node_modules/universal-github-app-jwt/lib/utils.js
|
||||||
function isPkcs1(privateKey2) {
|
function isPkcs1(privateKey) {
|
||||||
return privateKey2.includes("-----BEGIN RSA PRIVATE KEY-----");
|
return privateKey.includes("-----BEGIN RSA PRIVATE KEY-----");
|
||||||
}
|
}
|
||||||
function isOpenSsh(privateKey2) {
|
function isOpenSsh(privateKey) {
|
||||||
return privateKey2.includes("-----BEGIN OPENSSH PRIVATE KEY-----");
|
return privateKey.includes("-----BEGIN OPENSSH PRIVATE KEY-----");
|
||||||
}
|
}
|
||||||
function string2ArrayBuffer(str) {
|
function string2ArrayBuffer(str) {
|
||||||
const buf = new ArrayBuffer(str.length);
|
const buf = new ArrayBuffer(str.length);
|
||||||
@@ -21335,17 +21335,17 @@ function base64encodeJSON(obj) {
|
|||||||
// node_modules/universal-github-app-jwt/lib/crypto-node.js
|
// node_modules/universal-github-app-jwt/lib/crypto-node.js
|
||||||
var import_node_crypto = require("node:crypto");
|
var import_node_crypto = require("node:crypto");
|
||||||
var import_node_crypto2 = require("node:crypto");
|
var import_node_crypto2 = require("node:crypto");
|
||||||
function convertPrivateKey(privateKey2) {
|
function convertPrivateKey(privateKey) {
|
||||||
if (!isPkcs1(privateKey2)) return privateKey2;
|
if (!isPkcs1(privateKey)) return privateKey;
|
||||||
return (0, import_node_crypto2.createPrivateKey)(privateKey2).export({
|
return (0, import_node_crypto2.createPrivateKey)(privateKey).export({
|
||||||
type: "pkcs8",
|
type: "pkcs8",
|
||||||
format: "pem"
|
format: "pem"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// node_modules/universal-github-app-jwt/lib/get-token.js
|
// node_modules/universal-github-app-jwt/lib/get-token.js
|
||||||
async function getToken({ privateKey: privateKey2, payload }) {
|
async function getToken({ privateKey, payload }) {
|
||||||
const convertedPrivateKey = convertPrivateKey(privateKey2);
|
const convertedPrivateKey = convertPrivateKey(privateKey);
|
||||||
if (isPkcs1(convertedPrivateKey)) {
|
if (isPkcs1(convertedPrivateKey)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"[universal-github-app-jwt] Private Key is in PKCS#1 format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats"
|
"[universal-github-app-jwt] Private Key is in PKCS#1 format, but only PKCS#8 is supported. See https://github.com/gr2m/universal-github-app-jwt#private-key-formats"
|
||||||
@@ -21383,10 +21383,10 @@ async function getToken({ privateKey: privateKey2, payload }) {
|
|||||||
// node_modules/universal-github-app-jwt/index.js
|
// node_modules/universal-github-app-jwt/index.js
|
||||||
async function githubAppJwt({
|
async function githubAppJwt({
|
||||||
id,
|
id,
|
||||||
privateKey: privateKey2,
|
privateKey,
|
||||||
now = Math.floor(Date.now() / 1e3)
|
now = Math.floor(Date.now() / 1e3)
|
||||||
}) {
|
}) {
|
||||||
const privateKeyWithNewlines = privateKey2.replace(/\\n/g, "\n");
|
const privateKeyWithNewlines = privateKey.replace(/\\n/g, "\n");
|
||||||
const nowWithSafetyMargin = now - 30;
|
const nowWithSafetyMargin = now - 30;
|
||||||
const expiration = nowWithSafetyMargin + 60 * 10;
|
const expiration = nowWithSafetyMargin + 60 * 10;
|
||||||
const payload = {
|
const payload = {
|
||||||
@@ -21544,14 +21544,14 @@ var LruObject = class {
|
|||||||
|
|
||||||
// node_modules/@octokit/auth-app/dist-node/index.js
|
// node_modules/@octokit/auth-app/dist-node/index.js
|
||||||
async function getAppAuthentication({
|
async function getAppAuthentication({
|
||||||
appId: appId2,
|
appId,
|
||||||
privateKey: privateKey2,
|
privateKey,
|
||||||
timeDifference
|
timeDifference
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
const authOptions = {
|
const authOptions = {
|
||||||
id: appId2,
|
id: appId,
|
||||||
privateKey: privateKey2
|
privateKey
|
||||||
};
|
};
|
||||||
if (timeDifference) {
|
if (timeDifference) {
|
||||||
Object.assign(authOptions, {
|
Object.assign(authOptions, {
|
||||||
@@ -21566,7 +21566,7 @@ async function getAppAuthentication({
|
|||||||
expiresAt: new Date(appAuthentication.expiration * 1e3).toISOString()
|
expiresAt: new Date(appAuthentication.expiration * 1e3).toISOString()
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (privateKey2 === "-----BEGIN RSA PRIVATE KEY-----") {
|
if (privateKey === "-----BEGIN RSA PRIVATE KEY-----") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"The 'privateKey` option contains only the first line '-----BEGIN RSA PRIVATE KEY-----'. If you are setting it using a `.env` file, make sure it is set on a single line with newlines replaced by '\n'"
|
"The 'privateKey` option contains only the first line '-----BEGIN RSA PRIVATE KEY-----'. If you are setting it using a `.env` file, make sure it is set on a single line with newlines replaced by '\n'"
|
||||||
);
|
);
|
||||||
@@ -21597,19 +21597,19 @@ async function get(cache, options) {
|
|||||||
permissionsString,
|
permissionsString,
|
||||||
singleFileName
|
singleFileName
|
||||||
] = result.split("|");
|
] = result.split("|");
|
||||||
const permissions2 = options.permissions || permissionsString.split(/,/).reduce((permissions22, string) => {
|
const permissions = options.permissions || permissionsString.split(/,/).reduce((permissions2, string) => {
|
||||||
if (/!$/.test(string)) {
|
if (/!$/.test(string)) {
|
||||||
permissions22[string.slice(0, -1)] = "write";
|
permissions2[string.slice(0, -1)] = "write";
|
||||||
} else {
|
} else {
|
||||||
permissions22[string] = "read";
|
permissions2[string] = "read";
|
||||||
}
|
}
|
||||||
return permissions22;
|
return permissions2;
|
||||||
}, {});
|
}, {});
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
createdAt,
|
createdAt,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
permissions: permissions2,
|
permissions,
|
||||||
repositoryIds: options.repositoryIds,
|
repositoryIds: options.repositoryIds,
|
||||||
repositoryNames: options.repositoryNames,
|
repositoryNames: options.repositoryNames,
|
||||||
singleFileName,
|
singleFileName,
|
||||||
@@ -21633,11 +21633,11 @@ async function set(cache, options, data) {
|
|||||||
}
|
}
|
||||||
function optionsToCacheKey({
|
function optionsToCacheKey({
|
||||||
installationId,
|
installationId,
|
||||||
permissions: permissions2 = {},
|
permissions = {},
|
||||||
repositoryIds = [],
|
repositoryIds = [],
|
||||||
repositoryNames = []
|
repositoryNames = []
|
||||||
}) {
|
}) {
|
||||||
const permissionsString = Object.keys(permissions2).sort().map((name) => permissions2[name] === "read" ? name : `${name}!`).join(",");
|
const permissionsString = Object.keys(permissions).sort().map((name) => permissions[name] === "read" ? name : `${name}!`).join(",");
|
||||||
const repositoryIdsString = repositoryIds.sort().join(",");
|
const repositoryIdsString = repositoryIds.sort().join(",");
|
||||||
const repositoryNamesString = repositoryNames.join(",");
|
const repositoryNamesString = repositoryNames.join(",");
|
||||||
return [
|
return [
|
||||||
@@ -21653,7 +21653,7 @@ function toTokenAuthentication({
|
|||||||
createdAt,
|
createdAt,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
repositorySelection,
|
repositorySelection,
|
||||||
permissions: permissions2,
|
permissions,
|
||||||
repositoryIds,
|
repositoryIds,
|
||||||
repositoryNames,
|
repositoryNames,
|
||||||
singleFileName
|
singleFileName
|
||||||
@@ -21664,7 +21664,7 @@ function toTokenAuthentication({
|
|||||||
tokenType: "installation",
|
tokenType: "installation",
|
||||||
token,
|
token,
|
||||||
installationId,
|
installationId,
|
||||||
permissions: permissions2,
|
permissions,
|
||||||
createdAt,
|
createdAt,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
repositorySelection
|
repositorySelection
|
||||||
@@ -21717,7 +21717,7 @@ async function getInstallationAuthenticationImpl(state, options, request2) {
|
|||||||
token: token2,
|
token: token2,
|
||||||
createdAt: createdAt2,
|
createdAt: createdAt2,
|
||||||
expiresAt: expiresAt2,
|
expiresAt: expiresAt2,
|
||||||
permissions: permissions22,
|
permissions: permissions2,
|
||||||
repositoryIds: repositoryIds2,
|
repositoryIds: repositoryIds2,
|
||||||
repositoryNames: repositoryNames2,
|
repositoryNames: repositoryNames2,
|
||||||
singleFileName: singleFileName2,
|
singleFileName: singleFileName2,
|
||||||
@@ -21728,7 +21728,7 @@ async function getInstallationAuthenticationImpl(state, options, request2) {
|
|||||||
token: token2,
|
token: token2,
|
||||||
createdAt: createdAt2,
|
createdAt: createdAt2,
|
||||||
expiresAt: expiresAt2,
|
expiresAt: expiresAt2,
|
||||||
permissions: permissions22,
|
permissions: permissions2,
|
||||||
repositorySelection: repositorySelection2,
|
repositorySelection: repositorySelection2,
|
||||||
repositoryIds: repositoryIds2,
|
repositoryIds: repositoryIds2,
|
||||||
repositoryNames: repositoryNames2,
|
repositoryNames: repositoryNames2,
|
||||||
@@ -21761,7 +21761,7 @@ async function getInstallationAuthenticationImpl(state, options, request2) {
|
|||||||
data: {
|
data: {
|
||||||
token,
|
token,
|
||||||
expires_at: expiresAt,
|
expires_at: expiresAt,
|
||||||
repositories: repositories2,
|
repositories,
|
||||||
permissions: permissionsOptional,
|
permissions: permissionsOptional,
|
||||||
repository_selection: repositorySelectionOptional,
|
repository_selection: repositorySelectionOptional,
|
||||||
single_file: singleFileName
|
single_file: singleFileName
|
||||||
@@ -21770,17 +21770,17 @@ async function getInstallationAuthenticationImpl(state, options, request2) {
|
|||||||
"POST /app/installations/{installation_id}/access_tokens",
|
"POST /app/installations/{installation_id}/access_tokens",
|
||||||
payload
|
payload
|
||||||
);
|
);
|
||||||
const permissions2 = permissionsOptional || {};
|
const permissions = permissionsOptional || {};
|
||||||
const repositorySelection = repositorySelectionOptional || "all";
|
const repositorySelection = repositorySelectionOptional || "all";
|
||||||
const repositoryIds = repositories2 ? repositories2.map((r) => r.id) : void 0;
|
const repositoryIds = repositories ? repositories.map((r) => r.id) : void 0;
|
||||||
const repositoryNames = repositories2 ? repositories2.map((repo) => repo.name) : void 0;
|
const repositoryNames = repositories ? repositories.map((repo) => repo.name) : void 0;
|
||||||
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
||||||
const cacheOptions = {
|
const cacheOptions = {
|
||||||
token,
|
token,
|
||||||
createdAt,
|
createdAt,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
repositorySelection,
|
repositorySelection,
|
||||||
permissions: permissions2,
|
permissions,
|
||||||
repositoryIds,
|
repositoryIds,
|
||||||
repositoryNames
|
repositoryNames
|
||||||
};
|
};
|
||||||
@@ -21794,7 +21794,7 @@ async function getInstallationAuthenticationImpl(state, options, request2) {
|
|||||||
createdAt,
|
createdAt,
|
||||||
expiresAt,
|
expiresAt,
|
||||||
repositorySelection,
|
repositorySelection,
|
||||||
permissions: permissions2,
|
permissions,
|
||||||
repositoryIds,
|
repositoryIds,
|
||||||
repositoryNames
|
repositoryNames
|
||||||
};
|
};
|
||||||
@@ -21986,16 +21986,16 @@ function createAppAuth(options) {
|
|||||||
|
|
||||||
// lib/get-permissions-from-inputs.js
|
// lib/get-permissions-from-inputs.js
|
||||||
function getPermissionsFromInputs(env) {
|
function getPermissionsFromInputs(env) {
|
||||||
return Object.entries(env).reduce((permissions2, [key, value]) => {
|
return Object.entries(env).reduce((permissions, [key, value]) => {
|
||||||
if (!key.startsWith("INPUT_PERMISSION-")) return permissions2;
|
if (!key.startsWith("INPUT_PERMISSION-")) return permissions;
|
||||||
if (!value) return permissions2;
|
if (!value) return permissions;
|
||||||
const permission = key.slice("INPUT_PERMISSION-".length).toLowerCase().replaceAll(/-/g, "_");
|
const permission = key.slice("INPUT_PERMISSION-".length).toLowerCase().replaceAll(/-/g, "_");
|
||||||
if (permissions2 === void 0) {
|
if (permissions === void 0) {
|
||||||
return { [permission]: value };
|
return { [permission]: value };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
// @ts-expect-error - needs to be typed correctly
|
// @ts-expect-error - needs to be typed correctly
|
||||||
...permissions2,
|
...permissions,
|
||||||
[permission]: value
|
[permission]: value
|
||||||
};
|
};
|
||||||
}, void 0);
|
}, void 0);
|
||||||
@@ -22112,43 +22112,43 @@ async function pRetry(input, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lib/main.js
|
// lib/main.js
|
||||||
async function main(appId2, privateKey2, owner2, repositories2, permissions2, core3, createAppAuth2, request2, skipTokenRevoke2) {
|
async function main(appId, privateKey, owner, repositories, permissions, core3, createAppAuth2, request2, skipTokenRevoke) {
|
||||||
let parsedOwner = "";
|
let parsedOwner = "";
|
||||||
let parsedRepositoryNames = [];
|
let parsedRepositoryNames = [];
|
||||||
if (!owner2 && repositories2.length === 0) {
|
if (!owner && repositories.length === 0) {
|
||||||
const [owner3, repo] = String(process.env.GITHUB_REPOSITORY).split("/");
|
const [owner2, repo] = String(process.env.GITHUB_REPOSITORY).split("/");
|
||||||
parsedOwner = owner3;
|
parsedOwner = owner2;
|
||||||
parsedRepositoryNames = [repo];
|
parsedRepositoryNames = [repo];
|
||||||
core3.info(
|
core3.info(
|
||||||
`Inputs 'owner' and 'repositories' are not set. Creating token for this repository (${owner3}/${repo}).`
|
`Inputs 'owner' and 'repositories' are not set. Creating token for this repository (${owner2}/${repo}).`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (owner2 && repositories2.length === 0) {
|
if (owner && repositories.length === 0) {
|
||||||
parsedOwner = owner2;
|
parsedOwner = owner;
|
||||||
core3.info(
|
core3.info(
|
||||||
`Input 'repositories' is not set. Creating token for all repositories owned by ${owner2}.`
|
`Input 'repositories' is not set. Creating token for all repositories owned by ${owner}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!owner2 && repositories2.length > 0) {
|
if (!owner && repositories.length > 0) {
|
||||||
parsedOwner = String(process.env.GITHUB_REPOSITORY_OWNER);
|
parsedOwner = String(process.env.GITHUB_REPOSITORY_OWNER);
|
||||||
parsedRepositoryNames = repositories2;
|
parsedRepositoryNames = repositories;
|
||||||
core3.info(
|
core3.info(
|
||||||
`No 'owner' input provided. Using default owner '${parsedOwner}' to create token for the following repositories:${repositories2.map((repo) => `
|
`No 'owner' input provided. Using default owner '${parsedOwner}' to create token for the following repositories:${repositories.map((repo) => `
|
||||||
- ${parsedOwner}/${repo}`).join("")}`
|
- ${parsedOwner}/${repo}`).join("")}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (owner2 && repositories2.length > 0) {
|
if (owner && repositories.length > 0) {
|
||||||
parsedOwner = owner2;
|
parsedOwner = owner;
|
||||||
parsedRepositoryNames = repositories2;
|
parsedRepositoryNames = repositories;
|
||||||
core3.info(
|
core3.info(
|
||||||
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
|
`Inputs 'owner' and 'repositories' are set. Creating token for the following repositories:
|
||||||
${repositories2.map((repo) => `
|
${repositories.map((repo) => `
|
||||||
- ${parsedOwner}/${repo}`).join("")}`
|
- ${parsedOwner}/${repo}`).join("")}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const auth5 = createAppAuth2({
|
const auth5 = createAppAuth2({
|
||||||
appId: appId2,
|
appId,
|
||||||
privateKey: privateKey2,
|
privateKey,
|
||||||
request: request2
|
request: request2
|
||||||
});
|
});
|
||||||
let authentication, installationId, appSlug;
|
let authentication, installationId, appSlug;
|
||||||
@@ -22159,7 +22159,7 @@ async function main(appId2, privateKey2, owner2, repositories2, permissions2, co
|
|||||||
auth5,
|
auth5,
|
||||||
parsedOwner,
|
parsedOwner,
|
||||||
parsedRepositoryNames,
|
parsedRepositoryNames,
|
||||||
permissions2
|
permissions
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
shouldRetry: (error) => error.status >= 500,
|
shouldRetry: (error) => error.status >= 500,
|
||||||
@@ -22175,7 +22175,7 @@ async function main(appId2, privateKey2, owner2, repositories2, permissions2, co
|
|||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
({ authentication, installationId, appSlug } = await pRetry(
|
({ authentication, installationId, appSlug } = await pRetry(
|
||||||
() => getTokenFromOwner(request2, auth5, parsedOwner, permissions2),
|
() => getTokenFromOwner(request2, auth5, parsedOwner, permissions),
|
||||||
{
|
{
|
||||||
onFailedAttempt: (error) => {
|
onFailedAttempt: (error) => {
|
||||||
core3.info(
|
core3.info(
|
||||||
@@ -22190,12 +22190,12 @@ async function main(appId2, privateKey2, owner2, repositories2, permissions2, co
|
|||||||
core3.setOutput("token", authentication.token);
|
core3.setOutput("token", authentication.token);
|
||||||
core3.setOutput("installation-id", installationId);
|
core3.setOutput("installation-id", installationId);
|
||||||
core3.setOutput("app-slug", appSlug);
|
core3.setOutput("app-slug", appSlug);
|
||||||
if (!skipTokenRevoke2) {
|
if (!skipTokenRevoke) {
|
||||||
core3.saveState("token", authentication.token);
|
core3.saveState("token", authentication.token);
|
||||||
core3.saveState("expiresAt", authentication.expiresAt);
|
core3.saveState("expiresAt", authentication.expiresAt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function getTokenFromOwner(request2, auth5, parsedOwner, permissions2) {
|
async function getTokenFromOwner(request2, auth5, parsedOwner, permissions) {
|
||||||
const response = await request2("GET /users/{username}/installation", {
|
const response = await request2("GET /users/{username}/installation", {
|
||||||
username: parsedOwner,
|
username: parsedOwner,
|
||||||
request: {
|
request: {
|
||||||
@@ -22205,13 +22205,13 @@ async function getTokenFromOwner(request2, auth5, parsedOwner, permissions2) {
|
|||||||
const authentication = await auth5({
|
const authentication = await auth5({
|
||||||
type: "installation",
|
type: "installation",
|
||||||
installationId: response.data.id,
|
installationId: response.data.id,
|
||||||
permissions: permissions2
|
permissions
|
||||||
});
|
});
|
||||||
const installationId = response.data.id;
|
const installationId = response.data.id;
|
||||||
const appSlug = response.data["app_slug"];
|
const appSlug = response.data["app_slug"];
|
||||||
return { authentication, installationId, appSlug };
|
return { authentication, installationId, appSlug };
|
||||||
}
|
}
|
||||||
async function getTokenFromRepository(request2, auth5, parsedOwner, parsedRepositoryNames, permissions2) {
|
async function getTokenFromRepository(request2, auth5, parsedOwner, parsedRepositoryNames, permissions) {
|
||||||
const response = await request2("GET /repos/{owner}/{repo}/installation", {
|
const response = await request2("GET /repos/{owner}/{repo}/installation", {
|
||||||
owner: parsedOwner,
|
owner: parsedOwner,
|
||||||
repo: parsedRepositoryNames[0],
|
repo: parsedRepositoryNames[0],
|
||||||
@@ -22223,7 +22223,7 @@ async function getTokenFromRepository(request2, auth5, parsedOwner, parsedReposi
|
|||||||
type: "installation",
|
type: "installation",
|
||||||
installationId: response.data.id,
|
installationId: response.data.id,
|
||||||
repositoryNames: parsedRepositoryNames,
|
repositoryNames: parsedRepositoryNames,
|
||||||
permissions: permissions2
|
permissions
|
||||||
});
|
});
|
||||||
const installationId = response.data.id;
|
const installationId = response.data.id;
|
||||||
const appSlug = response.data["app_slug"];
|
const appSlug = response.data["app_slug"];
|
||||||
@@ -22233,6 +22233,26 @@ async function getTokenFromRepository(request2, auth5, parsedOwner, parsedReposi
|
|||||||
// lib/request.js
|
// lib/request.js
|
||||||
var import_core = __toESM(require_core(), 1);
|
var import_core = __toESM(require_core(), 1);
|
||||||
var baseUrl = import_core.default.getInput("github-api-url").replace(/\/$/, "");
|
var baseUrl = import_core.default.getInput("github-api-url").replace(/\/$/, "");
|
||||||
|
var proxyEnvironmentKeys = [
|
||||||
|
"https_proxy",
|
||||||
|
"HTTPS_PROXY",
|
||||||
|
"http_proxy",
|
||||||
|
"HTTP_PROXY"
|
||||||
|
];
|
||||||
|
function proxyEnvironmentConfigured() {
|
||||||
|
return proxyEnvironmentKeys.some((key) => process.env[key]);
|
||||||
|
}
|
||||||
|
function nativeProxySupportEnabled() {
|
||||||
|
return process.env.NODE_USE_ENV_PROXY === "1";
|
||||||
|
}
|
||||||
|
function ensureNativeProxySupport() {
|
||||||
|
if (!proxyEnvironmentConfigured() || nativeProxySupportEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
"A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step."
|
||||||
|
);
|
||||||
|
}
|
||||||
var request_default = request.defaults({
|
var request_default = request.defaults({
|
||||||
headers: { "user-agent": "actions/create-github-app-token" },
|
headers: { "user-agent": "actions/create-github-app-token" },
|
||||||
baseUrl
|
baseUrl
|
||||||
@@ -22245,23 +22265,27 @@ if (!process.env.GITHUB_REPOSITORY) {
|
|||||||
if (!process.env.GITHUB_REPOSITORY_OWNER) {
|
if (!process.env.GITHUB_REPOSITORY_OWNER) {
|
||||||
throw new Error("GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'");
|
throw new Error("GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'");
|
||||||
}
|
}
|
||||||
var appId = import_core2.default.getInput("app-id");
|
async function run() {
|
||||||
var privateKey = import_core2.default.getInput("private-key");
|
ensureNativeProxySupport();
|
||||||
var owner = import_core2.default.getInput("owner");
|
const appId = import_core2.default.getInput("app-id");
|
||||||
var repositories = import_core2.default.getInput("repositories").split(/[\n,]+/).map((s) => s.trim()).filter((x) => x !== "");
|
const privateKey = import_core2.default.getInput("private-key");
|
||||||
var skipTokenRevoke = import_core2.default.getBooleanInput("skip-token-revoke");
|
const owner = import_core2.default.getInput("owner");
|
||||||
var permissions = getPermissionsFromInputs(process.env);
|
const repositories = import_core2.default.getInput("repositories").split(/[\n,]+/).map((s) => s.trim()).filter((x) => x !== "");
|
||||||
var main_default = main(
|
const skipTokenRevoke = import_core2.default.getBooleanInput("skip-token-revoke");
|
||||||
appId,
|
const permissions = getPermissionsFromInputs(process.env);
|
||||||
privateKey,
|
return main(
|
||||||
owner,
|
appId,
|
||||||
repositories,
|
privateKey,
|
||||||
permissions,
|
owner,
|
||||||
import_core2.default,
|
repositories,
|
||||||
createAppAuth,
|
permissions,
|
||||||
request_default,
|
import_core2.default,
|
||||||
skipTokenRevoke
|
createAppAuth,
|
||||||
).catch((error) => {
|
request_default,
|
||||||
|
skipTokenRevoke
|
||||||
|
);
|
||||||
|
}
|
||||||
|
var main_default = run().catch((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
import_core2.default.setFailed(error.message);
|
import_core2.default.setFailed(error.message);
|
||||||
});
|
});
|
||||||
|
|||||||
Vendored
+25
-1
@@ -20485,13 +20485,37 @@ var request = withDefaults2(endpoint, defaults_default);
|
|||||||
|
|
||||||
// lib/request.js
|
// lib/request.js
|
||||||
var baseUrl = import_core.default.getInput("github-api-url").replace(/\/$/, "");
|
var baseUrl = import_core.default.getInput("github-api-url").replace(/\/$/, "");
|
||||||
|
var proxyEnvironmentKeys = [
|
||||||
|
"https_proxy",
|
||||||
|
"HTTPS_PROXY",
|
||||||
|
"http_proxy",
|
||||||
|
"HTTP_PROXY"
|
||||||
|
];
|
||||||
|
function proxyEnvironmentConfigured() {
|
||||||
|
return proxyEnvironmentKeys.some((key) => process.env[key]);
|
||||||
|
}
|
||||||
|
function nativeProxySupportEnabled() {
|
||||||
|
return process.env.NODE_USE_ENV_PROXY === "1";
|
||||||
|
}
|
||||||
|
function ensureNativeProxySupport() {
|
||||||
|
if (!proxyEnvironmentConfigured() || nativeProxySupportEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
"A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step."
|
||||||
|
);
|
||||||
|
}
|
||||||
var request_default = request.defaults({
|
var request_default = request.defaults({
|
||||||
headers: { "user-agent": "actions/create-github-app-token" },
|
headers: { "user-agent": "actions/create-github-app-token" },
|
||||||
baseUrl
|
baseUrl
|
||||||
});
|
});
|
||||||
|
|
||||||
// post.js
|
// post.js
|
||||||
post(import_core2.default, request_default).catch((error) => {
|
async function run() {
|
||||||
|
ensureNativeProxySupport();
|
||||||
|
return post(import_core2.default, request_default);
|
||||||
|
}
|
||||||
|
run().catch((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
import_core2.default.setFailed(error.message);
|
import_core2.default.setFailed(error.message);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,31 @@ import { request } from "@octokit/request";
|
|||||||
// Get the GitHub API URL from the action input and remove any trailing slash
|
// Get the GitHub API URL from the action input and remove any trailing slash
|
||||||
const baseUrl = core.getInput("github-api-url").replace(/\/$/, "");
|
const baseUrl = core.getInput("github-api-url").replace(/\/$/, "");
|
||||||
|
|
||||||
|
const proxyEnvironmentKeys = [
|
||||||
|
"https_proxy",
|
||||||
|
"HTTPS_PROXY",
|
||||||
|
"http_proxy",
|
||||||
|
"HTTP_PROXY",
|
||||||
|
];
|
||||||
|
|
||||||
|
function proxyEnvironmentConfigured() {
|
||||||
|
return proxyEnvironmentKeys.some((key) => process.env[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nativeProxySupportEnabled() {
|
||||||
|
return process.env.NODE_USE_ENV_PROXY === "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureNativeProxySupport() {
|
||||||
|
if (!proxyEnvironmentConfigured() || nativeProxySupportEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
"A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Configure the default settings for GitHub API requests
|
// Configure the default settings for GitHub API requests
|
||||||
export default request.defaults({
|
export default request.defaults({
|
||||||
headers: { "user-agent": "actions/create-github-app-token" },
|
headers: { "user-agent": "actions/create-github-app-token" },
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { createAppAuth } from "@octokit/auth-app";
|
|||||||
|
|
||||||
import { getPermissionsFromInputs } from "./lib/get-permissions-from-inputs.js";
|
import { getPermissionsFromInputs } from "./lib/get-permissions-from-inputs.js";
|
||||||
import { main } from "./lib/main.js";
|
import { main } from "./lib/main.js";
|
||||||
import request from "./lib/request.js";
|
import request, { ensureNativeProxySupport } from "./lib/request.js";
|
||||||
|
|
||||||
if (!process.env.GITHUB_REPOSITORY) {
|
if (!process.env.GITHUB_REPOSITORY) {
|
||||||
throw new Error("GITHUB_REPOSITORY missing, must be set to '<owner>/<repo>'");
|
throw new Error("GITHUB_REPOSITORY missing, must be set to '<owner>/<repo>'");
|
||||||
@@ -15,31 +15,37 @@ if (!process.env.GITHUB_REPOSITORY_OWNER) {
|
|||||||
throw new Error("GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'");
|
throw new Error("GITHUB_REPOSITORY_OWNER missing, must be set to '<owner>'");
|
||||||
}
|
}
|
||||||
|
|
||||||
const appId = core.getInput("app-id");
|
async function run() {
|
||||||
const privateKey = core.getInput("private-key");
|
ensureNativeProxySupport();
|
||||||
const owner = core.getInput("owner");
|
|
||||||
const repositories = core
|
|
||||||
.getInput("repositories")
|
|
||||||
.split(/[\n,]+/)
|
|
||||||
.map((s) => s.trim())
|
|
||||||
.filter((x) => x !== "");
|
|
||||||
|
|
||||||
const skipTokenRevoke = core.getBooleanInput("skip-token-revoke");
|
const appId = core.getInput("app-id");
|
||||||
|
const privateKey = core.getInput("private-key");
|
||||||
|
const owner = core.getInput("owner");
|
||||||
|
const repositories = core
|
||||||
|
.getInput("repositories")
|
||||||
|
.split(/[\n,]+/)
|
||||||
|
.map((s) => s.trim())
|
||||||
|
.filter((x) => x !== "");
|
||||||
|
|
||||||
const permissions = getPermissionsFromInputs(process.env);
|
const skipTokenRevoke = core.getBooleanInput("skip-token-revoke");
|
||||||
|
|
||||||
|
const permissions = getPermissionsFromInputs(process.env);
|
||||||
|
|
||||||
|
return main(
|
||||||
|
appId,
|
||||||
|
privateKey,
|
||||||
|
owner,
|
||||||
|
repositories,
|
||||||
|
permissions,
|
||||||
|
core,
|
||||||
|
createAppAuth,
|
||||||
|
request,
|
||||||
|
skipTokenRevoke,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Export promise for testing
|
// Export promise for testing
|
||||||
export default main(
|
export default run().catch((error) => {
|
||||||
appId,
|
|
||||||
privateKey,
|
|
||||||
owner,
|
|
||||||
repositories,
|
|
||||||
permissions,
|
|
||||||
core,
|
|
||||||
createAppAuth,
|
|
||||||
request,
|
|
||||||
skipTokenRevoke,
|
|
||||||
).catch((error) => {
|
|
||||||
/* c8 ignore next 3 */
|
/* c8 ignore next 3 */
|
||||||
console.error(error);
|
console.error(error);
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
|
|||||||
@@ -3,9 +3,15 @@
|
|||||||
import core from "@actions/core";
|
import core from "@actions/core";
|
||||||
|
|
||||||
import { post } from "./lib/post.js";
|
import { post } from "./lib/post.js";
|
||||||
import request from "./lib/request.js";
|
import request, { ensureNativeProxySupport } from "./lib/request.js";
|
||||||
|
|
||||||
post(core, request).catch((error) => {
|
async function run() {
|
||||||
|
ensureNativeProxySupport();
|
||||||
|
|
||||||
|
return post(core, request);
|
||||||
|
}
|
||||||
|
|
||||||
|
run().catch((error) => {
|
||||||
/* c8 ignore next 3 */
|
/* c8 ignore next 3 */
|
||||||
console.error(error);
|
console.error(error);
|
||||||
core.setFailed(error.message);
|
core.setFailed(error.message);
|
||||||
|
|||||||
@@ -21,6 +21,14 @@ for (const file of testFiles) {
|
|||||||
const env = {
|
const env = {
|
||||||
GITHUB_OUTPUT: undefined,
|
GITHUB_OUTPUT: undefined,
|
||||||
GITHUB_STATE: undefined,
|
GITHUB_STATE: undefined,
|
||||||
|
HTTP_PROXY: undefined,
|
||||||
|
HTTPS_PROXY: undefined,
|
||||||
|
http_proxy: undefined,
|
||||||
|
https_proxy: undefined,
|
||||||
|
NO_PROXY: undefined,
|
||||||
|
no_proxy: undefined,
|
||||||
|
NODE_OPTIONS: undefined,
|
||||||
|
NODE_USE_ENV_PROXY: undefined,
|
||||||
};
|
};
|
||||||
const { stderr, stdout } = await execa("node", [`tests/${file}`], { env });
|
const { stderr, stdout } = await execa("node", [`tests/${file}`], { env });
|
||||||
t.snapshot(stderr, "stderr");
|
t.snapshot(stderr, "stderr");
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
process.env.GITHUB_REPOSITORY = "actions/create-github-app-token";
|
||||||
|
process.env.GITHUB_REPOSITORY_OWNER = "actions";
|
||||||
|
process.env.HTTPS_PROXY = "http://127.0.0.1:3128";
|
||||||
|
|
||||||
|
const originalConsoleError = console.error;
|
||||||
|
console.error = (...args) => {
|
||||||
|
originalConsoleError(
|
||||||
|
...args.map((arg) => (arg instanceof Error ? arg.message : arg)),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
await import("../main.js");
|
||||||
|
await new Promise((resolve) => setImmediate(resolve));
|
||||||
|
process.exitCode = 0;
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
process.env["INPUT_GITHUB-API-URL"] = "https://api.github.com";
|
||||||
|
process.env.HTTPS_PROXY = "http://127.0.0.1:3128";
|
||||||
|
|
||||||
|
const originalConsoleError = console.error;
|
||||||
|
console.error = (...args) => {
|
||||||
|
originalConsoleError(
|
||||||
|
...args.map((arg) => (arg instanceof Error ? arg.message : arg)),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
await import("../post.js");
|
||||||
|
await new Promise((resolve) => setImmediate(resolve));
|
||||||
|
process.exitCode = 0;
|
||||||
@@ -82,6 +82,16 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
POST /app/installations/123456/access_tokens␊
|
POST /app/installations/123456/access_tokens␊
|
||||||
{"repositories":["create-github-app-token"]}`
|
{"repositories":["create-github-app-token"]}`
|
||||||
|
|
||||||
|
## main-proxy-requires-native-support.test.js
|
||||||
|
|
||||||
|
> stderr
|
||||||
|
|
||||||
|
'A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.'
|
||||||
|
|
||||||
|
> stdout
|
||||||
|
|
||||||
|
'::error::A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.'
|
||||||
|
|
||||||
## main-repo-skew.test.js
|
## main-repo-skew.test.js
|
||||||
|
|
||||||
> stderr
|
> stderr
|
||||||
@@ -333,6 +343,16 @@ Generated by [AVA](https://avajs.dev).
|
|||||||
POST /app/installations/123456/access_tokens␊
|
POST /app/installations/123456/access_tokens␊
|
||||||
{"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull_requests":"read"}}`
|
{"repositories":["create-github-app-token"],"permissions":{"issues":"write","pull_requests":"read"}}`
|
||||||
|
|
||||||
|
## post-proxy-requires-native-support.test.js
|
||||||
|
|
||||||
|
> stderr
|
||||||
|
|
||||||
|
'A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.'
|
||||||
|
|
||||||
|
> stdout
|
||||||
|
|
||||||
|
'::error::A proxy environment variable is set, but Node.js native proxy support is not enabled. Set NODE_USE_ENV_PROXY=1 for this action step.'
|
||||||
|
|
||||||
## post-revoke-token-fail-response.test.js
|
## post-revoke-token-fail-response.test.js
|
||||||
|
|
||||||
> stderr
|
> stderr
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user