-
-
Notifications
You must be signed in to change notification settings - Fork 374
/
Copy pathGitHub.ts
155 lines (130 loc) · 5 KB
/
GitHub.ts
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import { GitHubPRDSL, GitHubDSL, GitHubAPIPR, GitHubJSONDSL } from "../dsl/GitHubDSL"
import { GitHubAPI } from "./github/GitHubAPI"
import GitHubUtils from "./github/GitHubUtils"
import gitDSLForGitHub from "./github/GitHubGit"
import { Octokit as NodeGitHub } from "@octokit/rest"
import { Platform } from "./platform"
import { GitHubIssueCommenter } from "./github/comms/issueCommenter"
import { GitHubChecksCommenter } from "./github/comms/checksCommenter"
/** Handles conforming to the Platform Interface for GitHub, API work is handle by GitHubAPI */
export type GitHubType = Platform & { api: GitHubAPI }
export function GitHub(api: GitHubAPI) {
/**
* Converts the PR JSON into something easily used by the Github API client.
*/
const APIMetadataForPR = (pr: GitHubPRDSL): GitHubAPIPR => {
return {
number: pr.number,
repo: pr.base.repo.name,
owner: pr.base.repo.owner.login,
}
}
/** A quick one off func to ensure there's always some labels */
const getIssue = async () => {
const issue = await api.getIssue()
return issue || { labels: [] }
}
return {
name: "GitHub",
api,
getReviewInfo: api.getPullRequestInfo,
getPlatformGitRepresentation: () => gitDSLForGitHub(api),
getPlatformReviewDSLRepresentation: async () => {
let pr: GitHubPRDSL
try {
pr = await api.getPullRequestInfo()
} catch {
process.exitCode = 1
throw `
Could not find pull request information,
if you are using a private repo then perhaps
Danger does not have permission to access that repo.
`
}
const issue = await getIssue()
const commits = await api.getPullRequestCommits()
const reviews = await api.getReviews()
const requested_reviewers = await api.getReviewerRequests()
const thisPR = APIMetadataForPR(pr)
return {
issue,
pr,
commits,
reviews,
requested_reviewers,
thisPR,
}
},
// When there's an event we don't need any of ^
getPlatformReviewSimpleRepresentation: async () => ({}),
...GitHubIssueCommenter(api),
...(GitHubChecksCommenter(api) || {}),
getFileContents: api.fileContents,
executeRuntimeEnvironment,
} as GitHubType
}
// This class should get un-classed, but for now we can expand by functions
export const githubJSONToGitHubDSL = (gh: GitHubJSONDSL, api: NodeGitHub): GitHubDSL => {
return {
...gh,
api,
utils: GitHubUtils(gh.pr, api),
}
}
import overrideRequire from "override-require"
import {
customGitHubResolveRequest,
dangerPrefix,
shouldUseGitHubOverride,
getGitHubFileContentsFromLocation,
dangerRepresentationForPath,
} from "./github/customGitHubRequire"
import { DangerRunner } from "../runner/runners/runner"
import { existsSync, readFileSync } from "fs"
import cleanDangerfile from "../runner/runners/utils/cleanDangerfile"
import transpiler from "../runner/runners/utils/transpiler"
import { getGitHubAPIToken } from "./github/getGitHubAPIToken"
const executeRuntimeEnvironment = async (
start: DangerRunner["runDangerfileEnvironment"],
dangerfilePath: string,
environment: any
) => {
const token = await getGitHubAPIToken()
// Use custom module resolution to handle github urls instead of just fs access
const restoreOriginalModuleLoader = overrideRequire(shouldUseGitHubOverride, customGitHubResolveRequest(token))
// We need to validate that the
// dangerfile comes from the web, and do all the prefixing etc
let path: string
let content: string
if (existsSync(dangerfilePath)) {
path = dangerfilePath
content = readFileSync(dangerfilePath, "utf8")
} else {
path = dangerPrefix + dangerfilePath
const rep = dangerRepresentationForPath(dangerfilePath)
if (!rep.repoSlug) {
const msg = `if it is local, perhaps you have a typo? If it's using a remote file, it doesn't have a repo reference.`
throw new Error(`Could not find the Dangerfile at ${dangerfilePath} - ${msg}`)
}
const dangerfileContent = await getGitHubFileContentsFromLocation(token, rep, rep.repoSlug)
if (!dangerfileContent) {
const msg = `does a file exist at ${rep.dangerfilePath} in ${rep.repoSlug}?.`
throw new Error(`Could not find the Dangerfile at ${dangerfilePath} - ${msg}`)
}
// Chop off the danger import
const newDangerfile = cleanDangerfile(dangerfileContent)
// Cool, transpile it into something we can run
content = transpiler(newDangerfile, dangerfilePath)
}
// If there's an event.json - we should always pass it inside the default export
// For PRs, people will probably ignore it because of `danger.github.pr` but
// it can't hurt to have the consistency.
let defaultExport = {}
if (existsSync("/github/workflow/event.json")) {
defaultExport = JSON.parse(readFileSync("/github/workflow/event.json", "utf8"))
}
// Actually start up[ the runtime evaluation
await start([path], [content], environment, defaultExport)
// Undo the runtime
restoreOriginalModuleLoader()
}