From b6869bfd24090f1cb8ca3183603180c6965734cd Mon Sep 17 00:00:00 2001 From: Pierre Vanduynslager Date: Wed, 9 Jan 2019 15:48:37 -0500 Subject: [PATCH] feat: add support for GitHub Actions --- README.md | 47 ++++----- index.js | 1 + services/github.js | 44 +++++++++ test/index.test.js | 9 +- test/services/github.test.js | 180 +++++++++++++++++++++++++++++++++++ 5 files changed, 257 insertions(+), 24 deletions(-) create mode 100644 services/github.js create mode 100644 test/services/github.test.js diff --git a/README.md b/README.md index 07f05b2..606356b 100644 --- a/README.md +++ b/README.md @@ -62,29 +62,30 @@ if (isCI) { ## Supported CI -| CI Service (`name`) | `service` | `isCi` | `branch` | `commit` | `tag` | `build` | `buildUrl` | `job` | `jobUrl` | `isPr` | `pr` | `prBranch` | `slug` | `root` | -|----------------------------------------------------------------------------------------------------------------------------------------|:-----------:|:------------------:|:---------------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:---------------------:|:---------------------:|:---------------------:|:------------------:|:------------------:| -| [AppVeyor]( https://www.appveyor.com/docs/environment-variables) | `appveyor` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [Bamboo](https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html) | `bamboo` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | -| [Bitbucket](https://confluence.atlassian.com/bitbucket/environment-variables-794502608.html) | `bitbucket` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | -| [Bitrise](https://devcenter.bitrise.io/builds/available-environment-variables/#exposed-by-bitriseio) | `bitrise` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | -| [Buddy](https://buddy.works/knowledge/deployments/how-use-environment-variables#default-environment-variables) | `buddy` | :white_check_mark: | [:warning:](#buddy) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | -| [Buildkite](https://buildkite.com/docs/builds/environment-variables) | `buildkite` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [CircleCI](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) | `circleci` | :white_check_mark: | [:warning:](#circleci) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | -| [Cirrus CI](https://cirrus-ci.org/guide/writing-tasks/#environment-variables) | `cirrus` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html) | `codebuild` | :white_check_mark: | [:warning:](#aws-codebuild) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | -| [Codefresh](https://codefresh.io/docs/docs/codefresh-yaml/variables#system-provided-variables) | `codefresh` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [Codeship](https://documentation.codeship.com/basic/builds-and-configuration/set-environment-variables/#default-environment-variables) | `codeship` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | -| [Drone](https://readme.drone.io/reference/environ/) | `drone` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | -| [Gitlab CI/CD](https://docs.gitlab.com/ce/ci/variables/README.html) | `gitlab` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | -| [Jenkins](https://wiki.jenkins.io/display/JENKINS/Building+a+software+project) | `jenkins` | :white_check_mark: | [:warning:](#jenkins) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | [:warning:](#jenkins) | [:warning:](#jenkins) | [:warning:](#jenkins) | :white_check_mark: | :white_check_mark: | -| [Sail CI](https://sail.ci/docs/environment-variables) | `sail` | :white_check_mark: | [:warning:](#sail) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | -| [Semaphore](https://semaphoreci.com/docs/available-environment-variables.html) | `semaphore` | :white_check_mark: | [:warning:](#semaphore) | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [Shippable](http://docs.shippable.com/ci/env-vars/#stdEnv) | `shippable` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [TeamCity](https://confluence.jetbrains.com/display/TCD10/Predefined+Build+Parameters) | `teamcity` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | -| [Travis CI](https://docs.travis-ci.com/user/environment-variables#default-environment-variables) | `travis` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | -| [Visual Studio Team Services](https://docs.microsoft.com/en-us/vsts/pipelines/build/variables) | `vsts` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | -| [Wercker](http://devcenter.wercker.com/docs/environment-variables/available-env-vars#hs_cos_wrapper_name) | `wercker` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| CI Service (`name`) | `service` | `isCi` | `branch` | `commit` | `tag` | `build` | `buildUrl` | `job` | `jobUrl` | `isPr` | `pr` | `prBranch` | `slug` | `root` | +|-----------------------------------------------------------------------------------------------------------------------------------------|:-----------:|:------------------:|:---------------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:|:---------------------:|:---------------------:|:---------------------:|:------------------:|:------------------:| +| [AppVeyor]( https://www.appveyor.com/docs/environment-variables) | `appveyor` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Bamboo](https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html) | `bamboo` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | +| [Bitbucket](https://confluence.atlassian.com/bitbucket/environment-variables-794502608.html) | `bitbucket` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| [Bitrise](https://devcenter.bitrise.io/builds/available-environment-variables/#exposed-by-bitriseio) | `bitrise` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| [Buddy](https://buddy.works/knowledge/deployments/how-use-environment-variables#default-environment-variables) | `buddy` | :white_check_mark: | [:warning:](#buddy) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | +| [Buildkite](https://buildkite.com/docs/builds/environment-variables) | `buildkite` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [CircleCI](https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables) | `circleci` | :white_check_mark: | [:warning:](#circleci) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| [Cirrus CI](https://cirrus-ci.org/guide/writing-tasks/#environment-variables) | `cirrus` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html) | `codebuild` | :white_check_mark: | [:warning:](#aws-codebuild) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | +| [Codefresh](https://codefresh.io/docs/docs/codefresh-yaml/variables#system-provided-variables) | `codefresh` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Codeship](https://documentation.codeship.com/basic/builds-and-configuration/set-environment-variables/#default-environment-variables) | `codeship` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :x: | +| [Drone](https://readme.drone.io/reference/environ/) | `drone` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | +| [GitHub Actions](https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#environment-variables) | `github` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [GitLab CI/CD](https://docs.gitlab.com/ce/ci/variables/README.html) | `gitlab` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| [Jenkins](https://wiki.jenkins.io/display/JENKINS/Building+a+software+project) | `jenkins` | :white_check_mark: | [:warning:](#jenkins) | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | [:warning:](#jenkins) | [:warning:](#jenkins) | [:warning:](#jenkins) | :white_check_mark: | :white_check_mark: | +| [Sail CI](https://sail.ci/docs/environment-variables) | `sail` | :white_check_mark: | [:warning:](#sail) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | +| [Semaphore](https://semaphoreci.com/docs/available-environment-variables.html) | `semaphore` | :white_check_mark: | [:warning:](#semaphore) | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Shippable](http://docs.shippable.com/ci/env-vars/#stdEnv) | `shippable` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [TeamCity](https://confluence.jetbrains.com/display/TCD10/Predefined+Build+Parameters) | `teamcity` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | +| [Travis CI](https://docs.travis-ci.com/user/environment-variables#default-environment-variables) | `travis` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | +| [Visual Studio Team Services](https://docs.microsoft.com/en-us/vsts/pipelines/build/variables) | `vsts` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | +| [Wercker](http://devcenter.wercker.com/docs/environment-variables/available-env-vars#hs_cos_wrapper_name) | `wercker` | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :white_check_mark: | :white_check_mark: | :warning: See [Caveats](#caveats) diff --git a/index.js b/index.js index 1d7a810..f725cee 100644 --- a/index.js +++ b/index.js @@ -16,6 +16,7 @@ const services = { codefresh: require('./services/codefresh'), codeship: require('./services/codeship'), drone: require('./services/drone'), + github: require('./services/github'), gitlab: require('./services/gitlab'), jenkins: require('./services/jenkins'), sail: require('./services/sail'), diff --git a/services/github.js b/services/github.js new file mode 100644 index 0000000..2ee5734 --- /dev/null +++ b/services/github.js @@ -0,0 +1,44 @@ +// https://developer.github.com/actions/creating-github-actions/accessing-the-runtime-environment/#environment-variables + +const parseBranch = branch => (/refs\/heads\/(.*)/i.exec(branch) || [])[1]; + +const getPrEvent = ({env}) => { + try { + const event = env.GITHUB_EVENT_PATH ? require(env.GITHUB_EVENT_PATH) : undefined; + + if (event && event.pull_request) { + return { + branch: event.pull_request.base ? parseBranch(event.pull_request.base.ref) : undefined, + pr: event.pull_request.number, + }; + } + } catch (error) { + // Noop + } + + return {pr: undefined, branch: undefined}; +}; + +module.exports = { + detect({env}) { + return Boolean(env.GITHUB_ACTION); + }, + configuration({env, cwd}) { + const isPr = env.GITHUB_EVENT_NAME === 'pull_request'; + const branch = parseBranch(env.GITHUB_REF); + + return Object.assign( + { + name: 'GitHub Actions', + service: 'github', + commit: env.GITHUB_SHA, + isPr, + branch, + prBranch: isPr ? branch : undefined, + slug: env.GITHUB_REPOSITORY, + root: env.GITHUB_WORKSPACE, + }, + isPr ? getPrEvent({env, cwd}) : undefined + ); + }, +}; diff --git a/test/index.test.js b/test/index.test.js index 5201811..e550d51 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -88,7 +88,14 @@ test('Drone', t => { t.is(service, 'drone'); }); -test('Gitlab', t => { +test('GitHub', t => { + const {isCi, service} = m({env: {GITHUB_ACTION: 'action-name'}}); + + t.is(isCi, true); + t.is(service, 'github'); +}); + +test('GitLab', t => { const {isCi, service} = m({env: {GITLAB_CI: 'true'}}); t.is(isCi, true); diff --git a/test/services/github.test.js b/test/services/github.test.js new file mode 100644 index 0000000..3f59a19 --- /dev/null +++ b/test/services/github.test.js @@ -0,0 +1,180 @@ +import fs from 'fs'; +import test from 'ava'; +import tempy from 'tempy'; +import github from '../../services/github'; + +/* eslint camelcase: ["error", {properties: "never"}] */ + +const env = { + GITHUB_ACTION: 'action-name', + GITHUB_SHA: '1234', + GITHUB_REF: '/refs/heads/master', + GITHUB_REPOSITORY: 'owner/repo', + GITHUB_WORKSPACE: '/workspace', +}; + +test('Push', t => { + t.deepEqual(github.configuration({env}), { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: 'master', + isPr: false, + prBranch: undefined, + root: '/workspace', + slug: 'owner/repo', + }); +}); + +test('PR - with event.json file', t => { + const eventFile = tempy.file({extension: 'json'}); + const event = {pull_request: {number: '10', base: {ref: '/refs/heads/master'}}}; + fs.writeFileSync(eventFile, JSON.stringify(event)); + + t.deepEqual( + github.configuration({ + env: Object.assign({}, env, { + GITHUB_EVENT_NAME: 'pull_request', + GITHUB_REF: '/refs/heads/pr-branch', + GITHUB_EVENT_PATH: eventFile, + }), + }), + { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: 'master', + isPr: true, + prBranch: 'pr-branch', + pr: '10', + root: '/workspace', + slug: 'owner/repo', + } + ); +}); + +test('PR - with missing event.json file', t => { + t.deepEqual( + github.configuration({ + env: Object.assign({}, env, { + GITHUB_EVENT_NAME: 'pull_request', + GITHUB_REF: '/refs/heads/pr-branch', + GITHUB_EVENT_PATH: '/tmp/null', + }), + }), + { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: undefined, + isPr: true, + prBranch: 'pr-branch', + pr: undefined, + root: '/workspace', + slug: 'owner/repo', + } + ); +}); + +test('PR - with missing event.json file path', t => { + t.deepEqual( + github.configuration({ + env: Object.assign({}, env, { + GITHUB_EVENT_NAME: 'pull_request', + GITHUB_REF: '/refs/heads/pr-branch', + }), + }), + { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: undefined, + isPr: true, + prBranch: 'pr-branch', + pr: undefined, + root: '/workspace', + slug: 'owner/repo', + } + ); +}); + +test('PR - with missing "pull_request" in event.json file', t => { + const eventFile = tempy.file({extension: 'json'}); + const event = {}; + fs.writeFileSync(eventFile, JSON.stringify(event)); + + t.deepEqual( + github.configuration({ + env: Object.assign({}, env, { + GITHUB_EVENT_NAME: 'pull_request', + GITHUB_REF: '/refs/heads/pr-branch', + GITHUB_EVENT_PATH: eventFile, + }), + }), + { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: undefined, + isPr: true, + prBranch: 'pr-branch', + pr: undefined, + root: '/workspace', + slug: 'owner/repo', + } + ); +}); + +test('PR - with missing "pull_request.base" in event.json file', t => { + const eventFile = tempy.file({extension: 'json'}); + const event = {pull_request: {number: '10'}}; + fs.writeFileSync(eventFile, JSON.stringify(event)); + + t.deepEqual( + github.configuration({ + env: Object.assign({}, env, { + GITHUB_EVENT_NAME: 'pull_request', + GITHUB_REF: '/refs/heads/pr-branch', + GITHUB_EVENT_PATH: eventFile, + }), + }), + { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: undefined, + isPr: true, + prBranch: 'pr-branch', + pr: '10', + root: '/workspace', + slug: 'owner/repo', + } + ); +}); + +test('PR - with erronous branch names', t => { + const eventFile = tempy.file({extension: 'json'}); + const event = {pull_request: {number: '10', base: {ref: '/refs/tags/master'}}}; + fs.writeFileSync(eventFile, JSON.stringify(event)); + + t.deepEqual( + github.configuration({ + env: Object.assign({}, env, { + GITHUB_EVENT_NAME: 'pull_request', + GITHUB_REF: '/refs/tags/pr-branch', + GITHUB_EVENT_PATH: eventFile, + }), + }), + { + name: 'GitHub Actions', + service: 'github', + commit: '1234', + branch: undefined, + isPr: true, + prBranch: undefined, + pr: '10', + root: '/workspace', + slug: 'owner/repo', + } + ); +});