feat(github): support fine-grained token (#23810)

This commit is contained in:
Jiahao Guo 2023-08-16 13:53:48 +08:00 committed by GitHub
parent a36424771a
commit 8ad31261d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 30 deletions

View file

@ -57,14 +57,55 @@ describe('modules/platform/github/index', () => {
); );
}); });
it('should throw if fine-grained token', async () => { it('should throw if using fine-grained token with GHE <3.10 ', async () => {
httpMock
.scope('https://ghe.renovatebot.com')
.head('/')
.reply(200, '', { 'x-github-enterprise-version': '3.9.0' });
await expect( await expect(
github.initPlatform({ token: 'github_pat_XXXXXX' }) github.initPlatform({
endpoint: 'https://ghe.renovatebot.com',
token: 'github_pat_XXXXXX',
})
).rejects.toThrow( ).rejects.toThrow(
'Init: Fine-grained Personal Access Tokens do not support the GitHub GraphQL API and cannot be used with Renovate.' 'Init: Fine-grained Personal Access Tokens do not support GitHub Enterprise Server API version <3.10 and cannot be used with Renovate.'
); );
}); });
it('should throw if using fine-grained token with GHE unknown version ', async () => {
httpMock.scope('https://ghe.renovatebot.com').head('/').reply(200);
await expect(
github.initPlatform({
endpoint: 'https://ghe.renovatebot.com',
token: 'github_pat_XXXXXX',
})
).rejects.toThrow(
'Init: Fine-grained Personal Access Tokens do not support GitHub Enterprise Server API version <3.10 and cannot be used with Renovate.'
);
});
it('should support fine-grained token with GHE >=3.10', async () => {
httpMock
.scope('https://ghe.renovatebot.com')
.head('/')
.reply(200, '', { 'x-github-enterprise-version': '3.10.0' })
.get('/user')
.reply(200, { login: 'renovate-bot' })
.get('/user/emails')
.reply(200, [{ email: 'user@domain.com' }]);
expect(
await github.initPlatform({
endpoint: 'https://ghe.renovatebot.com',
token: 'github_pat_XXXXXX',
})
).toEqual({
endpoint: 'https://ghe.renovatebot.com/',
gitAuthor: 'undefined <user@domain.com>',
renovateUsername: 'renovate-bot',
token: 'github_pat_XXXXXX',
});
});
it('should throw if user failure', async () => { it('should throw if user failure', async () => {
httpMock.scope(githubApiHost).get('/user').reply(404); httpMock.scope(githubApiHost).get('/user').reply(404);
await expect(github.initPlatform({ token: '123test' })).rejects.toThrow(); await expect(github.initPlatform({ token: '123test' })).rejects.toThrow();

View file

@ -23,6 +23,7 @@ import {
import { logger } from '../../../logger'; import { logger } from '../../../logger';
import type { BranchStatus, VulnerabilityAlert } from '../../../types'; import type { BranchStatus, VulnerabilityAlert } from '../../../types';
import { ExternalHostError } from '../../../types/errors/external-host-error'; import { ExternalHostError } from '../../../types/errors/external-host-error';
import { isGithubFineGrainedPersonalAccessToken } from '../../../util/check-token';
import * as git from '../../../util/git'; import * as git from '../../../util/git';
import { listCommitTree, pushCommitToRenovateRef } from '../../../util/git'; import { listCommitTree, pushCommitToRenovateRef } from '../../../util/git';
import type { import type {
@ -133,11 +134,6 @@ export async function initPlatform({
if (!token) { if (!token) {
throw new Error('Init: You must configure a GitHub token'); throw new Error('Init: You must configure a GitHub token');
} }
if (token.startsWith('github_pat_')) {
throw new Error(
'Init: Fine-grained Personal Access Tokens do not support the GitHub GraphQL API and cannot be used with Renovate.'
);
}
token = token.replace(/^ghs_/, 'x-access-token:ghs_'); token = token.replace(/^ghs_/, 'x-access-token:ghs_');
platformConfig.isGHApp = token.startsWith('x-access-token:'); platformConfig.isGHApp = token.startsWith('x-access-token:');
@ -149,6 +145,20 @@ export async function initPlatform({
} }
await detectGhe(token); await detectGhe(token);
/**
* GHE requires version >=3.10 to support fine-grained access tokens
* https://docs.github.com/en/enterprise-server@3.10/admin/release-notes#authentication
*/
if (
isGithubFineGrainedPersonalAccessToken(token) &&
platformConfig.isGhe &&
(!platformConfig.gheVersion ||
semver.lt(platformConfig.gheVersion, '3.10.0'))
) {
throw new Error(
'Init: Fine-grained Personal Access Tokens do not support GitHub Enterprise Server API version <3.10 and cannot be used with Renovate.'
);
}
let renovateUsername: string; let renovateUsername: string;
if (username) { if (username) {

View file

@ -246,7 +246,7 @@ describe('util/check-token', () => {
).toBe(githubToken); ).toBe(githubToken);
}); });
it('take personal assess token over fine grained token', () => { it('take personal access token over fine grained token', () => {
const githubToken = 'ghp_github'; const githubToken = 'ghp_github';
const gitTagsGithubToken = 'github_pat_gitTags'; const gitTagsGithubToken = 'github_pat_gitTags';
expect( expect(

View file

@ -1,12 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`workers/global/config/parse/env .getConfig(env) does not support GitHub fine-grained PATs 1`] = `
{
"hostRules": [],
"token": "a github.com token",
}
`;
exports[`workers/global/config/parse/env .getConfig(env) supports Azure DevOps 1`] = ` exports[`workers/global/config/parse/env .getConfig(env) supports Azure DevOps 1`] = `
{ {
"endpoint": "an Azure DevOps endpoint", "endpoint": "an Azure DevOps endpoint",

View file

@ -161,13 +161,20 @@ describe('workers/global/config/parse/env', () => {
}); });
}); });
it('does not support GitHub fine-grained PATs', () => { it('supports GitHub fine-grained PATs', () => {
const envParam: NodeJS.ProcessEnv = { const envParam: NodeJS.ProcessEnv = {
GITHUB_COM_TOKEN: 'github_pat_XXXXXX', GITHUB_COM_TOKEN: 'github_pat_XXXXXX',
RENOVATE_TOKEN: 'a github.com token', RENOVATE_TOKEN: 'a github.com token',
}; };
expect(env.getConfig(envParam)).toMatchSnapshot({ expect(env.getConfig(envParam)).toEqual({
token: 'a github.com token', token: 'a github.com token',
hostRules: [
{
hostType: 'github',
matchHost: 'github.com',
token: 'github_pat_XXXXXX',
},
],
}); });
}); });

View file

@ -164,18 +164,12 @@ export function getConfig(inputEnv: NodeJS.ProcessEnv): AllConfig {
}); });
if (env.GITHUB_COM_TOKEN) { if (env.GITHUB_COM_TOKEN) {
if (env.GITHUB_COM_TOKEN.startsWith('github_pat_')) { logger.debug(`Converting GITHUB_COM_TOKEN into a global host rule`);
logger.warn( config.hostRules.push({
'GITHUB_COM_TOKEN: Fine-grained Personal Access Tokens do not support the GitHub GraphQL API. Use a classic PAT instead.' hostType: 'github',
); matchHost: 'github.com',
} else { token: env.GITHUB_COM_TOKEN,
logger.debug(`Converting GITHUB_COM_TOKEN into a global host rule`); });
config.hostRules.push({
hostType: 'github',
matchHost: 'github.com',
token: env.GITHUB_COM_TOKEN,
});
}
} }
// These env vars are deprecated and deleted to make sure they're not used // These env vars are deprecated and deleted to make sure they're not used