Skip to content

Commit

Permalink
It runs
Browse files Browse the repository at this point in the history
  • Loading branch information
azz committed Feb 25, 2018
1 parent 251114d commit 2a8f9c5
Show file tree
Hide file tree
Showing 15 changed files with 141 additions and 85 deletions.
6 changes: 5 additions & 1 deletion dangerfile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ declare function fail(params: string): void
// declare function schedule(callback: (resolve: any) => void): void

const checkREADME = async () => {
if (!danger.github) {
return
}

// Request a CHANGELOG entry if not declared #trivial
const hasChangelog = danger.git.modified_files.includes("CHANGELOG.md")
const isTrivial = (danger.github.pr.body + danger.github.pr.title).includes("#trivial")
const isGreenkeeper = danger.github.pr.user.login === "greenkeeper"
const isGreenkeeper = danger.github!.pr.user.login === "greenkeeper"

// Politely ask for their name on the entry too
if (!hasChangelog && !isTrivial && !isGreenkeeper) {
Expand Down
4 changes: 4 additions & 0 deletions source/ci_source/ci_source_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export function ensureEnvKeysAreInt(env: Env, keys: string[]): boolean {
* If there are multiple pull requests open for a branch, returns the first.
*/
export async function getPullRequestIDForBranch(metadata: RepoMetaData, env: Env, branch: string): Promise<number> {
if (process.env["DANGER_BITBUCKETSERVER_HOST"]) {
// TODO:
}

const token = env["DANGER_GITHUB_API_TOKEN"]
if (!token) {
return 0
Expand Down
19 changes: 6 additions & 13 deletions source/commands/danger-pr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import * as debug from "debug"
import * as jsome from "jsome"

import { FakeCI } from "../ci_source/providers/Fake"
import { GitHub } from "../platforms/GitHub"
import { GitHubAPI } from "../platforms/github/GitHubAPI"
import { pullRequestParser } from "../platforms/github/pullRequestParser"
import { pullRequestParser } from "../platforms/pullRequestParser"
import { dangerfilePath } from "./utils/file-utils"
import validateDangerfileExists from "./utils/validateDangerfileExists"
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"

// yarn build; cat source/_tests/fixtures/danger-js-pr-384.json | node --inspect --inspect-brk distribution/commands/danger-runner.js --text-only

Expand All @@ -35,7 +34,7 @@ program
.on("--help", () => {
log("\n")
log(" Docs:")
if (!process.env["DANGER_GITHUB_API_TOKEN"]) {
if (!process.env["DANGER_GITHUB_API_TOKEN"] && !process.env["DANGER_BITBUCKETSERVER_HOST"]) {
log("")
log(" You don't have a DANGER_GITHUB_API_TOKEN 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")
Expand Down Expand Up @@ -71,19 +70,13 @@ if (program.args.length === 0) {
// 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 token = process.env["DANGER_GITHUB_API_TOKEN"]
if (!token) {
console.log("You don't have a DANGER_GITHUB_API_TOKEN set up, this is optional, but TBH, you want to do this")
console.log("Check out: http://danger.systems/js/guides/the_dangerfile.html#working-on-your-dangerfile")
}

console.log(`Starting Danger PR on ${pr.repo}#${pr.pullRequestNumber}`)

if (validateDangerfileExists(dangerFile)) {
d(`executing dangerfile at ${dangerFile}`)
const source = new FakeCI({ DANGER_TEST_REPO: pr.repo, DANGER_TEST_PR: pr.pullRequestNumber })
const api = new GitHubAPI(source, token)
const platform = new GitHub(api)
const platform = getPlatformForEnv(process.env, source, /* requireAuth */ false)

if (app.json || app.js) {
d("getting just the JSON/JS DSL")
runHalfProcessJSON(platform)
Expand All @@ -102,7 +95,7 @@ if (program.args.length === 0) {
}

// Run the first part of a Danger Process and output the JSON to CLI
async function runHalfProcessJSON(platform: GitHub) {
async function runHalfProcessJSON(platform: Platform) {
const dangerDSL = await jsonDSLGenerator(platform)
const processInput = prepareDangerDSL(dangerDSL)
const output = JSON.parse(processInput)
Expand Down
2 changes: 1 addition & 1 deletion source/commands/danger-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ getRuntimeCISource(app).then(source => {
if (!platform) {
console.log(chalk.red(`Could not find a source code hosting platform for ${source.name}.`))
console.log(
`Currently Danger JS only supports GitHub, if you want other platforms, consider the Ruby version or help out.`
`Currently Danger JS only supports GitHub and BitBucket Server, if you want other platforms, consider the Ruby version or help out.`
)
process.exitCode = 1
}
Expand Down
10 changes: 7 additions & 3 deletions source/dsl/DangerDSL.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GitDSL, GitJSONDSL } from "../dsl/GitDSL"
import { GitHubDSL } from "../dsl/GitHubDSL"
import { BitBucketServerDSL } from "../dsl/BitBucketServerDSL"
import { BitBucketServerDSL, BitBucketServerJSONDSL } from "../dsl/BitBucketServerDSL"
import { DangerUtilsDSL } from "./DangerUtilsDSL"
import { CliArgs } from "../runner/cli-args"

Expand Down Expand Up @@ -50,7 +50,9 @@ export interface DangerDSLJSONType {
/** The data only version of Git DSL */
git: GitJSONDSL
/** The data only version of GitHub DSL */
github: GitHubDSL
github?: GitHubDSL
/** The data only version of BitBucket Server DSL */
bitbucket_server?: BitBucketServerJSONDSL
/**
* Used in the Danger JSON DSL to pass metadata between
* processes. It will be undefined when used inside the Danger DSL
Expand Down Expand Up @@ -102,7 +104,9 @@ export interface DangerDSLType {
* this is the full JSON from the webhook. You can find the full
* typings for those webhooks [at github-webhook-event-types](https://github.com/orta/github-webhook-event-types).
*/
readonly github: GitHubDSL
readonly github?: GitHubDSL

readonly bitbucket_server?: BitBucketServerDSL

/**
* Functions which are globally useful in most Dangerfiles. Right
Expand Down
3 changes: 2 additions & 1 deletion source/platforms/BitBucketServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { GitJSONDSL } from "../dsl/GitDSL"
import { BitBucketServerPRDSL, BitBucketServerJSONDSL } from "../dsl/BitBucketServerDSL"
import { BitBucketServerAPI } from "./bitbucket_server/BitBucketServerAPI"
import gitDSLForBitBucketServer from "./bitbucket_server/BitBucketServerGit"
import { Platform } from "./platform"

/** Handles conforming to the Platform Interface for BitBucketServer, API work is handle by BitBucketServerAPI */

export class BitBucketServer {
export class BitBucketServer implements Platform {
name: string

constructor(public readonly api: BitBucketServerAPI) {
Expand Down
3 changes: 2 additions & 1 deletion source/platforms/GitHub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import GitHubUtils from "./github/GitHubUtils"
import gitDSLForGitHub from "./github/GitHubGit"

import * as NodeGitHub from "@octokit/rest"
import { Platform } from "./platform"

/** Handles conforming to the Platform Interface for GitHub, API work is handle by GitHubAPI */

export class GitHub {
export class GitHub implements Platform {
name: string

constructor(public readonly api: GitHubAPI) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,18 @@ describe("parsing urls", () => {
repo: "artsy/emission",
})
})

it("handles bitbucket server PRs", () => {
expect(pullRequestParser("http://localhost:7990/projects/PROJ/repos/repo/pull-requests/1")).toEqual({
pullRequestNumber: "1",
repo: "projects/PROJ/repos/repo",
})
})

it("handles bitbucket server PRs (overview)", () => {
expect(pullRequestParser("http://localhost:7990/projects/PROJ/repos/repo/pull-requests/1/overview")).toEqual({
pullRequestNumber: "1",
repo: "projects/PROJ/repos/repo",
})
})
})
46 changes: 22 additions & 24 deletions source/platforms/bitbucket_server/BitBucketServerAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,22 @@ import { api as fetch } from "../../api/fetch"

export class BitBucketServerAPI {
fetch: typeof fetch
private readonly baseUrl = process.env["DANGER_BITBUCKETSERVER_HOST"]
private readonly d = debug("danger:BitBucketServerAPI")

private pr: BitBucketServerPRDSL

constructor(
public readonly repoMetadata: RepoMetaData,
public readonly repoCredentials: { host: string; username: string; password: string }
public readonly repoCredentials: { host: string; username?: string; password?: string }
) {
// This allows Peril to DI in a new Fetch function
// which can handle unique API edge-cases around integrations
this.fetch = fetch
}

private getPRBasePath(service = "api") {
const [projectKey, repositorySlug] = this.repoMetadata.repoSlug.split("/")
const pullRequestId = this.repoMetadata.pullRequestID
return (
`${this.baseUrl}/rest/${service}/1.0/` +
`projects/${projectKey}/` +
`repos/${repositorySlug}/` +
`pull-requests/${pullRequestId}`
)
const { repoSlug, pullRequestID } = this.repoMetadata
return `rest/${service}/1.0/${repoSlug}/pull-requests/${pullRequestID}`
}

getPullRequestInfo = async (): Promise<BitBucketServerPRDSL> => {
Expand All @@ -52,19 +45,16 @@ export class BitBucketServerAPI {
}
const path = this.getPRBasePath()
const res = await this.get(path)
throwIfNotOk(res)
const prDSL = (await res.json()) as BitBucketServerPRDSL
this.pr = prDSL

if (res.ok) {
return prDSL
} else {
throw `Could not get PR Metadata for ${path}`
}
return prDSL
}

getPullRequestCommits = async (): Promise<BitBucketServerCommit[]> => {
const path = `${this.getPRBasePath()}/commits`
const res = await this.get(path)
throwIfNotOk(res)
return (await res.json()).values
}

Expand All @@ -76,18 +66,21 @@ export class BitBucketServerAPI {
getPullRequestComments = async (): Promise<BitBucketServerPRActivity[]> => {
const path = `${this.getPRBasePath()}/activities?fromType=COMMENT`
const res = await this.get(path)
throwIfNotOk(res)
return (await res.json()).values
}

getPullRequestActivities = async (): Promise<BitBucketServerPRActivity[]> => {
const path = `${this.getPRBasePath()}/activities?fromType=ACTIVITY`
const res = await this.get(path)
throwIfNotOk(res)
return (await res.json()).values
}

getIssues = async (): Promise<JIRAIssue[]> => {
const path = `${this.getPRBasePath("jira")}/issues`
const res = await this.get(path)
throwIfNotOk(res)
return await res.json()
}

Expand All @@ -105,13 +98,8 @@ export class BitBucketServerAPI {
}

getFileContents = async (filePath: string) => {
const [projectKey, repositorySlug] = this.repoMetadata.repoSlug.split("/")
const path =
`${this.baseUrl}/` +
`projects/${projectKey}/` +
`repos/${repositorySlug}/` +
`raw/${filePath}` +
`?at=${this.pr.toRef.id}`
const { repoSlug } = this.repoMetadata
const path = `${repoSlug}/` + `raw/${filePath}` + `?at=${this.pr.toRef.id}`
const res = await this.get(path)
return await res.text()
}
Expand Down Expand Up @@ -161,7 +149,7 @@ export class BitBucketServerAPI {

private api = (path: string, headers: any = {}, body: any = {}, method: string, suppressErrors?: boolean) => {
if (this.repoCredentials.username) {
headers["Authorization"] = `basic ${new Buffer(
headers["Authorization"] = `Basic ${new Buffer(
this.repoCredentials.username + ":" + this.repoCredentials.password
).toString("base64")}`
}
Expand Down Expand Up @@ -194,3 +182,13 @@ export class BitBucketServerAPI {
delete = (path: string, headers: any = {}, body: any = {}): Promise<node_fetch.Response> =>
this.api(path, headers, JSON.stringify(body), "DELETE")
}

function throwIfNotOk(res: node_fetch.Response) {
if (!res.ok) {
let message = `${res.status} - ${res.statusText}`
if (res.status >= 400 && res.status < 500) {
message += ` (Have you set DANGER_BITBUCKETSERVER_USERNAME and DANGER_BITBUCKETSERVER_PASSWORD?)`
}
throw new Error(message)
}
}
18 changes: 10 additions & 8 deletions source/platforms/bitbucket_server/BitBucketServerGit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { URL } from "url"

import { GitDSL, GitJSONDSL } from "../../dsl/GitDSL"
import { BitBucketServerCommit, BitBucketServerDSL } from "../../dsl/BitBucketServerDSL"
import { GitCommit } from "../../dsl/Commit"
Expand All @@ -10,6 +8,7 @@ import { diffToGitJSONDSL } from "../git/diffToGitJSONDSL"
import { GitJSONToGitDSLConfig, gitJSONToGitDSL } from "../git/gitJSONToGitDSL"

import * as debug from "debug"
import { RepoMetaData } from "../../ci_source/ci_source"
const d = debug("danger:BitBucketServerGit")

/**
Expand All @@ -18,11 +17,12 @@ const d = debug("danger:BitBucketServerGit")
* @param {BitBucketServerCommit} ghCommit A BitBucketServer based commit
* @returns {GitCommit} a Git commit representation without GH metadata
*/
function bitBucketServerCommitToGitCommit(bbsCommit: BitBucketServerCommit): GitCommit {
const url = new URL(
`projects/${null}/repos/${null}/commits/${bbsCommit.id}`, // TODO: need repoMetadata here
process.env["DANGER_BITBUCKET_HOST"]
).toString()
function bitBucketServerCommitToGitCommit(
bbsCommit: BitBucketServerCommit,
repoMetadata: RepoMetaData,
host: string
): GitCommit {
const url = `${host}/${repoMetadata.repoSlug}/commits/${bbsCommit.id}`
return {
sha: bbsCommit.id,
parents: bbsCommit.parents.map(p => p.id),
Expand All @@ -46,7 +46,9 @@ export default async function gitDSLForBitBucketServer(api: BitBucketServerAPI):
// We'll need all this info to be able to generate a working GitDSL object
const diff = await api.getPullRequestDiff()
const gitCommits = await api.getPullRequestCommits()
const commits = gitCommits.map(bitBucketServerCommitToGitCommit)
const commits = gitCommits.map(commit =>
bitBucketServerCommitToGitCommit(commit, api.repoMetadata, api.repoCredentials.host)
)
return diffToGitJSONDSL(diff, commits)
}

Expand Down
18 changes: 0 additions & 18 deletions source/platforms/github/pullRequestParser.ts

This file was deleted.

23 changes: 14 additions & 9 deletions source/platforms/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,7 @@ export interface Platform {
* @param {CISource} source The existing source, to ensure they can run against each other
* @returns {Platform} returns a platform if it can be supported
*/
export function getPlatformForEnv(env: Env, source: CISource): Platform {
// GitHub
const ghToken = env["DANGER_GITHUB_API_TOKEN"]
if (ghToken) {
const api = new GitHubAPI(source, ghToken)
const github = new GitHub(api)
return github
}

export function getPlatformForEnv(env: Env, source: CISource, requireAuth = true): Platform {
// BitBucket Server
const bbsHost = env["DANGER_BITBUCKETSERVER_HOST"]
if (bbsHost) {
Expand All @@ -78,6 +70,19 @@ export function getPlatformForEnv(env: Env, source: CISource): Platform {
return bbs
}

// GitHub
const ghToken = env["DANGER_GITHUB_API_TOKEN"]
if (ghToken || !requireAuth) {
if (!ghToken) {
console.log("You don't have a DANGER_GITHUB_API_TOKEN set up, this is optional, but TBH, you want to do this")
console.log("Check out: http://danger.systems/js/guides/the_dangerfile.html#working-on-your-dangerfile")
}

const api = new GitHubAPI(source, ghToken)
const github = new GitHub(api)
return github
}

console.error("The DANGER_GITHUB_API_TOKEN/DANGER_BITBUCKETSERVER_HOST environmental variable is missing")
console.error("Without an api token, danger will be unable to comment on a PR")
throw new Error("Cannot use authenticated API requests.")
Expand Down
Loading

0 comments on commit 2a8f9c5

Please sign in to comment.