Skip to content

Commit

Permalink
Merge pull request #691 from azz/jenkins-dx
Browse files Browse the repository at this point in the history
Support Multibranch pipelines in Jenkins
  • Loading branch information
orta authored Oct 11, 2018
2 parents dcc4815 + 3393ff0 commit f2a723c
Show file tree
Hide file tree
Showing 5 changed files with 1,427 additions and 63 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

## Master

- Jenkins: Respect `CHANGE_URL`/`CHANGE_ID` for GitHub and BitBucket Server [@azz][]

# 4.4.0

- Supports installation using Homebrew [@thii][]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@
"jest-json-reporter": "^1.2.2",
"lint-staged": "^7.3.0",
"madge": "^3.2.0",
"prettier": "^1.14.2",
"pkg": "^4.3.4",
"prettier": "^1.14.2",
"release-it": "^7.6.1",
"shx": "^0.3.2",
"ts-jest": "^23.10.3",
Expand Down
34 changes: 25 additions & 9 deletions source/ci_source/providers/Jenkins.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Env, CISource } from "../ci_source"
import { ensureEnvKeysExist, ensureEnvKeysAreInt } from "../ci_source_helpers"
import { pullRequestParser } from "../../platforms/pullRequestParser"

// https://jenkins.io/
// https://wiki.jenkins.io/display/JENKINS/Building+a+software+project#Buildingasoftwareproject-belowJenkinsSetEnvironmentVariables
Expand All @@ -14,9 +15,8 @@ import { ensureEnvKeysExist, ensureEnvKeysAreInt } from "../ci_source_helpers"
* in order to ensure that you have the build environment set up for PR integration.
*
* ### BitBucket Server
* If using Bitbucket Server, make sure to provide both `ghprbGhRepository` and `ghprbPullId` as environment variables.
* `ghprbGhRepository` is the path to your repository, e.g. `projects/team/repos/repositoryname`, while `ghprbPullId`
* provides the id of a pull request (usually `env.CHANGE_ID`). Danger will skip execution if this id is not provided.
* If using Bitbucket Server, ensure you are using Multibranch Pipelines or Organization Folders.
* Danger will respect the `CHANGE_URL` and `CHANGE_ID` environment variables.
*
* With that set up, you can edit your job to add `yarn danger ci` at the build action.
*
Expand All @@ -34,29 +34,45 @@ import { ensureEnvKeysExist, ensureEnvKeysAreInt } from "../ci_source_helpers"
export class Jenkins implements CISource {
constructor(private readonly env: Env) {}

private isJenkins() {
return ensureEnvKeysExist(this.env, ["JENKINS_URL"])
}

get name(): string {
return "Jenkins"
}

get isCI(): boolean {
return ensureEnvKeysExist(this.env, ["JENKINS_URL"])
return this.isJenkins()
}

get isPR(): boolean {
const mustHave = ["JENKINS_URL", "ghprbPullId", "ghprbGhRepository"]
const mustBeInts = ["ghprbPullId"]
return ensureEnvKeysExist(this.env, mustHave) && ensureEnvKeysAreInt(this.env, mustBeInts)
const isGitHubPR =
ensureEnvKeysExist(this.env, ["ghprbPullId", "ghprbGhRepository"]) &&
ensureEnvKeysAreInt(this.env, ["ghprbPullId"])
const isMultiBranchPR =
ensureEnvKeysExist(this.env, ["CHANGE_ID", "CHANGE_URL"]) && ensureEnvKeysAreInt(this.env, ["CHANGE_ID"])

return this.isJenkins() && (isMultiBranchPR || isGitHubPR)
}

get pullRequestID(): string {
return this.env.ghprbPullId
return this.env.ghprbPullId || this.env.CHANGE_ID
}

get repoSlug(): string {
if (this.env.CHANGE_URL) {
const result = pullRequestParser(this.env.CHANGE_URL)
if (!result) {
throw new Error(`Unable to get repository path from $CHANGE_URL`)
}

return result.repo
}
return this.env.ghprbGhRepository
}

get ciRunURL() {
return process.env.BUILD_URL
return process.env.RUN_DISPLAY_URL || process.env.BUILD_URL
}
}
86 changes: 61 additions & 25 deletions source/ci_source/providers/_tests/_jenkins.test.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
import { Jenkins } from "../Jenkins"
import { getCISourceForEnv } from "../../get_ci_source"

