diff --git a/README.md b/README.md index b9d7b0f..0d89708 100644 --- a/README.md +++ b/README.md @@ -32,46 +32,49 @@ if (ci.isCI) { Officially supported CI servers: -| Name | Constant | isPR | -| ------------------------------------------------------------------------------- | -------------------- | ---- | -| [AWS CodeBuild](https://aws.amazon.com/codebuild/) | `ci.CODEBUILD` | 🚫 | -| [AppVeyor](http://www.appveyor.com) | `ci.APPVEYOR` | ✅ | -| [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) | `ci.AZURE_PIPELINES` | ✅ | -| [Appcircle](https://appcircle.io/) | `ci.APPCIRCLE` | 🚫 | -| [Bamboo](https://www.atlassian.com/software/bamboo) by Atlassian | `ci.BAMBOO` | 🚫 | -| [Bitbucket Pipelines](https://bitbucket.org/product/features/pipelines) | `ci.BITBUCKET` | ✅ | -| [Bitrise](https://www.bitrise.io/) | `ci.BITRISE` | ✅ | -| [Buddy](https://buddy.works/) | `ci.BUDDY` | ✅ | -| [Buildkite](https://buildkite.com) | `ci.BUILDKITE` | ✅ | -| [CircleCI](http://circleci.com) | `ci.CIRCLE` | ✅ | -| [Cirrus CI](https://cirrus-ci.org) | `ci.CIRRUS` | ✅ | -| [Codefresh](https://codefresh.io/) | `ci.CODEFRESH` | ✅ | -| [Codeship](https://codeship.com) | `ci.CODESHIP` | 🚫 | -| [Drone](https://drone.io) | `ci.DRONE` | ✅ | -| [dsari](https://github.com/rfinnie/dsari) | `ci.DSARI` | 🚫 | -| [Expo Application Services](https://expo.dev/eas) | `ci.EAS` | 🚫 | -| [GitHub Actions](https://github.com/features/actions/) | `ci.GITHUB_ACTIONS` | ✅ | -| [GitLab CI](https://about.gitlab.com/gitlab-ci/) | `ci.GITLAB` | ✅ | -| [GoCD](https://www.go.cd/) | `ci.GOCD` | 🚫 | -| [Hudson](http://hudson-ci.org) | `ci.HUDSON` | 🚫 | -| [Jenkins CI](https://jenkins-ci.org) | `ci.JENKINS` | ✅ | -| [LayerCI](https://layerci.com/) | `ci.LAYERCI` | ✅ | -| [Magnum CI](https://magnum-ci.com) | `ci.MAGNUM` | 🚫 | -| [Netlify CI](https://www.netlify.com/) | `ci.NETLIFY` | ✅ | -| [Nevercode](http://nevercode.io/) | `ci.NEVERCODE` | ✅ | -| [Render](https://render.com/) | `ci.RENDER` | ✅ | -| [Sail CI](https://sail.ci/) | `ci.SAIL` | ✅ | -| [Screwdriver](https://screwdriver.cd/) | `ci.SCREWDRIVER` | ✅ | -| [Semaphore](https://semaphoreci.com) | `ci.SEMAPHORE` | ✅ | -| [Shippable](https://www.shippable.com/) | `ci.SHIPPABLE` | ✅ | -| [Solano CI](https://www.solanolabs.com/) | `ci.SOLANO` | ✅ | -| [Strider CD](https://strider-cd.github.io/) | `ci.STRIDER` | 🚫 | -| [TaskCluster](http://docs.taskcluster.net) | `ci.TASKCLUSTER` | 🚫 | -| [TeamCity](https://www.jetbrains.com/teamcity/) by JetBrains | `ci.TEAMCITY` | 🚫 | -| [Travis CI](http://travis-ci.org) | `ci.TRAVIS` | ✅ | -| [Vercel](https://vercel.com/) | `ci.VERCEL` | 🚫 | -| [Visual Studio App Center](https://appcenter.ms/) | `ci.APPCENTER` | 🚫 | -| [Woodpecker](https://woodpecker-ci.org/) | `ci.WOODPECKER` | ✅ | +| Name | Constant | isPR | +| ------------------------------------------------------------------------------- | -------------------- | ---- | +| [AWS CodeBuild](https://aws.amazon.com/codebuild/) | `ci.CODEBUILD` | 🚫 | +| [AppVeyor](http://www.appveyor.com) | `ci.APPVEYOR` | ✅ | +| [Azure Pipelines](https://azure.microsoft.com/en-us/services/devops/pipelines/) | `ci.AZURE_PIPELINES` | ✅ | +| [Appcircle](https://appcircle.io/) | `ci.APPCIRCLE` | 🚫 | +| [Bamboo](https://www.atlassian.com/software/bamboo) by Atlassian | `ci.BAMBOO` | 🚫 | +| [Bitbucket Pipelines](https://bitbucket.org/product/features/pipelines) | `ci.BITBUCKET` | ✅ | +| [Bitrise](https://www.bitrise.io/) | `ci.BITRISE` | ✅ | +| [Buddy](https://buddy.works/) | `ci.BUDDY` | ✅ | +| [Buildkite](https://buildkite.com) | `ci.BUILDKITE` | ✅ | +| [CircleCI](http://circleci.com) | `ci.CIRCLE` | ✅ | +| [Cirrus CI](https://cirrus-ci.org) | `ci.CIRRUS` | ✅ | +| [Codefresh](https://codefresh.io/) | `ci.CODEFRESH` | ✅ | +| [Codeship](https://codeship.com) | `ci.CODESHIP` | 🚫 | +| [Drone](https://drone.io) | `ci.DRONE` | ✅ | +| [dsari](https://github.com/rfinnie/dsari) | `ci.DSARI` | 🚫 | +| [Expo Application Services](https://expo.dev/eas) | `ci.EAS` | 🚫 | +| [Gerrit CI](https://www.gerritcodereview.com) | `ci.GERRIT` | 🚫 | +| [GitHub Actions](https://github.com/features/actions/) | `ci.GITHUB_ACTIONS` | ✅ | +| [GitLab CI](https://about.gitlab.com/gitlab-ci/) | `ci.GITLAB` | ✅ | +| [GoCD](https://www.go.cd/) | `ci.GOCD` | 🚫 | +| [Google Cloud Build](https://cloud.google.com/build) | `ci.GOOGLE_CLOUD_BUILD` | 🚫 | +| [Heroku](https://www.heroku.com) | `ci.HEROKU` | 🚫 | +| [Hudson](http://hudson-ci.org) | `ci.HUDSON` | 🚫 | +| [Jenkins CI](https://jenkins-ci.org) | `ci.JENKINS` | ✅ | +| [LayerCI](https://layerci.com/) | `ci.LAYERCI` | ✅ | +| [Magnum CI](https://magnum-ci.com) | `ci.MAGNUM` | 🚫 | +| [Netlify CI](https://www.netlify.com/) | `ci.NETLIFY` | ✅ | +| [Nevercode](http://nevercode.io/) | `ci.NEVERCODE` | ✅ | +| [Render](https://render.com/) | `ci.RENDER` | ✅ | +| [Sail CI](https://sail.ci/) | `ci.SAIL` | ✅ | +| [Screwdriver](https://screwdriver.cd/) | `ci.SCREWDRIVER` | ✅ | +| [Semaphore](https://semaphoreci.com) | `ci.SEMAPHORE` | ✅ | +| [Shippable](https://www.shippable.com/) | `ci.SHIPPABLE` | ✅ | +| [Solano CI](https://www.solanolabs.com/) | `ci.SOLANO` | ✅ | +| [Strider CD](https://strider-cd.github.io/) | `ci.STRIDER` | 🚫 | +| [TaskCluster](http://docs.taskcluster.net) | `ci.TASKCLUSTER` | 🚫 | +| [TeamCity](https://www.jetbrains.com/teamcity/) by JetBrains | `ci.TEAMCITY` | 🚫 | +| [Travis CI](http://travis-ci.org) | `ci.TRAVIS` | ✅ | +| [Vercel](https://vercel.com/) | `ci.VERCEL` | 🚫 | +| [Visual Studio App Center](https://appcenter.ms/) | `ci.APPCENTER` | 🚫 | +| [Woodpecker](https://woodpecker-ci.org/) | `ci.WOODPECKER` | ✅ | ## API diff --git a/index.d.ts b/index.d.ts index 62a4d2d..8fc88cc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -41,9 +41,12 @@ export const CODESHIP: boolean; export const DRONE: boolean; export const DSARI: boolean; export const EAS: boolean; +export const GERRIT: boolean; export const GITHUB_ACTIONS: boolean; export const GITLAB: boolean; export const GOCD: boolean; +export const GOOGLE_CLOUD_BUILD: boolean; +export const HEROKU boolean; export const HUDSON: boolean; export const JENKINS: boolean; export const LAYERCI: boolean; diff --git a/index.js b/index.js index 29bc205..e91c518 100644 --- a/index.js +++ b/index.js @@ -54,19 +54,35 @@ vendors.forEach(function (vendor) { }) exports.isCI = !!( - env.CI || // Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari - env.CONTINUOUS_INTEGRATION || // Travis CI, Cirrus CI + env.BUILD_ID || // Jenkins, Cloudbees env.BUILD_NUMBER || // Jenkins, TeamCity + env.CI || // Travis CI, CircleCI, Cirrus CI, Gitlab CI, Appveyor, CodeShip, dsari env.CI_APP_ID || // Appflow env.CI_BUILD_ID || // Appflow env.CI_BUILD_NUMBER || // Appflow + env.CI_NAME || // Codeship and others + env.CONTINUOUS_INTEGRATION || // Travis CI, Cirrus CI env.RUN_ID || // TaskCluster, dsari exports.name || false ) function checkEnv (obj) { + // "env": "CIRRUS" if (typeof obj === 'string') return !!env[obj] + + // "env": { "env": "NODE", "includes": "/app/.heroku/node/bin/node" } + if ('env' in obj) { + // Currently there are no other types, uncomment when there are + // if ('includes' in obj) { + return env[obj.env] && env[obj.env].includes(obj.includes) + // } + } + if ('any' in obj) { + return obj.any.some(function (k) { + return !!env[k] + }) + } return Object.keys(obj).every(function (k) { return env[k] === obj[k] }) diff --git a/package.json b/package.json index 6321246..2197368 100644 --- a/package.json +++ b/package.json @@ -30,5 +30,8 @@ "clear-module": "^4.1.2", "standard": "^17.0.0", "tape": "^5.6.0" + }, + "engines": { + "node": ">=8" } } diff --git a/test.js b/test.js index f5a5af1..31b236b 100644 --- a/test.js +++ b/test.js @@ -58,9 +58,9 @@ test('Unknown CI', function (t) { test('Anonymous CI', function (t) { const ANONYMOUS_ENV_VARS = [ - 'CI', 'CONTINUOUS_INTEGRATION', 'BUILD_NUMBER', - 'CI_APP_ID', 'CI_BUILD_ID', 'CI_BUILD_NUMBER', - 'RUN_ID' + 'CI', 'CONTINUOUS_INTEGRATION', 'BUILD_ID', + 'BUILD_NUMBER', 'CI_APP_ID', 'CI_BUILD_ID', + 'CI_BUILD_NUMBER', 'RUN_ID', 'CI_NAME' ] for (const envVar in ANONYMOUS_ENV_VARS) { @@ -606,7 +606,7 @@ test('Netlify CI - Not PR', function (t) { t.end() }) -test('Vercel', function (t) { +test('Vercel - NOW_BUILDER', function (t) { process.env.NOW_BUILDER = '1' clearModule('./') @@ -623,6 +623,23 @@ test('Vercel', function (t) { t.end() }) +test('Vercel - VERCEL_URL', function (t) { + process.env.VERCEL_URL = '1' + + clearModule('./') + const ci = require('./') + + t.equal(ci.isCI, true) + t.equal(ci.isPR, null) + t.equal(ci.name, 'Vercel') + t.equal(ci.VERCEL, true) + assertVendorConstants('VERCEL', ci, t) + + delete process.env.VERCEL_URL + + t.end() +}) + test('Nevercode - PR', function (t) { process.env.NEVERCODE = 'true' process.env.NEVERCODE_PULL_REQUEST = 'true' @@ -860,6 +877,22 @@ test('Xcode Server - Not PR', function (t) { t.end() }) +test('Heroku', function (t) { + const realNode = process.env.NODE + process.env.NODE = '/extra/content/app/.heroku/node/bin/node --extra --content' + + clearModule('./') + const ci = require('./') + + t.equal(ci.isCI, true) + t.equal(ci.name, 'Heroku') + t.equal(ci.HEROKU, true) + assertVendorConstants('HEROKU', ci, t) + + process.env.NODE = realNode + t.end() +}) + function assertVendorConstants (expect, ci, t) { ci._vendors.forEach(function (constant) { let bool = constant === expect diff --git a/vendors.json b/vendors.json index 2f25d02..29d90c2 100644 --- a/vendors.json +++ b/vendors.json @@ -1,21 +1,26 @@ [ + { + "name": "Appcircle", + "constant": "APPCIRCLE", + "env": "AC_APPCIRCLE" + }, { "name": "AppVeyor", "constant": "APPVEYOR", "env": "APPVEYOR", "pr": "APPVEYOR_PULL_REQUEST_NUMBER" }, + { + "name": "AWS CodeBuild", + "constant": "CODEBUILD", + "env": "CODEBUILD_BUILD_ARN" + }, { "name": "Azure Pipelines", "constant": "AZURE_PIPELINES", "env": "SYSTEM_TEAMFOUNDATIONCOLLECTIONURI", "pr": "SYSTEM_PULLREQUEST_PULLREQUESTID" }, - { - "name": "Appcircle", - "constant": "APPCIRCLE", - "env": "AC_APPCIRCLE" - }, { "name": "Bamboo", "constant": "BAMBOO", @@ -57,23 +62,18 @@ "env": "CIRRUS_CI", "pr": "CIRRUS_PR" }, - { - "name": "Codemagic", - "constant": "CODEMAGIC", - "env": "CM_BUILD_ID", - "pr": "CM_PULL_REQUEST" - }, - { - "name": "AWS CodeBuild", - "constant": "CODEBUILD", - "env": "CODEBUILD_BUILD_ARN" - }, { "name": "Codefresh", "constant": "CODEFRESH", "env": "CF_BUILD_ID", "pr": { "any": ["CF_PULL_REQUEST_NUMBER", "CF_PULL_REQUEST_ID"] } }, + { + "name": "Codemagic", + "constant": "CODEMAGIC", + "env": "CM_BUILD_ID", + "pr": "CM_PULL_REQUEST" + }, { "name": "Codeship", "constant": "CODESHIP", @@ -85,12 +85,6 @@ "env": "DRONE", "pr": { "DRONE_BUILD_EVENT": "pull_request" } }, - { - "name": "Woodpecker", - "constant": "WOODPECKER", - "env": { "CI": "woodpecker" }, - "pr": { "CI_BUILD_EVENT": "pull_request" } - }, { "name": "dsari", "constant": "DSARI", @@ -118,12 +112,27 @@ "constant": "GOCD", "env": "GO_PIPELINE_LABEL" }, + { + "name": "Google Cloud Build", + "constant": "GOOGLE_CLOUD_BUILD", + "env": "BUILDER_OUTPUT" + }, { "name": "LayerCI", "constant": "LAYERCI", "env": "LAYERCI", "pr": "LAYERCI_PULL_REQUEST" }, + { + "name": "Gerrit", + "constant": "GERRIT", + "env": "GERRIT_PROJECT" + }, + { + "name": "Heroku", + "constant": "HEROKU", + "env": { "env": "NODE", "includes": "/app/.heroku/node/bin/node" } + }, { "name": "Hudson", "constant": "HUDSON", @@ -164,18 +173,18 @@ "env": "SAILCI", "pr": "SAIL_PULL_REQUEST_NUMBER" }, - { - "name": "Semaphore", - "constant": "SEMAPHORE", - "env": "SEMAPHORE", - "pr": "PULL_REQUEST_NUMBER" - }, { "name": "Screwdriver", "constant": "SCREWDRIVER", "env": "SCREWDRIVER", "pr": { "env": "SD_PULL_REQUEST", "ne": "false" } }, + { + "name": "Semaphore", + "constant": "SEMAPHORE", + "env": "SEMAPHORE", + "pr": "PULL_REQUEST_NUMBER" + }, { "name": "Shippable", "constant": "SHIPPABLE", @@ -212,13 +221,19 @@ { "name": "Vercel", "constant": "VERCEL", - "env": "NOW_BUILDER" + "env": { "any": ["NOW_BUILDER", "VERCEL_URL"] } }, { "name": "Visual Studio App Center", "constant": "APPCENTER", "env": "APPCENTER_BUILD_ID" }, + { + "name": "Woodpecker", + "constant": "WOODPECKER", + "env": { "CI": "woodpecker" }, + "pr": { "CI_BUILD_EVENT": "pull_request" } + }, { "name": "Xcode Cloud", "constant": "XCODE_CLOUD",