From 76913a188936a7b82259ee35b32583619aaaafb2 Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Mon, 17 Aug 2020 14:14:19 +0200 Subject: [PATCH] feat(github): support app tokens (#6859) --- lib/globals.d.ts | 1 - .../__snapshots__/artifacts.spec.ts.snap | 4 +- lib/manager/gomod/artifacts.spec.ts | 37 ++++++-------- lib/manager/gomod/artifacts.ts | 5 +- .../github/__snapshots__/index.spec.ts.snap | 48 ------------------- lib/platform/github/index.spec.ts | 11 ----- lib/platform/github/index.ts | 3 -- lib/util/http/auth.ts | 18 +++++-- lib/util/http/github.spec.ts | 11 +++-- lib/util/http/github.ts | 4 -- 10 files changed, 38 insertions(+), 104 deletions(-) diff --git a/lib/globals.d.ts b/lib/globals.d.ts index 175119eb5f..c37e0594e8 100644 --- a/lib/globals.d.ts +++ b/lib/globals.d.ts @@ -11,7 +11,6 @@ declare interface Error { declare namespace NodeJS { interface Global { - appMode?: boolean; gitAuthor?: { name: string; email: string }; trustLevel?: string; diff --git a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap index a2c73308b4..6120a58930 100644 --- a/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap +++ b/lib/manager/gomod/__snapshots__/artifacts.spec.ts.snap @@ -105,7 +105,7 @@ Array [ ] `; -exports[`.updateArtifacts() supports docker mode with credentials and appMode enabled 1`] = ` +exports[`.updateArtifacts() supports docker mode with goModTidy 1`] = ` Array [ Object { "cmd": "docker pull renovate/go:latest", @@ -120,7 +120,7 @@ Array [ }, }, Object { - "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"git config --global url.\\\\\\"https://x-access-token:some-token@github.com/\\\\\\".insteadOf \\\\\\"https://github.com/\\\\\\" && go get -d ./... && go mod tidy\\"", + "cmd": "docker run --rm --name=renovate_go --label=renovate_child --user=foobar -v \\"/tmp/github/some/repo\\":\\"/tmp/github/some/repo\\" -v \\"/tmp/renovate/cache\\":\\"/tmp/renovate/cache\\" -v \\"/tmp/renovate/cache/others/go\\":\\"/tmp/renovate/cache/others/go\\" -e GOPATH -e GOPROXY -e GONOSUMDB -e CGO_ENABLED -w \\"/tmp/github/some/repo\\" renovate/go:latest bash -l -c \\"go get -d ./... && go mod tidy\\"", "options": Object { "cwd": "/tmp/github/some/repo", "encoding": "utf-8", diff --git a/lib/manager/gomod/artifacts.spec.ts b/lib/manager/gomod/artifacts.spec.ts index 0e632f61d2..0f4c9f5ed0 100644 --- a/lib/manager/gomod/artifacts.spec.ts +++ b/lib/manager/gomod/artifacts.spec.ts @@ -212,12 +212,10 @@ describe('.updateArtifacts()', () => { ).not.toBeNull(); expect(execSnapshots).toMatchSnapshot(); }); - it('supports docker mode with credentials and appMode enabled', async () => { + it('supports docker mode with goModTidy', async () => { jest.spyOn(docker, 'removeDanglingContainers').mockResolvedValueOnce(); await setUtilConfig({ ...config, binarySource: BinarySource.Docker }); - hostRules.find.mockReturnValueOnce({ - token: 'some-token', - }); + hostRules.find.mockReturnValueOnce({}); fs.readFile.mockResolvedValueOnce('Current go.sum' as any); fs.readFile.mockResolvedValueOnce(null as any); // vendor modules filename const execSnapshots = mockExecAll(exec); @@ -228,24 +226,19 @@ describe('.updateArtifacts()', () => { fs.readFile.mockResolvedValueOnce('New go.sum 2' as any); fs.readFile.mockResolvedValueOnce('New go.sum 3' as any); fs.readFile.mockResolvedValueOnce('New go.mod' as any); - try { - global.appMode = true; - expect( - await gomod.updateArtifacts({ - packageFileName: 'go.mod', - updatedDeps: [], - newPackageFileContent: gomod1, - config: { - ...config, - binarySource: BinarySource.Docker, - postUpdateOptions: ['gomodTidy'], - }, - }) - ).not.toBeNull(); - expect(execSnapshots).toMatchSnapshot(); - } finally { - delete global.appMode; - } + expect( + await gomod.updateArtifacts({ + packageFileName: 'go.mod', + updatedDeps: [], + newPackageFileContent: gomod1, + config: { + ...config, + binarySource: BinarySource.Docker, + postUpdateOptions: ['gomodTidy'], + }, + }) + ).not.toBeNull(); + expect(execSnapshots).toMatchSnapshot(); }); it('catches errors', async () => { const execSnapshots = mockExecAll(exec); diff --git a/lib/manager/gomod/artifacts.ts b/lib/manager/gomod/artifacts.ts index 1a5373dc0b..a3d658327f 100644 --- a/lib/manager/gomod/artifacts.ts +++ b/lib/manager/gomod/artifacts.ts @@ -16,10 +16,7 @@ function getPreCommands(): string[] | null { }); let preCommands = null; if (credentials?.token) { - let token = global.appMode - ? `x-access-token:${credentials.token}` - : credentials.token; - token = quote(token); + const token = quote(credentials.token); preCommands = [ `git config --global url.\"https://${token}@github.com/\".insteadOf \"https://github.com/\"`, // eslint-disable-line no-useless-escape ]; diff --git a/lib/platform/github/__snapshots__/index.spec.ts.snap b/lib/platform/github/__snapshots__/index.spec.ts.snap index 97d208dc32..370cc42b37 100644 --- a/lib/platform/github/__snapshots__/index.spec.ts.snap +++ b/lib/platform/github/__snapshots__/index.spec.ts.snap @@ -5045,54 +5045,6 @@ Array [ ] `; -exports[`platform/github initRepo should use different header in app mode 1`] = ` -Object { - "defaultBranch": "master", - "defaultBranchSha": "1234", - "isFork": false, -} -`; - -exports[`platform/github initRepo should use different header in app mode 2`] = ` -Array [ - Object { - "graphql": Object { - "query": Object { - "repository": Object { - "__args": Object { - "name": "repo", - "owner": "some", - }, - "defaultBranchRef": Object { - "name": null, - "target": Object { - "oid": null, - }, - }, - "isArchived": null, - "isFork": null, - "mergeCommitAllowed": null, - "nameWithOwner": null, - "rebaseMergeAllowed": null, - "squashMergeAllowed": null, - }, - }, - }, - "headers": Object { - "accept": "application/vnd.github.machine-man-preview+json, application/vnd.github.v3+json", - "accept-encoding": "gzip, deflate", - "authorization": "token abc123", - "content-length": "330", - "content-type": "application/json", - "host": "api.github.com", - "user-agent": "https://github.com/renovatebot/renovate", - }, - "method": "POST", - "url": "https://api.github.com/graphql", - }, -] -`; - exports[`platform/github initRepo throws not-found 1`] = ` Array [ Object { diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index ea8df4b18b..333d8078fc 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -40,7 +40,6 @@ describe('platform/github', () => { afterEach(() => { httpMock.reset(); - global.appMode = false; }); const graphqlOpenPullRequests = fs.readFileSync( @@ -233,16 +232,6 @@ describe('platform/github', () => { ).rejects.toThrow(REPOSITORY_DISABLED); expect(httpMock.getTrace()).toMatchSnapshot(); }); - it('should use different header in app mode', async () => { - global.appMode = true; - const scope = httpMock.scope(githubApiHost); - initRepoMock(scope, 'some/repo'); - const config = await github.initRepo({ - repository: 'some/repo', - } as any); - expect(config).toMatchSnapshot(); - expect(httpMock.getTrace()).toMatchSnapshot(); - }); it('should rebase', async () => { const scope = httpMock.scope(githubApiHost); initRepoMock(scope, 'some/repo'); diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 7d1ce6d5fe..f03bc7dbcd 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -400,9 +400,6 @@ export async function initRepo({ if (forkMode) { logger.debug('Using forkToken for git init'); parsedEndpoint.auth = config.forkToken; - } else if (global.appMode) { - logger.debug('Using app token for git init'); - parsedEndpoint.auth = `x-access-token:${opts.token}`; } else { logger.debug('Using personal access token for git init'); parsedEndpoint.auth = opts.token; diff --git a/lib/util/http/auth.ts b/lib/util/http/auth.ts index 9b7fa0394b..da691f0937 100644 --- a/lib/util/http/auth.ts +++ b/lib/util/http/auth.ts @@ -1,3 +1,4 @@ +import is from '@sindresorhus/is'; import { NormalizedOptions } from 'got'; import { PLATFORM_TYPE_GITEA, @@ -12,11 +13,20 @@ export function applyAuthorization(inOptions: GotOptions): GotOptions { return options; } if (options.token) { - if ( - options.hostType === PLATFORM_TYPE_GITHUB || - options.hostType === PLATFORM_TYPE_GITEA - ) { + if (options.hostType === PLATFORM_TYPE_GITEA) { options.headers.authorization = `token ${options.token}`; + } else if (options.hostType === PLATFORM_TYPE_GITHUB) { + options.headers.authorization = `token ${options.token}`; + if (options.token.startsWith('x-access-token:')) { + const appToken = options.token.replace('x-access-token:', ''); + options.headers.authorization = `token ${appToken}`; + if (is.string(options.headers.accept)) { + options.headers.accept = options.headers.accept.replace( + 'application/vnd.github.v3+json', + 'application/vnd.github.machine-man-preview+json' + ); + } + } } else if (options.hostType === PLATFORM_TYPE_GITLAB) { options.headers['Private-token'] = options.token; } else { diff --git a/lib/util/http/github.spec.ts b/lib/util/http/github.spec.ts index 7446cb4b09..95ca43865e 100644 --- a/lib/util/http/github.spec.ts +++ b/lib/util/http/github.spec.ts @@ -8,6 +8,7 @@ import { PLATFORM_RATE_LIMIT_EXCEEDED, REPOSITORY_CHANGED, } from '../../constants/error-messages'; +import * as hostRules from '../host-rules'; import { GithubHttp, setBaseUrl } from './github'; const githubApiHost = 'https://api.github.com'; @@ -18,25 +19,25 @@ describe(getName(__filename), () => { githubApi = new GithubHttp(); setBaseUrl(githubApiHost); jest.resetAllMocks(); - delete global.appMode; httpMock.setup(); }); afterEach(() => { httpMock.reset(); + hostRules.clear(); }); describe('HTTP', () => { it('supports app mode', async () => { + hostRules.add({ hostType: 'github', token: 'x-access-token:abc123' }); httpMock.scope(githubApiHost).get('/some-url').reply(200); - global.appMode = true; await githubApi.get('/some-url', { headers: { accept: 'some-accept' }, }); const [req] = httpMock.getTrace(); expect(req).toBeDefined(); expect(req.headers.accept).toBe( - 'application/vnd.github.machine-man-preview+json, some-accept' + 'some-accept, application/vnd.github.machine-man-preview+json' ); }); it('strips v3 for graphql', async () => { @@ -226,16 +227,16 @@ describe(getName(__filename), () => { }`; it('supports app mode', async () => { + hostRules.add({ hostType: 'github', token: 'x-access-token:abc123' }); httpMock .scope(githubApiHost) .post('/graphql') .reply(200, { data: { repository: { testItem: 'XXX' } } }); - global.appMode = true; await githubApi.queryRepoField(query, 'testItem', { paginate: false }); const [req] = httpMock.getTrace(); expect(req).toBeDefined(); expect(req.headers.accept).toBe( - 'application/vnd.github.machine-man-preview+json, application/vnd.github.v3+json' + 'application/vnd.github.machine-man-preview+json' ); }); it('returns empty array for undefined data', async () => { diff --git a/lib/util/http/github.ts b/lib/util/http/github.ts index 39c5a59aeb..35ca32c319 100644 --- a/lib/util/http/github.ts +++ b/lib/util/http/github.ts @@ -130,11 +130,7 @@ interface GraphqlOptions { function constructAcceptString(input?: any): string { const defaultAccept = 'application/vnd.github.v3+json'; - const appModeAccept = 'application/vnd.github.machine-man-preview+json'; const acceptStrings = typeof input === 'string' ? input.split(/\s*,\s*/) : []; - if (global.appMode && !acceptStrings.includes(appModeAccept)) { - acceptStrings.unshift(appModeAccept); - } if ( !acceptStrings.some((x) => x.startsWith('application/vnd.github.')) || acceptStrings.length < 2 -- GitLab