const correctEnv = {
ghprbGhRepository: "danger/danger-js",
ghprbPullId: "50",
JENKINS_URL: "https://danger.jenkins",
const envs = {
ghprb: {
ghprbGhRepository: "danger/danger-js",
ghprbPullId: "50",
JENKINS_URL: "https://danger.jenkins",
},
multibranchGitHub: {
CHANGE_URL: "https://github.com/danger/danger-js/pull/50",
CHANGE_ID: "50",
JENKINS_URL: "https://danger.jenkins",
},
multibranchBBS: {
CHANGE_URL: "https://bitbucket.server/projects/PROJ/repos/REPO/pull-requests/50",
CHANGE_ID: "50",
JENKINS_URL: "https://danger.jenkins",
},
}

const types = Object.keys(envs)

describe("being found when looking for CI", () => {
it("finds Jenkins with the right ENV", () => {
const ci = getCISourceForEnv(correctEnv)
it.each(types)("%s - finds Jenkins with the right ENV", type => {
const env = envs[type]
const ci = getCISourceForEnv(env)
expect(ci).toBeInstanceOf(Jenkins)
})
})

describe(".isCI", () => {
it("validates when JENKINS_URL is present in environment", () => {
const jenkins = new Jenkins(correctEnv)
it.each(types)("%s - validates when JENKINS_URL is present in environment", type => {
const jenkins = new Jenkins(envs[type])
expect(jenkins.isCI).toBeTruthy()
})

Expand All @@ -27,8 +42,8 @@ describe(".isCI", () => {
})

describe(".isPR", () => {
it("validates when all Jenkins environment variables are set", () => {
const jenkins = new Jenkins(correctEnv)
it.each(types)("%s - validates when all Jenkins environment variables are set", type => {
const jenkins = new Jenkins(envs[type])
expect(jenkins.isPR).toBeTruthy()
})

Expand All @@ -37,39 +52,60 @@ describe(".isPR", () => {
expect(jenkins.isPR).toBeFalsy()
})

const envs = ["JENKINS_URL", "ghprbPullId", "ghprbGhRepository"]
envs.forEach((key: string) => {
const env = {
...correctEnv,
[key]: null,
}
describe.each(types)("%s", type => {
const envVars = Object.keys(envs[type])
envVars.forEach((key: string) => {
const env = {
...envs[type],
[key]: null,
}

it(`does not validate when ${key} is missing`, () => {
const jenkins = new Jenkins(env)
expect(jenkins.isPR).toBeFalsy()
it(`does not validate when ${key} is missing`, () => {
const jenkins = new Jenkins(env)
expect(jenkins.isPR).toBeFalsy()
})
})
})

it("needs to have a PR number", () => {
it("ghprb - needs to have a PR number", () => {
const env = {
...correctEnv,
...envs.ghprb,
ghprbPullId: "not a number",
}
const jenkins = new Jenkins(env)
expect(jenkins.isPR).toBeFalsy()
})

it("multibranch - needs to have a PR number", () => {
const env = {
...envs.multibranchGitHub,
CHANGE_ID: "not a number",
}
const jenkins = new Jenkins(env)
expect(jenkins.isPR).toBeFalsy()
})
})

describe(".pullRequestID", () => {
it("pulls it out of environment", () => {
const jenkins = new Jenkins(correctEnv)
it.each(types)("%s - pulls it out of environment", type => {
const jenkins = new Jenkins(envs[type])
expect(jenkins.pullRequestID).toEqual("50")
})
})

describe(".repoSlug", () => {
it("pulls it out of environment", () => {
const jenkins = new Jenkins(correctEnv)
it("ghprb - pulls it out of environment", () => {
const jenkins = new Jenkins(envs.ghprb)
expect(jenkins.repoSlug).toEqual("danger/danger-js")
})

it("multibranch-github - pulls it out of environment", () => {
const jenkins = new Jenkins(envs.multibranchGitHub)
expect(jenkins.repoSlug).toEqual("danger/danger-js")
})

it("multibranch-bb-server - pulls it out of environment", () => {
const jenkins = new Jenkins(envs.multibranchBBS)
expect(jenkins.repoSlug).toEqual("projects/PROJ/repos/REPO")
})
})
Loading

0 comments on commit f2a723c

Please sign in to comment.