diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a8ca835..94b9c8f2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,8 +15,16 @@ -- Adds GitLab & GitLab CI support. - [@notjosh, @bigkraig] +- Adds GitLab & GitLab CI support. - [@notjosh, @bigkraig, @jamime] + +# 7.1.4 + +- Un-hardcodes the repo in `danger.github.utils.createOrUpdatePR`- [@ds300] + +# 7.1.3 + - Cleans up the declarations a little bit - [@orta] +- Adds support for [Codefresh CI](https://codefresh.io) - [@stevenp] # 7.1.2 @@ -69,9 +77,8 @@ # 7.0.18 -- Adds a CLI option `--fail-on-errors` so that you can force `danger ci` to return a failed exit code on any `fail`s in - a Dangerfile [@f-meloni] -- Add a failOnErrors option to fail the build if there are error on the danger report [@f-meloni] +- Adds a CLI option `--failOnErrors` so that you can force `danger ci` to return a failed exit code on any `fail`s in a + Dangerfile [@f-meloni] # 7.0.17 @@ -1620,9 +1627,11 @@ Not usable for others, only stubs of classes etc. - [@orta] [@sgtcoolguy]: https://github.com/sgtcoolguy [@sharkysharks]: https://github.com/sharkysharks [@stevemoser]: https://github.com/stevemoser +[@stevenp]: https://github.com/stevenp [@sunshinejr]: https://github.com/sunshinejr [@tychota]: https://github.com/tychota [@urkle]: https://github.com/urkle [@wizardishungry]: https://github.com/wizardishungry [@dblandin]: https://github.com/dblandin [@paulmelnikow]: https://github.com/paulmelnikow +[@ds300]: https://github.com/ds300 diff --git a/README.md b/README.md index bd324c7fe..4bf415b13 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ You can use Danger to codify your teams norms, leaving humans to think about har Danger JS works with GitHub, GitLab or BitBucket Server for code review, then with: Travis CI, GitLab CI, Circle CI, GitHub Actions, Semaphore, Jenkins, Docker Cloud, Bitrise, surf-build, Codeship, Drone, Buildkite, Nevercode, -buddybuild, TeamCity, Visual Studio Team Services, Screwdriver, Concourse, Netlify or CodeBuild. +buddybuild, TeamCity, Visual Studio Team Services, Screwdriver, Concourse, Netlify, CodeBuild or Codefresh. [![npm](https://img.shields.io/npm/v/danger.svg)](https://www.npmjs.com/package/danger) [![Build Status](https://travis-ci.org/danger/danger-js.svg?branch=master)](https://travis-ci.org/danger/danger-js) diff --git a/package.json b/package.json index 3f5ad9f30..851a87c77 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "danger", - "version": "7.1.2", + "version": "7.1.4", "description": "Unit tests for Team Culture", "main": "distribution/danger.js", "typings": "distribution/danger.d.ts", diff --git a/source/ci_source/providers/Codefresh.ts b/source/ci_source/providers/Codefresh.ts new file mode 100644 index 000000000..e71e31f30 --- /dev/null +++ b/source/ci_source/providers/Codefresh.ts @@ -0,0 +1,69 @@ +import { Env, CISource } from "../ci_source" +import { ensureEnvKeysExist, ensureEnvKeysAreInt } from "../ci_source_helpers" + +/** + * ### CI Setup + * + * To set up Danger on Codefresh, create a freestyle step in your Codefresh yaml configuration: + * + * ```yml + * Danger: + * title: Run Danger + * image: node:latest + * working_directory: ${{main_clone}} + * entry_point: '/bin/bash' + * cmd: + * - '-ce' + * - | + * npm install -g yarn + * yarn add danger --dev + * yarn danger ci --failOnErrors + * when: + * steps: + * - name: main_clone + * on: + * - success + * ``` + * + * The `failOnErrors` option is required in order to ensure that the step fails properly when Danger fails. If you don't wnat this behavior, you can remove this option. + * + * Don't forget to add the `DANGER_GITHUB_API_TOKEN` variable to your pipeline settings so that Danger can properly post comments to your pull request. + * + */ + +export class Codefresh implements CISource { + constructor(private readonly env: Env) {} + + get name(): string { + return "Codefresh" + } + + get isCI(): boolean { + return ensureEnvKeysExist(this.env, ["CF_BUILD_ID", "CF_BUILD_URL"]) + } + + get isPR(): boolean { + return ( + ensureEnvKeysExist(this.env, ["CF_PULL_REQUEST_NUMBER"]) && + ensureEnvKeysAreInt(this.env, ["CF_PULL_REQUEST_NUMBER"]) + ) + } + + get pullRequestID(): string { + if (this.env.CF_PULL_REQUEST_NUMBER) { + return this.env.CF_PULL_REQUEST_NUMBER + } else { + return "" + } + } + + get repoSlug(): string { + const owner = this.env.CF_REPO_OWNER + const reponame = this.env.CF_REPO_NAME + return owner && reponame ? `${owner}/${reponame}` : "" + } + + get ciRunURL() { + return this.env.CF_BUILD_URL + } +} diff --git a/source/ci_source/providers/_tests/_codefresh.test.ts b/source/ci_source/providers/_tests/_codefresh.test.ts new file mode 100644 index 000000000..07d5f027b --- /dev/null +++ b/source/ci_source/providers/_tests/_codefresh.test.ts @@ -0,0 +1,80 @@ +import { Codefresh } from "../Codefresh" +import { getCISourceForEnv } from "../../get_ci_source" + +const correctEnv = { + CF_REPO_OWNER: "codefresh", + CF_REPO_NAME: "someproject", + CF_BUILD_ID: "1501", + CF_PULL_REQUEST_NUMBER: "800", + CF_BUILD_URL: "https://g.codefresh.io/build/1234", +} + +describe("being found when looking for CI", () => { + it("finds Codefresh with the right ENV", () => { + const ci = getCISourceForEnv(correctEnv) + expect(ci).toBeInstanceOf(Codefresh) + }) +}) + +describe(".isCI", () => { + it("validates when all Codefresh environment vars are set", () => { + const codefresh = new Codefresh(correctEnv) + expect(codefresh.isCI).toBeTruthy() + }) + + it("does not validate without env", () => { + const codefresh = new Codefresh({}) + expect(codefresh.isCI).toBeFalsy() + }) +}) + +describe(".isPR", () => { + it("validates when all Codefresh environment vars are set", () => { + const codefresh = new Codefresh(correctEnv) + expect(codefresh.isPR).toBeTruthy() + }) + + it("does not validate outside of Codefresh", () => { + const codefresh = new Codefresh({}) + expect(codefresh.isPR).toBeFalsy() + }) + + const envs = ["CF_REPO_OWNER", "CF_REPO_NAME", "CF_BUILD_ID", "CF_PULL_REQUEST_NUMBER", "CF_BUILD_URL"] + envs.forEach((key: string) => { + let env = { + CF_REPO_OWNER: "codefresh", + CF_REPO_NAME: "someproject", + CF_BUILD_ID: "1501", + CF_PULL_REQUEST_NUMBER: "800", + CF_BUILD_URL: "https://g.codefresh.io/build/1234", + } + env[key] = null + + it(`does not validate when ${key} is missing`, () => { + const codefresh = new Codefresh({}) + expect(codefresh.isPR).toBeFalsy() + }) + }) + + it("needs to have an integer PR number", () => { + let env = { + CF_PULL_REQUEST_NUMBER: "asdasd", + } + const codefresh = new Codefresh(env) + expect(codefresh.isPR).toBeFalsy() + }) +}) + +describe(".pullRequestID", () => { + it("pulls it out of the env", () => { + const codefresh = new Codefresh({ CF_PULL_REQUEST_NUMBER: "800" }) + expect(codefresh.pullRequestID).toEqual("800") + }) +}) + +describe(".repoSlug", () => { + it("derives it from the PR Url", () => { + const codefresh = new Codefresh(correctEnv) + expect(codefresh.repoSlug).toEqual("codefresh/someproject") + }) +}) diff --git a/source/ci_source/providers/index.ts b/source/ci_source/providers/index.ts index 94828b3a7..07b143738 100644 --- a/source/ci_source/providers/index.ts +++ b/source/ci_source/providers/index.ts @@ -3,6 +3,7 @@ import { BuddyBuild } from "./BuddyBuild" import { Buildkite } from "./Buildkite" import { Circle } from "./Circle" import { CodeBuild } from "./CodeBuild" +import { Codefresh } from "./Codefresh" import { Codeship } from "./Codeship" import { Concourse } from "./Concourse" import { DockerCloud } from "./DockerCloud" @@ -42,6 +43,7 @@ const providers = [ Concourse, Netlify, CodeBuild, + Codefresh, ] // Mainly used for Dangerfile linting @@ -65,6 +67,7 @@ const realProviders = [ Concourse, Netlify, CodeBuild, + Codefresh, ] export { providers, realProviders } diff --git a/source/platforms/github/GitHubUtils.ts b/source/platforms/github/GitHubUtils.ts index d9dc98e73..977d74e7e 100644 --- a/source/platforms/github/GitHubUtils.ts +++ b/source/platforms/github/GitHubUtils.ts @@ -157,19 +157,19 @@ export const createOrUpdatePR = (pr: GitHubPRDSL | undefined, api: GitHub) => as d("Updating existing PR") return await api.pulls.update({ number: existingPR.number, - base: "source", - owner: "artsy", - repo: "artsy.github.io", + base: config.baseBranch, + owner, + repo, title: config.title, body: config.body, }) } else { d("Creating a new PR") return await api.pulls.create({ - base: "source", + base: config.baseBranch, head: config.newBranchName, - owner: "artsy", - repo: "artsy.github.io", + owner, + repo, title: config.title, }) }