fix!: require NODE_USE_ENV_PROXY for proxy support (#342)
BREAKING CHANGE: Custom proxy handling has been removed. If you use HTTP_PROXY or HTTPS_PROXY, you must now also set NODE_USE_ENV_PROXY=1 on the action step.
This commit is contained in:
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- beta
|
||||
pull_request:
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
@@ -33,7 +34,7 @@ jobs:
|
||||
name: end-to-end
|
||||
runs-on: ubuntu-latest
|
||||
# do not run from forks, as forks don’t have access to repository secrets
|
||||
if: github.event_name == 'merge_group' || 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:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
@@ -53,3 +54,28 @@ jobs:
|
||||
with:
|
||||
route: GET /installation/repositories
|
||||
- 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 }}
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
### `app-id`
|
||||
|
||||
@@ -4,6 +4,31 @@ import { request } from "@octokit/request";
|
||||
// Get the GitHub API URL from the action input and remove any trailing slash
|
||||
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
|
||||
export default request.defaults({
|
||||
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 { main } from "./lib/main.js";
|
||||
import request from "./lib/request.js";
|
||||
import request, { ensureNativeProxySupport } from "./lib/request.js";
|
||||
|
||||
if (!process.env.GITHUB_REPOSITORY) {
|
||||
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>'");
|
||||
}
|
||||
|
||||
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 !== "");
|
||||
async function run() {
|
||||
ensureNativeProxySupport();
|
||||
|
||||
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 default main(
|
||||
appId,
|
||||
privateKey,
|
||||
owner,
|
||||
repositories,
|
||||
permissions,
|
||||
core,
|
||||
createAppAuth,
|
||||
request,
|
||||
skipTokenRevoke,
|
||||
).catch((error) => {
|
||||
export default run().catch((error) => {
|
||||
/* c8 ignore next 3 */
|
||||
console.error(error);
|
||||
core.setFailed(error.message);
|
||||
|
||||
@@ -3,9 +3,15 @@
|
||||
import * as core from "@actions/core";
|
||||
|
||||
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 */
|
||||
console.error(error);
|
||||
core.setFailed(error.message);
|
||||
|
||||
@@ -21,6 +21,14 @@ for (const file of testFiles) {
|
||||
const env = {
|
||||
GITHUB_OUTPUT: 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 });
|
||||
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␊
|
||||
{"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
|
||||
|
||||
> stderr
|
||||
@@ -333,6 +343,16 @@ Generated by [AVA](https://avajs.dev).
|
||||
POST /app/installations/123456/access_tokens␊
|
||||
{"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
|
||||
|
||||
> stderr
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user