-
-
Notifications
You must be signed in to change notification settings - Fork 362
/
danger-pr.ts
147 lines (130 loc) · 5.78 KB
/
danger-pr.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
#! /usr/bin/env node
import program from "commander"
import { debug } from "../debug"
import prettyjson from "prettyjson"
import { FakeCI } from "../ci_source/providers/Fake"
import { pullRequestParser } from "../platforms/pullRequestParser"
import { dangerfilePath } from "./utils/fileUtils"
import setSharedArgs, { SharedCLI } from "./utils/sharedDangerfileArgs"
import { jsonDSLGenerator } from "../runner/dslGenerator"
import { prepareDangerDSL } from "./utils/runDangerSubprocess"
import { runRunner } from "./ci/runner"
import { Platform, getPlatformForEnv } from "../platforms/platform"
import { CISource } from "../ci_source/ci_source"
import { getGitLabHostFromEnv } from "../platforms/gitlab/GitLabAPI"
const d = debug("pr")
const log = console.log
interface App extends SharedCLI {
/** Should we show the Danger Process PR JSON? */
json?: boolean
/** Should we show a more human readable for of the PR JSON? */
js?: boolean
}
program
.usage("[options] <pr_url>")
.description("Emulate running Danger against an existing GitHub Pull Request.")
.option("-J, --json", "Output the raw JSON that would be passed into `danger process` for this PR.")
.option("-j, --js", "A more human-readable version of the JSON.")
.allowUnknownOption(true)
.on("--help", () => {
log("\n")
log(" Docs:")
if (
!process.env["DANGER_GITHUB_API_TOKEN"] &&
!process.env["DANGER_BITBUCKETSERVER_HOST"] &&
!process.env["DANGER_BITBUCKETCLOUD_OAUTH_KEY"] &&
!process.env["DANGER_BITBUCKETCLOUD_USERNAME"] &&
!process.env["DANGER_BITBUCKETCLOUD_REPO_ACCESSTOKEN"] &&
!process.env["DANGER_GITLAB_API_TOKEN"] &&
!process.env["DANGER_GITLAB_API_OAUTH_TOKEN"]
) {
log("")
log(
" You don't have a DANGER_GITHUB_API_TOKEN/DANGER_GITLAB_API_TOKEN/DANGER_GITLAB_API_OAUTH_TOKEN/DANGER_BITBUCKETCLOUD_OAUTH_KEY/DANGER_BITBUCKETCLOUD_USERNAME/DANGER_BITBUCKETCLOUD_REPO_ACCESSTOKEN set up, this is optional, but TBH, you want to do this."
)
log(" Check out: http://danger.systems/js/guides/the_dangerfile.html#working-on-your-dangerfile")
log("")
}
log("")
log(" -> API Reference")
log(" http://danger.systems/js/reference.html")
log("")
log(" -> Getting started:")
log(" http://danger.systems/js/guides/getting_started.html")
log("")
log(" -> The Dangerfile")
log(" http://danger.systems/js/guides/the_dangerfile.html")
})
setSharedArgs(program).parse(process.argv)
const app = program as any as App
const customProcess = !!app.process
if (program.args.length === 0) {
console.error("Please include a PR URL to run against")
process.exitCode = 1
} else {
const customHost =
process.env["DANGER_GITHUB_HOST"] || process.env["DANGER_BITBUCKETSERVER_HOST"] || getGitLabHostFromEnv(process.env) // This defaults to https://www.gitlab.com
// Allow an ambiguous amount of args to find the PR reference
const findPR = program.args.find((a) => a.includes(customHost) || a.includes("github") || a.includes("bitbucket.org"))
if (!findPR) {
console.error(`Could not find an arg which mentioned GitHub, BitBucket Server, BitBucket Cloud, or GitLab.`)
process.exitCode = 1
} else {
const pr = pullRequestParser(findPR)
if (!pr) {
console.error(`Could not get a repo and a PR number from your PR: ${findPR}, bad copy & paste?`)
process.exitCode = 1
} else {
// TODO: Use custom `fetch` in GitHub that stores and uses local cache if PR is closed, these PRs
// shouldn't change often and there is a limit on API calls per hour.
const isJSON = app.js || app.json
const note = isJSON ? console.error : console.log
note(`Starting Danger PR on ${pr.repo}#${pr.pullRequestNumber}`)
if (customProcess || isJSON || dangerfilePath(program)) {
if (!customProcess) {
d(`executing dangerfile at ${dangerfilePath(program)}`)
}
const source = new FakeCI({ DANGER_TEST_REPO: pr.repo, DANGER_TEST_PR: pr.pullRequestNumber })
const platform = getPlatformForEnv(
{
...process.env,
// Inject a platform hint, its up to getPlatformForEnv to decide if the environment is suitable for the
// requested platform. Because we have a URL we can determine with greater accuracy what platform that the
// user is attempting to test. This complexity is required because danger-pr defaults to using
// un-authenticated GitHub where typically when using FakeCI we want to use Fake(Platform) e.g. when running
// danger-local
DANGER_PR_PLATFORM: pr.platform,
},
source
)
if (isJSON) {
d("getting just the JSON/JS DSL")
runHalfProcessJSON(platform, source)
} else {
d("running process separated Danger")
// Always post to STDOUT in `danger-pr`
app.textOnly = true
// Can't send these to `danger runner`
delete app.js
delete app.json
runRunner(app, { source, platform, additionalEnvVars: { DANGER_LOCAL_NO_CI: "yep" } })
}
}
}
}
}
// Run the first part of a Danger Process and output the JSON to CLI
async function runHalfProcessJSON(platform: Platform, source: CISource) {
const dangerDSL = await jsonDSLGenerator(platform, source, program)
// Truncate the access token
if (dangerDSL.settings.github && dangerDSL.settings.github.accessToken) {
dangerDSL.settings.github.accessToken = dangerDSL.settings.github.accessToken.substring(0, 4) + "..."
}
const processInput = prepareDangerDSL(dangerDSL)
const output = JSON.parse(processInput)
if (app.json) {
process.stdout.write(JSON.stringify(output, null, 2))
} else if (app.js) {
console.log(prettyjson.render(output))
}
}