From 51858add0fb700cf9008320ebefa0b23be7d8fad Mon Sep 17 00:00:00 2001 From: Peter C <12292660+PeterC89@users.noreply.github.com> Date: Mon, 21 Jul 2025 15:21:25 +0100 Subject: [PATCH] fix: Correctly handle proxies with undici --- .github/workflows/ci.yaml | 10 +++++----- package-lock.json | 40 +++++++++++++++++++++++++++++++++------ package.json | 7 ++++--- src/github.ts | 37 ++++++++++++++---------------------- test/github.ts | 36 +---------------------------------- 5 files changed, 58 insertions(+), 72 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5af4eb427..d13a0d89d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [18, 20] + node: ['>=20.18.1 <21', 22] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v3 @@ -33,7 +33,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 18 + node-version: ">=20.18.1 <21" - run: npm install - run: npm test env: @@ -44,7 +44,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 18 + node-version: ">=20.18.1 <21" - run: npm install - run: npm run lint docs: @@ -53,7 +53,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v3 with: - node-version: 18 + node-version: ">=20.18.1 <21" - run: npm install - run: npm run docs - uses: JustinBeckwith/linkinator-action@v1 @@ -68,6 +68,6 @@ jobs: ref: main - uses: actions/setup-node@v3 with: - node-version: 18 + node-version: ">=20.18.1 <21" - run: npm install --save googleapis/release-please#${{ github.ref }} - run: npm run build diff --git a/package-lock.json b/package-lock.json index 58282e71e..9679ac3c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "semver": "^7.5.3", "type-fest": "^3.0.0", "typescript": "^4.6.4", + "undici": "^7.18.2", "unist-util-visit": "^2.0.3", "unist-util-visit-parents": "^3.1.1", "xpath": "^0.0.34", @@ -53,7 +54,7 @@ "@types/js-yaml": "^4.0.0", "@types/jsonpath": "^0.2.0", "@types/mocha": "^10.0.0", - "@types/node": "^18.0.0", + "@types/node": "^18.13.0", "@types/npmlog": "^7.0.0", "@types/semver": "^7.0.0", "@types/sinon": "^17.0.0", @@ -73,7 +74,7 @@ "snap-shot-it": "^7.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=18" } }, "node_modules/@babel/code-frame": { @@ -579,6 +580,7 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", "license": "MIT", + "peer": true, "dependencies": { "@octokit/auth-token": "^4.0.0", "@octokit/graphql": "^7.1.0", @@ -961,10 +963,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", - "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==", - "dev": true + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/normalize-package-data": { "version": "2.4.1", @@ -1101,6 +1107,7 @@ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", "dev": true, + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "4.33.0", "@typescript-eslint/types": "4.33.0", @@ -1210,6 +1217,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", "dev": true, + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2141,6 +2149,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", "dev": true, + "peer": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -3472,6 +3481,7 @@ "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", "license": "MIT", + "peer": true, "engines": { "node": ">= 10.16.0" } @@ -4364,6 +4374,7 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", "dev": true, + "peer": true, "bin": { "prettier": "bin-prettier.js" }, @@ -5367,6 +5378,7 @@ "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -5387,6 +5399,22 @@ "node": ">=0.8.0" } }, + "node_modules/undici": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.18.2.tgz", + "integrity": "sha512-y+8YjDFzWdQlSE9N5nzKMT3g4a5UBX1HKowfdXh0uvAnTaqqwqB92Jt4UXBAeKekDs5IaDKyJFR4X1gYVCgXcw==", + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + }, "node_modules/unist-util-is": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", diff --git a/package.json b/package.json index 185565d09..66d702971 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "./build/src/index.js", "bin": "./build/src/bin/release-please.js", "scripts": { - "test": "cross-env ENVIRONMENT=test LC_ALL=en c8 mocha --node-option no-experimental-fetch --recursive --timeout=5000 build/test", + "test": "cross-env ENVIRONMENT=test LC_ALL=en c8 mocha --recursive --timeout=5000 build/test", "docs": "echo add docs tests", "test:snap": "cross-env SNAPSHOT_UPDATE=1 LC_ALL=en npm test", "clean": "gts clean", @@ -46,7 +46,7 @@ "@types/js-yaml": "^4.0.0", "@types/jsonpath": "^0.2.0", "@types/mocha": "^10.0.0", - "@types/node": "^18.0.0", + "@types/node": "^18.13.0", "@types/npmlog": "^7.0.0", "@types/semver": "^7.0.0", "@types/sinon": "^17.0.0", @@ -92,6 +92,7 @@ "semver": "^7.5.3", "type-fest": "^3.0.0", "typescript": "^4.6.4", + "undici": "^7.18.2", "unist-util-visit": "^2.0.3", "unist-util-visit-parents": "^3.1.1", "xpath": "^0.0.34", @@ -99,7 +100,7 @@ "yargs": "^17.0.0" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.18.1" }, "overrides": { "tmp": "0.2.5" diff --git a/src/github.ts b/src/github.ts index c0bbf3668..f21fa3b4e 100644 --- a/src/github.ts +++ b/src/github.ts @@ -47,8 +47,13 @@ import { FileNotFoundError as MissingFileError, } from '@google-automations/git-file-utils'; import {Logger} from 'code-suggester/build/src/types'; -import {HttpsProxyAgent} from 'https-proxy-agent'; -import {HttpProxyAgent} from 'http-proxy-agent'; +import { + fetch as undiciFetch, + EnvHttpProxyAgent, + RequestInit, + RequestInfo, + Response, +} from 'undici'; import {PullRequestOverflowHandler} from './util/pull-request-overflow-handler'; import {mergeUpdates} from './updaters/composite'; @@ -68,11 +73,6 @@ export interface GitHubOptions { logger?: Logger; } -interface ProxyOption { - host: string; - port: number; -} - interface GitHubCreateOptions { owner: string; repo: string; @@ -82,7 +82,6 @@ interface GitHubCreateOptions { octokitAPIs?: OctokitAPIs; token?: string; logger?: Logger; - proxy?: ProxyOption; fetch?: any; } @@ -220,17 +219,11 @@ export class GitHub { this.logger = options.logger ?? defaultLogger; } - static createDefaultAgent(baseUrl: string, defaultProxy?: ProxyOption) { - if (!defaultProxy) { - return undefined; - } - - const {host, port} = defaultProxy; - if (new URL(baseUrl).protocol.replace(':', '') === 'http') { - return new HttpProxyAgent(`http://${host}:${port}`); - } else { - return new HttpsProxyAgent(`https://${host}:${port}`); - } + static fetch(url: RequestInfo, opts: RequestInit): Promise { + return undiciFetch(url, { + ...opts, + dispatcher: new EnvHttpProxyAgent(), + }); } /** @@ -256,8 +249,7 @@ export class GitHub { baseUrl: apiUrl, auth: options.token, request: { - agent: this.createDefaultAgent(apiUrl, options.proxy), - fetch: options.fetch, + fetch: options.fetch ?? this.fetch, }, }), request: request.defaults({ @@ -271,8 +263,7 @@ export class GitHub { graphql: graphql.defaults({ baseUrl: graphqlUrl, request: { - agent: this.createDefaultAgent(graphqlUrl, options.proxy), - fetch: options.fetch, + fetch: options.fetch ?? this.fetch, }, headers: { 'user-agent': `release-please/${releasePleaseVersion}`, diff --git a/test/github.ts b/test/github.ts index bab1ae232..ff40af448 100644 --- a/test/github.ts +++ b/test/github.ts @@ -22,7 +22,7 @@ import {resolve} from 'path'; import * as snapshot from 'snap-shot-it'; import * as sinon from 'sinon'; -import {GH_API_URL, GitHub, GitHubRelease} from '../src/github'; +import {GitHub, GitHubRelease} from '../src/github'; import {PullRequest} from '../src/pull-request'; import {TagName} from '../src/util/tag-name'; import {Version} from '../src/version'; @@ -38,11 +38,8 @@ import {PullRequestTitle} from '../src/util/pull-request-title'; import * as codeSuggester from 'code-suggester'; import {RawContent} from '../src/updaters/raw-content'; import {ReleasePleaseManifest} from '../src/updaters/release-please-manifest'; -import {HttpsProxyAgent} from 'https-proxy-agent'; -import {HttpProxyAgent} from 'http-proxy-agent'; import {Commit} from '../src/commit'; import {mockReleaseData, MockPullRequestOverflowHandler} from './helpers'; -const fetch = require('node-fetch'); const fixturesPath = './test/fixtures'; const sandbox = sinon.createSandbox(); @@ -100,37 +97,6 @@ describe('GitHub', () => { expect(github.repository.defaultBranch).to.eql('some-branch-from-api'); }); - - it('default agent is undefined when no proxy option passed ', () => { - expect(GitHub.createDefaultAgent('test_url')).eq(undefined); - }); - - it('should return a https agent', () => { - expect( - GitHub.createDefaultAgent(GH_API_URL, { - host: 'http://proxy.com', - port: 3000, - }) - ).instanceof(HttpsProxyAgent); - }); - - it('should throw error when baseUrl is an invalid url', () => { - expect(() => { - GitHub.createDefaultAgent('invalid_url', { - host: 'http://proxy.com', - port: 3000, - }); - }).to.throw('Invalid URL'); - }); - - it('should return a http agent', () => { - expect( - GitHub.createDefaultAgent('http://www.github.com', { - host: 'http://proxy.com', - port: 3000, - }) - ).instanceof(HttpProxyAgent); - }); }); describe('findFilesByFilename', () => {