diff --git a/package.json b/package.json index f0b17d56d..99a5c2ea0 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,8 @@ "detect-indent": "^6.1.0", "diff": "^5.0.0", "figures": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", "js-yaml": "^4.0.0", "jsonpath": "^1.1.1", "node-html-parser": "^6.0.0", diff --git a/src/github.ts b/src/github.ts index 911a95650..99199455c 100644 --- a/src/github.ts +++ b/src/github.ts @@ -46,6 +46,8 @@ 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'; // Extract some types from the `request` package. type RequestBuilderType = typeof request; @@ -63,6 +65,11 @@ export interface GitHubOptions { logger?: Logger; } +interface ProxyOption { + host: string; + port: number; +} + interface GitHubCreateOptions { owner: string; repo: string; @@ -72,6 +79,7 @@ interface GitHubCreateOptions { octokitAPIs?: OctokitAPIs; token?: string; logger?: Logger; + proxy?: ProxyOption; } type CommitFilter = (commit: Commit) => boolean; @@ -202,6 +210,24 @@ export class GitHub { this.logger = options.logger ?? defaultLogger; } + static createDefaultAgent(baseUrl: string, defaultProxy?: ProxyOption) { + if (!defaultProxy) { + return undefined; + } + + const {host, port} = defaultProxy; + + return new URL(baseUrl).protocol.replace(':', '') === 'http' + ? new HttpProxyAgent({ + host, + port, + }) + : new HttpsProxyAgent({ + host, + port, + }); + } + /** * Build a new GitHub client with auto-detected default branch. * @@ -224,6 +250,9 @@ export class GitHub { octokit: new Octokit({ baseUrl: apiUrl, auth: options.token, + request: { + agent: this.createDefaultAgent(apiUrl, options.proxy), + }, }), request: request.defaults({ baseUrl: apiUrl, diff --git a/test/github.ts b/test/github.ts index 8ff17454c..b54e69fde 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 {GitHub, GitHubRelease} from '../src/github'; +import {GH_API_URL, GitHub, GitHubRelease} from '../src/github'; import {PullRequest} from '../src/pull-request'; import {TagName} from '../src/util/tag-name'; import {Version} from '../src/version'; @@ -37,6 +37,8 @@ import {PullRequestBody} from '../src/util/pull-request-body'; import {PullRequestTitle} from '../src/util/pull-request-title'; import * as codeSuggester from 'code-suggester'; import {RawContent} from '../src/updaters/raw-content'; +import {HttpsProxyAgent} from 'https-proxy-agent'; +import {HttpProxyAgent} from 'http-proxy-agent'; const fixturesPath = './test/fixtures'; const sandbox = sinon.createSandbox(); @@ -88,8 +90,40 @@ describe('GitHub', () => { owner: 'some-owner', repo: 'some-repo', }); + 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', () => { diff --git a/tsconfig.json b/tsconfig.json index 7cc659719..ad49e4f68 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "./node_modules/gts/tsconfig-google.json", "compilerOptions": { + "allowSyntheticDefaultImports": true, "lib": ["es2018", "dom"], "rootDir": ".", "outDir": "build",