-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.ts
More file actions
104 lines (96 loc) · 2.72 KB
/
auth.ts
File metadata and controls
104 lines (96 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import * as core from '@actions/core'
import type { Context } from '@actions/github/lib/context'
type TokenResponse = {
token: string
}
type AuthService = {
url: string
key: string
name: string
}
export const STAGING_SERVICE: AuthService = {
url: 'https://github-auth.staging.code-pushup.dev',
key: '18850f2513adad10662e85f4f085a9714e64cef7793fc2ffe903b5ddcd62de42',
name: 'Code PushUp (staging)'
}
export const PRODUCTION_SERVICE: AuthService = {
url: 'https://github-auth.code-pushup.dev',
key: 'b2585352366ceead1323a1f3a7cf6b9212387ea6d2d8aeb397e7950aaa3ba776',
name: 'Code PushUp'
}
export async function authenticate(
{ owner, repo }: Context['repo'],
token: string
): Promise<string> {
if (token !== process.env.GITHUB_TOKEN) {
core.info('Using user-provided PAT')
return token
}
const productionResult = await tryService(PRODUCTION_SERVICE, owner, repo)
if (productionResult) {
core.info(`Using ${PRODUCTION_SERVICE.name} GitHub App installation token`)
return productionResult.token
}
const stagingResult = await tryService(STAGING_SERVICE, owner, repo)
if (stagingResult) {
core.info(`Using ${STAGING_SERVICE.name} GitHub App installation token`)
return stagingResult.token
}
core.info('Using default GITHUB_TOKEN')
return token
}
async function tryService(
service: AuthService,
owner: string,
repo: string
): Promise<{ token: string; service: AuthService } | null> {
try {
const response = await fetch(
`${service.url}/github/${owner}/${repo}/installation-token`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${service.key}`
}
}
)
const data = await response.json()
if (response.ok && isTokenResponse(data)) {
return { token: data.token, service }
}
handleErrorResponse(response.status, service.name)
} catch (error) {
core.debug(
`Unable to contact ${service.name} authentication service: ${error}`
)
return null
}
return null
}
function isTokenResponse(res: unknown): res is TokenResponse {
return (
!!res &&
typeof res === 'object' &&
'token' in res &&
typeof res.token === 'string'
)
}
function handleErrorResponse(status: number, serviceName: string): void {
switch (status) {
case 404:
core.debug(`${serviceName} GitHub App not installed on this repository`)
break
case 401:
core.warning(`${serviceName} authentication service authorization failed`)
break
case 500:
core.warning(
`${serviceName} authentication service temporarily unavailable`
)
break
default:
core.warning(
`${serviceName} authentication service returned unexpected status: ${status}`
)
}
}