diff --git a/docs/usage/getting-started/running.md b/docs/usage/getting-started/running.md index 6ae9c56fd4903d71fc2c98d7e737633d579f9ca1..d67c053e2ee77bc6a014e6d3076e712b5646e62e 100644 --- a/docs/usage/getting-started/running.md +++ b/docs/usage/getting-started/running.md @@ -174,7 +174,6 @@ Alternatively as environment variable `RENOVATE_TOKEN`, or via CLI `--token=`. **`repositories: ["orgname/repo-1","orgname/repo-2"]`** List of repositories to run on. -Auto discovery does not work with a GitHub App. Alternatively as comma-separated environment variable `RENOVATE_REPOSITORIES`. The GitHub App installation token is scoped at most to a single organization and running on multiple organizations requires multiple invocations of `renovate` with different `token` and `repositories` parameters. diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index ebb9ef0581ee148bdc778911e9e86348be86d2be..d1461eb4f758cd31df1930457c4f7de6a0eb0b49 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -175,6 +175,31 @@ describe('platform/github/index', () => { expect(repos).toMatchSnapshot(); expect(httpMock.getTrace()).toMatchSnapshot(); }); + it('should return an array of repos when using Github App endpoint', async () => { + //Use Github App token + await github.initPlatform({ + endpoint: githubApiHost, + username: 'renovate-bot', + gitAuthor: 'Renovate Bot', + token: 'x-access-token:123test', + }); + httpMock + .scope(githubApiHost) + .get('/installation/repositories?per_page=100') + .reply(200, { + repositories: [ + { + full_name: 'a/b', + }, + { + full_name: 'c/d', + }, + ], + }); + + const repos = await github.getRepos(); + expect(repos).toStrictEqual(['a/b', 'c/d']); + }); }); function initRepoMock( diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 4c06175bbb47f1262f91cb9206fa34cf1f13e65c..2bb8d39b86961a07fdc28da984e4890aa1113bf6 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -109,6 +109,8 @@ export async function initPlatform({ throw new Error('Init: You must configure a GitHub personal access token'); } + platformConfig.isGHApp = token.startsWith('x-access-token:'); + if (endpoint) { platformConfig.endpoint = ensureTrailingSlash(endpoint); githubHttp.setBaseUrl(platformConfig.endpoint); @@ -148,11 +150,21 @@ export async function initPlatform({ export async function getRepos(): Promise<string[]> { logger.debug('Autodiscovering GitHub repositories'); try { - const res = await githubApi.getJson<{ full_name: string }[]>( - 'user/repos?per_page=100', - { paginate: 'all' } - ); - return res.body.map((repo) => repo.full_name); + if (platformConfig.isGHApp) { + const res = await githubApi.getJson<{ + repositories: { full_name: string }[]; + }>(`installation/repositories?per_page=100`, { + paginationField: 'repositories', + paginate: 'all', + }); + return res.body.repositories.map((repo) => repo.full_name); + } else { + const res = await githubApi.getJson<{ full_name: string }[]>( + `user/repos?per_page=100`, + { paginate: 'all' } + ); + return res.body.map((repo) => repo.full_name); + } } catch (err) /* istanbul ignore next */ { logger.error({ err }, `GitHub getRepos error`); throw err; diff --git a/lib/platform/github/types.ts b/lib/platform/github/types.ts index 296e589e54f2a1835f12c70e16f4b7a2eccc3655..2e819ebf9ebf840e6b393adf0de44ac3ccc7a9a6 100644 --- a/lib/platform/github/types.ts +++ b/lib/platform/github/types.ts @@ -59,6 +59,7 @@ export interface PlatformConfig { endpoint: string; isGhe?: boolean; gheVersion?: string | null; + isGHApp?: boolean; } export interface LocalRepoConfig {