diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ca6026e..968c2b5ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ +- Add Codemagic.io as a supported CI - [@fbartho] + # 10.6.1 diff --git a/README.md b/README.md index 3bd1620b1..3aca74c5c 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ You can use Danger to codify your team's norms, leaving humans to think about ha Danger JS works with GitHub, BitBucket Server, BitBucket Cloud for code review, then with: Travis CI, GitLab CI, Semaphore, Circle CI, GitHub Actions, Jenkins, Docker Cloud, Bamboo, Bitrise, surf-build, Codeship, Drone, Buildkite, Nevercode, buddybuild, Buddy.works, TeamCity, Visual Studio Team Services, Screwdriver, Concourse, Netlify, CodeBuild, -Codefresh, AppCenter, BitBucket Pipelines, or Cirrus CI. +Codefresh, AppCenter, BitBucket Pipelines, Cirrus CI, or Codemagic. [![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/source/ci_source/providers/Codemagic.ts b/source/ci_source/providers/Codemagic.ts new file mode 100644 index 000000000..7831f7869 --- /dev/null +++ b/source/ci_source/providers/Codemagic.ts @@ -0,0 +1,46 @@ +import { Env, CISource } from "../ci_source" +import { ensureEnvKeysExist, ensureEnvKeysAreInt } from "../ci_source_helpers" + +/** + * Codemagic.io CI Integration + * + * Environment Variables Documented: https://docs.codemagic.io/building/environment-variables/ + * Notice a bug in the docs?: https://github.com/codemagic-ci-cd/codemagic-docs + * + * Need support/advice? https://slack.codemagic.io/ + */ +export class Codemagic implements CISource { + constructor(private readonly env: Env) {} + + get name(): string { + return "Codemagic" + } + + get isCI(): boolean { + // Codemagic developer relations confirmed this is fine to use for this purpose + return ensureEnvKeysExist(this.env, ["FCI_BUILD_ID"]) + } + + get isPR(): boolean { + const mustHave = ["FCI_PULL_REQUEST", "FCI_REPO_SLUG", "FCI_PROJECT_ID", "FCI_BUILD_ID"] + const mustBeInts = ["BUILD_NUMBER", "FCI_PULL_REQUEST_NUMBER"] + return ( + ensureEnvKeysExist(this.env, mustHave) && + ensureEnvKeysAreInt(this.env, mustBeInts) && + this.env.FCI_PULL_REQUEST === "true" + ) + } + + get pullRequestID(): string { + return this.env.FCI_PULL_REQUEST_NUMBER + } + + get repoSlug(): string { + return this.env.FCI_REPO_SLUG + } + + get ciRunURL() { + const { FCI_BUILD_ID, FCI_PROJECT_ID } = process.env + return `https://codemagic.io/app/${FCI_PROJECT_ID}/build/${FCI_BUILD_ID}` + } +} diff --git a/source/ci_source/providers/Nevercode.ts b/source/ci_source/providers/Nevercode.ts index 861115bb8..1e13098cf 100644 --- a/source/ci_source/providers/Nevercode.ts +++ b/source/ci_source/providers/Nevercode.ts @@ -5,6 +5,13 @@ import { ensureEnvKeysExist, ensureEnvKeysAreInt } from "../ci_source_helpers" * Nevercode.io CI Integration * * Environment Variables Documented: https://developer.nevercode.io/v1.0/docs/environment-variables-files + * + * Note: The company that runs Nevercode is migrating all customers + * to their new service Codemagic.io in Spring of 2021 + * - billing is migrated through Customer Support + * - the CI Configuration is managed in your repo instead of in a web-dashboard. + * + * TODO @fbartho delete this integration when it's fully offline. */ export class Nevercode implements CISource { constructor(private readonly env: Env) {} diff --git a/source/ci_source/providers/_tests/_codemagic.test.ts b/source/ci_source/providers/_tests/_codemagic.test.ts new file mode 100644 index 000000000..c4e85845e --- /dev/null +++ b/source/ci_source/providers/_tests/_codemagic.test.ts @@ -0,0 +1,60 @@ +import { Codemagic } from "../Codemagic" +import { getCISourceForEnv } from "../../get_ci_source" + +const correctEnv = { + FCI_PROJECT_ID: "abcdef123-app-uuid", + FCI_BUILD_ID: "abcdef123-build-uuid", + FCI_REPO_SLUG: "danger/danger-js", + FCI_PULL_REQUEST: "true", + FCI_PULL_REQUEST_NUMBER: "2", + BUILD_NUMBER: "42", +} + +describe("being found when looking for CI", () => { + it("finds Codemagic with the right ENV", () => { + const ci = getCISourceForEnv(correctEnv) + expect(ci).toBeInstanceOf(Codemagic) + }) +}) + +describe(".isCI", () => { + it("validates when all Codemagic environment vars are set", () => { + const codemagic = new Codemagic(correctEnv) + expect(codemagic.isCI).toBeTruthy() + }) + + it("does not validate without env", () => { + const codemagic = new Codemagic({}) + expect(codemagic.isCI).toBeFalsy() + }) +}) + +describe(".isPR", () => { + it("validates when all codemagic environment vars are set", () => { + const codemagic = new Codemagic(correctEnv) + expect(codemagic.isPR).toBeTruthy() + }) + + it("does not validate outside of codemagic", () => { + const codemagic = new Codemagic({}) + expect(codemagic.isPR).toBeFalsy() + }) + + const envs = [ + "FCI_PULL_REQUEST", + "FCI_REPO_SLUG", + "FCI_PROJECT_ID", + "FCI_BUILD_ID", + "BUILD_NUMBER", + "FCI_PULL_REQUEST_NUMBER", + ] + envs.forEach((key: string) => { + let env = Object.assign({}, correctEnv) + delete env[key] + + it(`does not validate when ${key} is missing`, () => { + const codemagic = new Codemagic(env) + expect(codemagic.isCI && codemagic.isPR).toBeFalsy() + }) + }) +}) diff --git a/source/ci_source/providers/index.ts b/source/ci_source/providers/index.ts index eaaa39037..a9eea6173 100644 --- a/source/ci_source/providers/index.ts +++ b/source/ci_source/providers/index.ts @@ -10,6 +10,7 @@ import { Cirrus } from "./Cirrus" import { CodeBuild } from "./CodeBuild" import { Codefresh } from "./Codefresh" import { Codeship } from "./Codeship" +import { Codemagic } from "./Codemagic" import { Concourse } from "./Concourse" import { DockerCloud } from "./DockerCloud" import { Drone } from "./Drone" @@ -54,6 +55,7 @@ const providers = [ BitbucketPipelines, Cirrus, Bamboo, + Codemagic, ] // Mainly used for Dangerfile linting @@ -82,6 +84,7 @@ const realProviders = [ AppCenter, Cirrus, Bamboo, + Codemagic, ] export { providers, realProviders }