1- import type { Octokit } from '@octokit/rest' ;
21import { beforeEach , describe , expect , test , vi } from 'vitest' ;
32
43const mocks = vi . hoisted ( ( ) => ( {
54 appsConfigured : vi . fn ( ) ,
65 ensureInitialized : vi . fn ( ) ,
76 getInstallationToken : vi . fn ( ) ,
87 hasEntitlement : vi . fn ( ) ,
8+ logger : {
9+ debug : vi . fn ( ) ,
10+ error : vi . fn ( ) ,
11+ info : vi . fn ( ) ,
12+ warn : vi . fn ( ) ,
13+ } ,
14+ GithubAppInstallationNotFoundError : class GithubAppInstallationNotFoundError extends Error {
15+ constructor ( owner : string , deploymentHostname : string ) {
16+ super ( `GitHub App installation not found for ${ deploymentHostname } /${ owner } ` ) ;
17+ this . name = 'GithubAppInstallationNotFoundError' ;
18+ }
19+ } ,
20+ } ) ) ;
21+
22+ vi . mock ( '@octokit/rest' , ( ) => ( {
23+ Octokit : class {
24+ public paginate = {
25+ iterator : async function * ( _request : unknown , options : { org : string } ) {
26+ yield {
27+ data : [ {
28+ clone_url : `https://github.com/${ options . org } /repo.git` ,
29+ full_name : `${ options . org } /repo` ,
30+ id : 1 ,
31+ name : 'repo' ,
32+ owner : {
33+ avatar_url : '' ,
34+ login : options . org ,
35+ } ,
36+ } ] ,
37+ } ;
38+ } ,
39+ } ;
40+
41+ public repos = {
42+ listForOrg : vi . fn ( ) ,
43+ } ;
44+
45+ public rest = {
46+ users : {
47+ getAuthenticated : vi . fn ( ) ,
48+ } ,
49+ } ;
50+ } ,
951} ) ) ;
1052
1153vi . mock ( '@sentry/node' , ( ) => ( {
1254 captureException : vi . fn ( ) ,
1355} ) ) ;
1456
1557vi . mock ( '@sourcebot/shared' , ( ) => ( {
16- createLogger : vi . fn ( ( ) => ( {
17- debug : vi . fn ( ) ,
18- error : vi . fn ( ) ,
19- info : vi . fn ( ) ,
20- warn : vi . fn ( ) ,
21- } ) ) ,
58+ createLogger : vi . fn ( ( ) => mocks . logger ) ,
2259 env : {
2360 FALLBACK_GITHUB_CLOUD_TOKEN : undefined ,
2461 } ,
@@ -30,6 +67,7 @@ vi.mock('./entitlements.js', () => ({
3067} ) ) ;
3168
3269vi . mock ( './ee/githubAppManager.js' , ( ) => ( {
70+ GithubAppInstallationNotFoundError : mocks . GithubAppInstallationNotFoundError ,
3371 GithubAppManager : {
3472 getInstance : ( ) => ( {
3573 appsConfigured : mocks . appsConfigured ,
@@ -39,14 +77,19 @@ vi.mock('./ee/githubAppManager.js', () => ({
3977 } ,
4078} ) ) ;
4179
42- import { getOctokitWithGithubApp } from './github.js' ;
80+ import type { Octokit } from '@octokit/rest' ;
81+ import { getGitHubReposFromConfig , getOctokitWithGithubApp } from './github.js' ;
4382
4483describe ( 'getOctokitWithGithubApp' , ( ) => {
4584 beforeEach ( ( ) => {
4685 mocks . appsConfigured . mockReset ( ) . mockReturnValue ( true ) ;
4786 mocks . ensureInitialized . mockReset ( ) . mockResolvedValue ( undefined ) ;
4887 mocks . getInstallationToken . mockReset ( ) . mockResolvedValue ( 'installation-token' ) ;
4988 mocks . hasEntitlement . mockReset ( ) ;
89+ mocks . logger . debug . mockReset ( ) ;
90+ mocks . logger . error . mockReset ( ) ;
91+ mocks . logger . info . mockReset ( ) ;
92+ mocks . logger . warn . mockReset ( ) ;
5093 } ) ;
5194
5295 test ( 'fails safely, then uses the GitHub App when the entitlement appears after startup' , async ( ) => {
@@ -101,4 +144,28 @@ describe('getOctokitWithGithubApp', () => {
101144 'org example' ,
102145 ) ) . rejects . toBe ( error ) ;
103146 } ) ;
147+
148+ test ( 'warns and continues when the GitHub App is not installed for one organization' , async ( ) => {
149+ mocks . hasEntitlement . mockResolvedValue ( true ) ;
150+ mocks . getInstallationToken . mockImplementation ( async ( owner : string ) => {
151+ if ( owner === 'invalid-org' ) {
152+ throw new mocks . GithubAppInstallationNotFoundError ( owner , 'github.com' ) ;
153+ }
154+ return 'installation-token' ;
155+ } ) ;
156+
157+ const result = await getGitHubReposFromConfig ( {
158+ type : 'github' ,
159+ orgs : [ 'valid-org' , 'invalid-org' ] ,
160+ } , new AbortController ( ) . signal ) ;
161+
162+ expect ( result . repos . map ( repo => repo . full_name ) ) . toEqual ( [ 'valid-org/repo' ] ) ;
163+ expect ( result . warnings ) . toEqual ( [
164+ 'GitHub App installation not found for github.com/invalid-org' ,
165+ ] ) ;
166+ expect ( mocks . logger . warn ) . toHaveBeenCalledWith (
167+ 'GitHub App installation not found for github.com/invalid-org' ,
168+ ) ;
169+ expect ( mocks . logger . error ) . not . toHaveBeenCalled ( ) ;
170+ } ) ;
104171} ) ;
0 commit comments