forked from danger/peril
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgithub_helpers.ts
More file actions
96 lines (87 loc) · 3.57 KB
/
github_helpers.ts
File metadata and controls
96 lines (87 loc) · 3.57 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
import fetch from "../../api/fetch"
import { getTemporaryAccessTokenForInstallation } from "../../api/github"
import { RepresentationForURL } from "../../danger/danger_run"
import { PERIL_ORG_INSTALLATION_ID } from "../../globals"
import winston from "../../logger"
export async function canUserWriteToRepo(token: string, user: string, repoSlug: string) {
// https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level
const req = await api(token, `repos/${repoSlug}/collaborators/${user}/permission`)
const res = await req.json()
return res.permission === "admin" || res.permission === "write"
}
export async function getGitHubFileContentsFromLocation(
token: string | null,
location: RepresentationForURL,
defaultRepo: string
) {
return getGitHubFileContents(token, location.repoSlug || defaultRepo, location.dangerfilePath, location.branch)
}
/**
* This function allows you to get the contents of a file from GitHub,
* given a token.
* Returns either the contents or an empty string.
*/
export async function getGitHubFileContents(token: string | null, repoSlug: string, path: string, ref: string | null, showError: boolean = true) {
const refString = ref ? `ref=${ref}` : ""
const res = await api(token, `repos/${repoSlug}/contents/${path}?${refString}`)
const data = await res.json()
if (res.ok) {
const buffer = Buffer.from(data.content, "base64")
return buffer.toString()
} else {
if (showError) {
winston.error("res: " + res.url)
winston.error("Getting GitHub file failed: " + JSON.stringify(data))
}
return ""
}
}
/**
* There's definitely a time when you want access to a GitHub file
* but won't have an auth token to do it yet, this function should
* help out there, as long as the Peril key and installation ID are
* in the environment it will build the appropriate auth.
* Returns either the contents or an empty string.
*/
export async function getGitHubFileContentsWithoutToken(repo: string, path: string) {
// Try see if we can pull it without an access token
const file = await getGitHubFileContents(null, repo, path, null, false);
if (file !== "") {
return file
}
// Might be private, in this case you have to have set up PERIL_ORG_INSTALLATION_ID
if (!PERIL_ORG_INSTALLATION_ID) {
throwNoPerilInstallationID()
}
const token = await getTemporaryAccessTokenForInstallation(PERIL_ORG_INSTALLATION_ID)
return await getGitHubFileContents(token, repo, path, null)
}
const throwNoPerilInstallationID = () => {
/* tslint:disable: max-line-length */
const msg =
"Sorry, if you have a Peril JSON settings file in a private repo, you will need an installation ID for your integration."
const subtitle =
"You can find this inside the integration_installation event sent when you installed the integration into your org."
const action = `Set this as "PERIL_ORG_INSTALLATION_ID" in your ENV vars.`
throw new Error([msg, subtitle, action].join(" "))
/* tslint:enable: max-line-length */
}
/**
* A quick GitHub API client
*/
async function api(token: string | null, path: string, headers: any = {}, body: any = {}, method: string = "GET") {
if (token) {
headers.Authorization = `token ${token}`
}
const baseUrl = process.env.DANGER_GITHUB_API_BASE_URL || "https://api.github.com"
const includeBody = !(method === "GET" || method === "HEAD")
return fetch(`${baseUrl}/${path}`, {
body: includeBody ? body : undefined,
headers: {
Accept: "application/vnd.github.machine-man-preview+json",
"Content-Type": "application/json",
...headers,
},
method,
})
}