From c661789d49c9933e51ad1aabc8c410ebd10f6b32 Mon Sep 17 00:00:00 2001 From: Gar Date: Mon, 14 Nov 2022 13:13:37 -0800 Subject: [PATCH] deps: move from @npmcli/ci-detect to ci-info See https://github.com/watson/ci-info/pull/95 for more context on achieving parity between these two modules. This changes npm to use `ci-info` instead of `@npmcli/ci-detect`. Everything that npm currently flags as a CI environment should still be doing so, so there is no breaking change there. There is going to be a subtle difference in the `ci-name` config, which nothing in npm currently looks at anyways, as well as the ci name that shows up in the default `user-agent` string. Some providers will be slightly different (i.e. circle-ci vs circleci and cirrus vs cirrus-ci) --- DEPENDENCIES.md | 8 +- lib/utils/config/definitions.js | 9 +- lib/utils/update-notifier.js | 4 +- node_modules/.gitignore | 2 +- node_modules/@npmcli/ci-detect/LICENSE | 15 -- node_modules/@npmcli/ci-detect/lib/index.js | 52 ---- node_modules/@npmcli/ci-detect/package.json | 44 ---- node_modules/ci-info/LICENSE | 21 ++ node_modules/ci-info/index.d.ts | 70 ++++++ node_modules/ci-info/index.js | 89 +++++++ node_modules/ci-info/package.json | 37 +++ node_modules/ci-info/vendors.json | 248 ++++++++++++++++++++ package-lock.json | 23 +- package.json | 4 +- scripts/dependency-graph.js | 1 - scripts/npm-cli-repos.txt | 1 - tap-snapshots/test/lib/docs.js.test.cjs | 2 +- test/lib/utils/config/definitions.js | 4 +- test/lib/utils/update-notifier.js | 8 +- workspaces/libnpmexec/lib/index.js | 4 +- workspaces/libnpmexec/lib/run-script.js | 8 +- workspaces/libnpmexec/package.json | 2 +- workspaces/libnpmexec/test/index.js | 14 +- workspaces/libnpmexec/test/run-script.js | 12 +- 24 files changed, 515 insertions(+), 167 deletions(-) delete mode 100644 node_modules/@npmcli/ci-detect/LICENSE delete mode 100644 node_modules/@npmcli/ci-detect/lib/index.js delete mode 100644 node_modules/@npmcli/ci-detect/package.json create mode 100644 node_modules/ci-info/LICENSE create mode 100644 node_modules/ci-info/index.d.ts create mode 100644 node_modules/ci-info/index.js create mode 100644 node_modules/ci-info/package.json create mode 100644 node_modules/ci-info/vendors.json diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 1448db1b9fde5..2187275722624 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -32,7 +32,6 @@ graph LR; libnpmexec-->minify-registry-metadata; libnpmexec-->npm-package-arg; libnpmexec-->npmcli-arborist["@npmcli/arborist"]; - libnpmexec-->npmcli-ci-detect["@npmcli/ci-detect"]; libnpmexec-->npmcli-eslint-config["@npmcli/eslint-config"]; libnpmexec-->npmcli-run-script["@npmcli/run-script"]; libnpmexec-->npmcli-template-oss["@npmcli/template-oss"]; @@ -113,7 +112,6 @@ graph LR; npm-->npm-registry-fetch; npm-->npm-user-validate; npm-->npmcli-arborist["@npmcli/arborist"]; - npm-->npmcli-ci-detect["@npmcli/ci-detect"]; npm-->npmcli-config["@npmcli/config"]; npm-->npmcli-docs["@npmcli/docs"]; npm-->npmcli-eslint-config["@npmcli/eslint-config"]; @@ -353,11 +351,11 @@ graph LR; libnpmdiff-->tar; libnpmexec-->bin-links; libnpmexec-->chalk; + libnpmexec-->ci-info; libnpmexec-->minify-registry-metadata; libnpmexec-->mkdirp; libnpmexec-->npm-package-arg; libnpmexec-->npmcli-arborist["@npmcli/arborist"]; - libnpmexec-->npmcli-ci-detect["@npmcli/ci-detect"]; libnpmexec-->npmcli-eslint-config["@npmcli/eslint-config"]; libnpmexec-->npmcli-run-script["@npmcli/run-script"]; libnpmexec-->npmcli-template-oss["@npmcli/template-oss"]; @@ -476,6 +474,7 @@ graph LR; npm-->archy; npm-->cacache; npm-->chalk; + npm-->ci-info; npm-->cli-columns; npm-->cli-table3; npm-->columnify; @@ -519,7 +518,6 @@ graph LR; npm-->npm-registry-fetch; npm-->npm-user-validate; npm-->npmcli-arborist["@npmcli/arborist"]; - npm-->npmcli-ci-detect["@npmcli/ci-detect"]; npm-->npmcli-config["@npmcli/config"]; npm-->npmcli-docs["@npmcli/docs"]; npm-->npmcli-eslint-config["@npmcli/eslint-config"]; @@ -783,4 +781,4 @@ packages higher up the chain. - @npmcli/git, make-fetch-happen, @npmcli/config, init-package-json - @npmcli/installed-package-contents, @npmcli/map-workspaces, cacache, npm-pick-manifest, @npmcli/run-script, read-package-json, promzard - @npmcli/docs, @npmcli/fs, npm-bundled, read-package-json-fast, unique-filename, npm-install-checks, npm-package-arg, npm-packlist, normalize-package-data, @npmcli/package-json, bin-links, nopt, npmlog, parse-conflict-json, read - - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, treeverse, minify-registry-metadata, ini, @npmcli/disparity-colors, @npmcli/ci-detect, mute-stream, npm-audit-report, npm-user-validate + - @npmcli/eslint-config, @npmcli/template-oss, ignore-walk, semver, npm-normalize-package-bin, @npmcli/name-from-folder, json-parse-even-better-errors, fs-minipass, ssri, unique-slug, @npmcli/promise-spawn, hosted-git-info, proc-log, validate-npm-package-name, @npmcli/node-gyp, minipass-fetch, @npmcli/query, cmd-shim, read-cmd-shim, write-file-atomic, abbrev, are-we-there-yet, gauge, treeverse, minify-registry-metadata, ini, @npmcli/disparity-colors, mute-stream, npm-audit-report, npm-user-validate diff --git a/lib/utils/config/definitions.js b/lib/utils/config/definitions.js index 245b9170d56fc..f511b1badfe85 100644 --- a/lib/utils/config/definitions.js +++ b/lib/utils/config/definitions.js @@ -4,8 +4,7 @@ module.exports = definitions const Definition = require('./definition.js') const { version: npmVersion } = require('../../../package.json') -const ciDetect = require('@npmcli/ci-detect') -const ciName = ciDetect() +const ciInfo = require('ci-info') const querystring = require('querystring') const { isWindows } = require('../is-windows.js') const { join } = require('path') @@ -433,7 +432,7 @@ define('cert', { }) define('ci-name', { - default: ciName || null, + default: ciInfo.name ? ciInfo.name.toLowerCase().split(' ').join('-') : null, defaultDescription: ` The name of the current CI system, or \`null\` when not on a known CI platform. @@ -442,7 +441,7 @@ define('ci-name', { description: ` The name of a continuous integration system. If not set explicitly, npm will detect the current CI environment using the - [\`@npmcli/ci-detect\`](http://npm.im/@npmcli/ci-detect) module. + [\`ci-info\`](http://npm.im/@npmcli/ci-info) module. `, flatten, }) @@ -1597,7 +1596,7 @@ define('production', { }) define('progress', { - default: !ciName, + default: !ciInfo.isCI, defaultDescription: ` \`true\` unless running in a known CI system `, diff --git a/lib/utils/update-notifier.js b/lib/utils/update-notifier.js index 75e944407ffbd..a7eaaca64747f 100644 --- a/lib/utils/update-notifier.js +++ b/lib/utils/update-notifier.js @@ -3,7 +3,7 @@ // Check daily for betas, and weekly otherwise. const pacote = require('pacote') -const ciDetect = require('@npmcli/ci-detect') +const ciInfo = require('ci-info') const semver = require('semver') const chalk = require('chalk') const { promisify } = require('util') @@ -39,7 +39,7 @@ const updateNotifier = async (npm, spec = 'latest') => { // never check for updates in CI, when updating npm already, or opted out if (!npm.config.get('update-notifier') || isGlobalNpmUpdate(npm) || - ciDetect()) { + ciInfo.isCI) { return SKIP } diff --git a/node_modules/.gitignore b/node_modules/.gitignore index b94e4bd99842c..de73c53a67719 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -15,7 +15,6 @@ !/@npmcli/ /@npmcli/* !/@npmcli/arborist -!/@npmcli/ci-detect !/@npmcli/config !/@npmcli/disparity-colors !/@npmcli/fs @@ -55,6 +54,7 @@ !/cacache !/chalk !/chownr +!/ci-info !/cidr-regex !/clean-stack !/cli-columns diff --git a/node_modules/@npmcli/ci-detect/LICENSE b/node_modules/@npmcli/ci-detect/LICENSE deleted file mode 100644 index 19cec97b18468..0000000000000 --- a/node_modules/@npmcli/ci-detect/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) npm, Inc. - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR -IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/node_modules/@npmcli/ci-detect/lib/index.js b/node_modules/@npmcli/ci-detect/lib/index.js deleted file mode 100644 index 34755c7f166c3..0000000000000 --- a/node_modules/@npmcli/ci-detect/lib/index.js +++ /dev/null @@ -1,52 +0,0 @@ -module.exports = () => - process.env.GERRIT_PROJECT ? 'gerrit' - : process.env.SYSTEM_TEAMFOUNDATIONCOLLECTIONURI ? 'azure-pipelines' - : process.env.BITRISE_IO ? 'bitrise' - : process.env.BUDDY_WORKSPACE_ID ? 'buddy' - : process.env.BUILDKITE ? 'buildkite' - : process.env.CIRRUS_CI ? 'cirrus' - : process.env.GITLAB_CI ? 'gitlab' - : process.env.APPVEYOR ? 'appveyor' - : process.env.CIRCLECI ? 'circle-ci' - : process.env.SEMAPHORE ? 'semaphore' - : process.env.DRONE ? 'drone' - : process.env.DSARI ? 'dsari' - : process.env.GITHUB_ACTION ? 'github-actions' - : process.env.TDDIUM ? 'tddium' - : process.env.SCREWDRIVER ? 'screwdriver' - : process.env.STRIDER ? 'strider' - : process.env.TASKCLUSTER_ROOT_URL ? 'taskcluster' - : process.env.JENKINS_URL ? 'jenkins' - : process.env['bamboo.buildKey'] ? 'bamboo' - : process.env.GO_PIPELINE_NAME ? 'gocd' - : process.env.HUDSON_URL ? 'hudson' - : process.env.WERCKER ? 'wercker' - : process.env.NETLIFY ? 'netlify' - : process.env.NOW_GITHUB_DEPLOYMENT ? 'now-github' - : process.env.GITLAB_DEPLOYMENT ? 'now-gitlab' - : process.env.BITBUCKET_DEPLOYMENT ? 'now-bitbucket' - : process.env.BITBUCKET_BUILD_NUMBER ? 'bitbucket-pipelines' - : process.env.NOW_BUILDER ? 'now' - : process.env.VERCEL_GITHUB_DEPLOYMENT ? 'vercel-github' - : process.env.VERCEL_GITLAB_DEPLOYMENT ? 'vercel-gitlab' - : process.env.VERCEL_BITBUCKET_DEPLOYMENT ? 'vercel-bitbucket' - : process.env.VERCEL_URL ? 'vercel' - : process.env.MAGNUM ? 'magnum' - : process.env.NEVERCODE ? 'nevercode' - : process.env.RENDER ? 'render' - : process.env.SAIL_CI ? 'sail' - : process.env.SHIPPABLE ? 'shippable' - : process.env.TEAMCITY_VERSION ? 'teamcity' - // codeship and a few others - : process.env.CI_NAME ? process.env.CI_NAME - // heroku doesn't set envs other than node in a heroku-specific location - : /\/\.heroku\/node\/bin\/node$/.test(process.env.NODE || '') ? 'heroku' - // test travis after the others, since several CI systems mimic it - : process.env.TRAVIS ? 'travis-ci' - // aws CodeBuild/CodePipeline - : process.env.CODEBUILD_SRC_DIR ? 'aws-codebuild' - : process.env.CI === 'woodpecker' ? 'woodpecker' - : process.env.CI === 'true' || process.env.CI === '1' ? 'custom' - // Google Cloud Build - it sets almost nothing - : process.env.BUILDER_OUTPUT ? 'builder' - : false diff --git a/node_modules/@npmcli/ci-detect/package.json b/node_modules/@npmcli/ci-detect/package.json deleted file mode 100644 index 4be4b65fe671f..0000000000000 --- a/node_modules/@npmcli/ci-detect/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@npmcli/ci-detect", - "version": "3.0.1", - "description": "Detect what kind of CI environment the program is in", - "author": "GitHub Inc.", - "license": "ISC", - "main": "./lib", - "scripts": { - "test": "tap", - "lint": "eslint \"**/*.js\"", - "postlint": "template-oss-check", - "lintfix": "npm run lint -- --fix", - "snap": "tap", - "posttest": "npm run lint", - "template-oss-apply": "template-oss-apply --force" - }, - "tap": { - "check-coverage": true, - "nyc-arg": [ - "--exclude", - "tap-snapshots/**" - ] - }, - "devDependencies": { - "@npmcli/eslint-config": "^4.0.0", - "@npmcli/template-oss": "4.6.2", - "tap": "^16.0.1" - }, - "files": [ - "bin/", - "lib/" - ], - "repository": { - "type": "git", - "url": "https://github.com/npm/ci-detect.git" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "templateOSS": { - "//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.", - "version": "4.6.2" - } -} diff --git a/node_modules/ci-info/LICENSE b/node_modules/ci-info/LICENSE new file mode 100644 index 0000000000000..2cc7405a823c4 --- /dev/null +++ b/node_modules/ci-info/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016-2021 Thomas Watson Steen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/ci-info/index.d.ts b/node_modules/ci-info/index.d.ts new file mode 100644 index 0000000000000..0572d36ea9eca --- /dev/null +++ b/node_modules/ci-info/index.d.ts @@ -0,0 +1,70 @@ +/** + * Returns a boolean. Will be `true` if the code is running on a CI server, + * otherwise `false`. + * + * Some CI servers not listed here might still trigger the `ci.isCI` + * boolean to be set to `true` if they use certain vendor neutral environment + * variables. In those cases `ci.name` will be `null` and no vendor specific + * boolean will be set to `true`. + */ +export const isCI: boolean; +/** + * Returns a boolean if PR detection is supported for the current CI server. + * Will be `true` if a PR is being tested, otherwise `false`. If PR detection is + * not supported for the current CI server, the value will be `null`. + */ +export const isPR: boolean | null; +/** + * Returns a string containing name of the CI server the code is running on. If + * CI server is not detected, it returns `null`. + * + * Don't depend on the value of this string not to change for a specific vendor. + * If you find your self writing `ci.name === 'Travis CI'`, you most likely want + * to use `ci.TRAVIS` instead. + */ +export const name: string | null; + +export const APPVEYOR: boolean; +export const AZURE_PIPELINES: boolean; +export const APPCIRCLE: boolean; +export const BAMBOO: boolean; +export const BITBUCKET: boolean; +export const BITRISE: boolean; +export const BUDDY: boolean; +export const BUILDKITE: boolean; +export const CIRCLE: boolean; +export const CIRRUS: boolean; +export const CODEBUILD: boolean; +export const CODEMAGIC: boolean; +export const CODEFRESH: boolean; +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; +export const MAGNUM: boolean; +export const NETLIFY: boolean; +export const NEVERCODE: boolean; +export const RENDER: boolean; +export const SAIL: boolean; +export const SEMAPHORE: boolean; +export const SCREWDRIVER: boolean; +export const SHIPPABLE: boolean; +export const SOLANO: boolean; +export const STRIDER: boolean; +export const TASKCLUSTER: boolean; +export const TEAMCITY: boolean; +export const TRAVIS: boolean; +export const VERCEL: boolean; +export const APPCENTER: boolean; +export const XCODE_CLOUD: boolean; +export const XCODE_SERVER: boolean; +export const WOODPECKER: boolean; diff --git a/node_modules/ci-info/index.js b/node_modules/ci-info/index.js new file mode 100644 index 0000000000000..e91c518557897 --- /dev/null +++ b/node_modules/ci-info/index.js @@ -0,0 +1,89 @@ +'use strict' + +const vendors = require('./vendors.json') + +const env = process.env + +// Used for testing only +Object.defineProperty(exports, '_vendors', { + value: vendors.map(function (v) { + return v.constant + }) +}) + +exports.name = null +exports.isPR = null + +vendors.forEach(function (vendor) { + const envs = Array.isArray(vendor.env) ? vendor.env : [vendor.env] + const isCI = envs.every(function (obj) { + return checkEnv(obj) + }) + + exports[vendor.constant] = isCI + + if (!isCI) { + return + } + + exports.name = vendor.name + + switch (typeof vendor.pr) { + case 'string': + // "pr": "CIRRUS_PR" + exports.isPR = !!env[vendor.pr] + break + case 'object': + if ('env' in vendor.pr) { + // "pr": { "env": "BUILDKITE_PULL_REQUEST", "ne": "false" } + exports.isPR = vendor.pr.env in env && env[vendor.pr.env] !== vendor.pr.ne + } else if ('any' in vendor.pr) { + // "pr": { "any": ["ghprbPullId", "CHANGE_ID"] } + exports.isPR = vendor.pr.any.some(function (key) { + return !!env[key] + }) + } else { + // "pr": { "DRONE_BUILD_EVENT": "pull_request" } + exports.isPR = checkEnv(vendor.pr) + } + break + default: + // PR detection not supported for this vendor + exports.isPR = null + } +}) + +exports.isCI = !!( + 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/node_modules/ci-info/package.json b/node_modules/ci-info/package.json new file mode 100644 index 0000000000000..59ab4df86d624 --- /dev/null +++ b/node_modules/ci-info/package.json @@ -0,0 +1,37 @@ +{ + "name": "ci-info", + "version": "3.6.1", + "description": "Get details about the current Continuous Integration environment", + "main": "index.js", + "typings": "index.d.ts", + "author": "Thomas Watson Steen (https://twitter.com/wa7son)", + "license": "MIT", + "repository": "https://github.com/watson/ci-info.git", + "bugs": "https://github.com/watson/ci-info/issues", + "homepage": "https://github.com/watson/ci-info", + "keywords": [ + "ci", + "continuous", + "integration", + "test", + "detect" + ], + "files": [ + "vendors.json", + "index.js", + "index.d.ts", + "CHANGELOG.md" + ], + "scripts": { + "lint:fix": "standard --fix", + "test": "standard && node test.js" + }, + "devDependencies": { + "clear-module": "^4.1.2", + "standard": "^17.0.0", + "tape": "^5.6.1" + }, + "engines": { + "node": ">=8" + } +} diff --git a/node_modules/ci-info/vendors.json b/node_modules/ci-info/vendors.json new file mode 100644 index 0000000000000..29d90c2979fe1 --- /dev/null +++ b/node_modules/ci-info/vendors.json @@ -0,0 +1,248 @@ +[ + { + "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": "Bamboo", + "constant": "BAMBOO", + "env": "bamboo_planKey" + }, + { + "name": "Bitbucket Pipelines", + "constant": "BITBUCKET", + "env": "BITBUCKET_COMMIT", + "pr": "BITBUCKET_PR_ID" + }, + { + "name": "Bitrise", + "constant": "BITRISE", + "env": "BITRISE_IO", + "pr": "BITRISE_PULL_REQUEST" + }, + { + "name": "Buddy", + "constant": "BUDDY", + "env": "BUDDY_WORKSPACE_ID", + "pr": "BUDDY_EXECUTION_PULL_REQUEST_ID" + }, + { + "name": "Buildkite", + "constant": "BUILDKITE", + "env": "BUILDKITE", + "pr": { "env": "BUILDKITE_PULL_REQUEST", "ne": "false" } + }, + { + "name": "CircleCI", + "constant": "CIRCLE", + "env": "CIRCLECI", + "pr": "CIRCLE_PULL_REQUEST" + }, + { + "name": "Cirrus CI", + "constant": "CIRRUS", + "env": "CIRRUS_CI", + "pr": "CIRRUS_PR" + }, + { + "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", + "env": { "CI_NAME": "codeship" } + }, + { + "name": "Drone", + "constant": "DRONE", + "env": "DRONE", + "pr": { "DRONE_BUILD_EVENT": "pull_request" } + }, + { + "name": "dsari", + "constant": "DSARI", + "env": "DSARI" + }, + { + "name": "Expo Application Services", + "constant": "EAS", + "env": "EAS_BUILD" + }, + { + "name": "GitHub Actions", + "constant": "GITHUB_ACTIONS", + "env": "GITHUB_ACTIONS", + "pr": { "GITHUB_EVENT_NAME": "pull_request" } + }, + { + "name": "GitLab CI", + "constant": "GITLAB", + "env": "GITLAB_CI", + "pr": "CI_MERGE_REQUEST_ID" + }, + { + "name": "GoCD", + "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", + "env": "HUDSON_URL" + }, + { + "name": "Jenkins", + "constant": "JENKINS", + "env": ["JENKINS_URL", "BUILD_ID"], + "pr": { "any": ["ghprbPullId", "CHANGE_ID"] } + }, + { + "name": "Magnum CI", + "constant": "MAGNUM", + "env": "MAGNUM" + }, + { + "name": "Netlify CI", + "constant": "NETLIFY", + "env": "NETLIFY", + "pr": { "env": "PULL_REQUEST", "ne": "false" } + }, + { + "name": "Nevercode", + "constant": "NEVERCODE", + "env": "NEVERCODE", + "pr": { "env": "NEVERCODE_PULL_REQUEST", "ne": "false" } + }, + { + "name": "Render", + "constant": "RENDER", + "env": "RENDER", + "pr": { "IS_PULL_REQUEST": "true" } + }, + { + "name": "Sail CI", + "constant": "SAIL", + "env": "SAILCI", + "pr": "SAIL_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", + "env": "SHIPPABLE", + "pr": { "IS_PULL_REQUEST": "true" } + }, + { + "name": "Solano CI", + "constant": "SOLANO", + "env": "TDDIUM", + "pr": "TDDIUM_PR_ID" + }, + { + "name": "Strider CD", + "constant": "STRIDER", + "env": "STRIDER" + }, + { + "name": "TaskCluster", + "constant": "TASKCLUSTER", + "env": ["TASK_ID", "RUN_ID"] + }, + { + "name": "TeamCity", + "constant": "TEAMCITY", + "env": "TEAMCITY_VERSION" + }, + { + "name": "Travis CI", + "constant": "TRAVIS", + "env": "TRAVIS", + "pr": { "env": "TRAVIS_PULL_REQUEST", "ne": "false" } + }, + { + "name": "Vercel", + "constant": "VERCEL", + "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", + "env": "CI_XCODE_PROJECT", + "pr": "CI_PULL_REQUEST_NUMBER" + }, + { + "name": "Xcode Server", + "constant": "XCODE_SERVER", + "env": "XCS" + } +] diff --git a/package-lock.json b/package-lock.json index 0c995200daf81..23976d5fdbbb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", - "@npmcli/ci-detect", "@npmcli/config", "@npmcli/map-workspaces", "@npmcli/package-json", @@ -19,6 +18,7 @@ "archy", "cacache", "chalk", + "ci-info", "cli-columns", "cli-table3", "columnify", @@ -87,7 +87,6 @@ "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^6.1.2", - "@npmcli/ci-detect": "^3.0.1", "@npmcli/config": "^6.1.0", "@npmcli/map-workspaces": "^3.0.0", "@npmcli/package-json": "^3.0.0", @@ -96,6 +95,7 @@ "archy": "~1.0.0", "cacache": "^17.0.2", "chalk": "^4.1.2", + "ci-info": "^3.6.1", "cli-columns": "^4.0.0", "cli-table3": "^0.6.3", "columnify": "^1.6.0", @@ -2079,14 +2079,6 @@ "resolved": "workspaces/arborist", "link": true }, - "node_modules/@npmcli/ci-detect": { - "version": "3.0.1", - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/@npmcli/config": { "resolved": "workspaces/config", "link": true @@ -3306,6 +3298,15 @@ "node": ">=10" } }, + "node_modules/ci-info": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.6.1.tgz", + "integrity": "sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==", + "inBundle": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cidr-regex": { "version": "3.1.1", "inBundle": true, @@ -15102,9 +15103,9 @@ "license": "ISC", "dependencies": { "@npmcli/arborist": "^6.1.2", - "@npmcli/ci-detect": "^3.0.1", "@npmcli/run-script": "^6.0.0", "chalk": "^4.1.0", + "ci-info": "^3.6.1", "npm-package-arg": "^10.0.0", "npmlog": "^7.0.1", "pacote": "^15.0.2", diff --git a/package.json b/package.json index ba34d7a2793ec..7c6f570fbe5b2 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,6 @@ "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^6.1.2", - "@npmcli/ci-detect": "^3.0.1", "@npmcli/config": "^6.1.0", "@npmcli/map-workspaces": "^3.0.0", "@npmcli/package-json": "^3.0.0", @@ -67,6 +66,7 @@ "archy": "~1.0.0", "cacache": "^17.0.2", "chalk": "^4.1.2", + "ci-info": "^3.6.1", "cli-columns": "^4.0.0", "cli-table3": "^0.6.3", "columnify": "^1.6.0", @@ -128,7 +128,6 @@ "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", - "@npmcli/ci-detect", "@npmcli/config", "@npmcli/map-workspaces", "@npmcli/package-json", @@ -137,6 +136,7 @@ "archy", "cacache", "chalk", + "ci-info", "cli-columns", "cli-table3", "columnify", diff --git a/scripts/dependency-graph.js b/scripts/dependency-graph.js index e292ce448fe74..2d8a773e03724 100644 --- a/scripts/dependency-graph.js +++ b/scripts/dependency-graph.js @@ -20,7 +20,6 @@ const aliases = { // If we see a bare package with just this name, it's NOT ours const namespaced = [ 'arborist', - 'ci-detect', 'config', 'disparity-colors', 'eslint-config', diff --git a/scripts/npm-cli-repos.txt b/scripts/npm-cli-repos.txt index 75b604fed9011..3f16b74fb23f6 100644 --- a/scripts/npm-cli-repos.txt +++ b/scripts/npm-cli-repos.txt @@ -4,7 +4,6 @@ are-we-there-yet benchmarks bin-links cacache -ci-detect cli cmd-shim config diff --git a/tap-snapshots/test/lib/docs.js.test.cjs b/tap-snapshots/test/lib/docs.js.test.cjs index 3c6a1b5025989..03913a0453ada 100644 --- a/tap-snapshots/test/lib/docs.js.test.cjs +++ b/tap-snapshots/test/lib/docs.js.test.cjs @@ -758,7 +758,7 @@ npm exec --package yo --package generator-node --call "yo node" The name of a continuous integration system. If not set explicitly, npm will detect the current CI environment using the -[\`@npmcli/ci-detect\`](http://npm.im/@npmcli/ci-detect) module. +[\`ci-info\`](http://npm.im/@npmcli/ci-info) module. #### \`cidr\` diff --git a/test/lib/utils/config/definitions.js b/test/lib/utils/config/definitions.js index da53ac3aea03f..dca584e104833 100644 --- a/test/lib/utils/config/definitions.js +++ b/test/lib/utils/config/definitions.js @@ -731,10 +731,10 @@ YYYY\r t.test('detect CI', t => { const defnNoCI = mockDefs({ - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false, name: null }, }) const defnCIFoo = mockDefs({ - '@npmcli/ci-detect': () => 'foo', + 'ci-info': { isCI: false, name: 'foo' }, }) t.equal(defnNoCI['ci-name'].default, null, 'null when not in CI') t.equal(defnCIFoo['ci-name'].default, 'foo', 'name of CI when in CI') diff --git a/test/lib/utils/update-notifier.js b/test/lib/utils/update-notifier.js index a35886c6ef20a..fa4a04bad9839 100644 --- a/test/lib/utils/update-notifier.js +++ b/test/lib/utils/update-notifier.js @@ -1,5 +1,5 @@ const t = require('tap') -let ciMock = null +let ciMock = {} const flatOptions = { global: false, cache: t.testdir() + '/_cacache' } const MANIFEST_REQUEST = [] @@ -86,7 +86,7 @@ t.afterEach(() => { const runUpdateNotifier = async ({ color = true, ...npmOptions } = {}) => { const _npm = { ...defaultNpm, ...npmOptions, logColor: color } return t.mock('../../../lib/utils/update-notifier.js', { - '@npmcli/ci-detect': () => ciMock, + 'ci-info': ciMock, pacote, fs, })(_npm) @@ -159,9 +159,9 @@ t.test('situations in which we do not notify', t => { t.test('do not update in CI', async t => { t.teardown(() => { - ciMock = null + ciMock = {} }) - ciMock = 'something' + ciMock = { isCI: true, name: 'something' } t.equal(await runUpdateNotifier(), null) t.strictSame(MANIFEST_REQUEST, [], 'no requests for manifests') }) diff --git a/workspaces/libnpmexec/lib/index.js b/workspaces/libnpmexec/lib/index.js index 575f8e6ea4a5e..2d6a7eafc2901 100644 --- a/workspaces/libnpmexec/lib/index.js +++ b/workspaces/libnpmexec/lib/index.js @@ -4,7 +4,7 @@ const { mkdir } = require('fs/promises') const { promisify } = require('util') const Arborist = require('@npmcli/arborist') -const ciDetect = require('@npmcli/ci-detect') +const ciInfo = require('ci-info') const crypto = require('crypto') const log = require('proc-log') const npa = require('npm-package-arg') @@ -242,7 +242,7 @@ const exec = async (opts) => { throw new Error('canceled') } - if (noTTY() || ciDetect()) { + if (noTTY() || ciInfo.isCI) { log.warn('exec', `The following package${ add.length === 1 ? ' was' : 's were' } not found and will be installed: ${ diff --git a/workspaces/libnpmexec/lib/run-script.js b/workspaces/libnpmexec/lib/run-script.js index 2f7b258345faa..ba60395468d62 100644 --- a/workspaces/libnpmexec/lib/run-script.js +++ b/workspaces/libnpmexec/lib/run-script.js @@ -1,5 +1,5 @@ const chalk = require('chalk') -const ciDetect = require('@npmcli/ci-detect') +const ciInfo = require('ci-info') const runScript = require('@npmcli/run-script') const readPackageJson = require('read-package-json-fast') const npmlog = require('npmlog') @@ -44,10 +44,8 @@ const run = async ({ try { if (script === scriptShell) { - const isTTY = !noTTY() - - if (isTTY) { - if (ciDetect()) { + if (!noTTY()) { + if (ciInfo.isCI) { return log.warn('exec', 'Interactive mode disabled in CI environment') } diff --git a/workspaces/libnpmexec/package.json b/workspaces/libnpmexec/package.json index 31f3531cbc538..5600ccec63ff5 100644 --- a/workspaces/libnpmexec/package.json +++ b/workspaces/libnpmexec/package.json @@ -59,9 +59,9 @@ }, "dependencies": { "@npmcli/arborist": "^6.1.2", - "@npmcli/ci-detect": "^3.0.1", "@npmcli/run-script": "^6.0.0", "chalk": "^4.1.0", + "ci-info": "^3.6.1", "npm-package-arg": "^10.0.0", "npmlog": "^7.0.1", "pacote": "^15.0.2", diff --git a/workspaces/libnpmexec/test/index.js b/workspaces/libnpmexec/test/index.js index 739a686aba8c3..269e74c18e793 100644 --- a/workspaces/libnpmexec/test/index.js +++ b/workspaces/libnpmexec/test/index.js @@ -475,7 +475,7 @@ require('fs').writeFileSync(process.argv.slice(2)[0], 'LOCAL PKG')`, fs.chmodSync(executable, 0o775) const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => true, + 'ci-info': { isCI: true }, 'proc-log': { warn (title, msg) { t.fail('should not warn about local file package install') @@ -850,7 +850,7 @@ t.test('prompt, accepts', async t => { const npxCache = resolve(testdir, 'npxCache') t.test('with clearProgress function', async t => { const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, npmlog: { clearProgress () { t.ok(true, 'should call clearProgress function') @@ -881,7 +881,7 @@ t.test('prompt, accepts', async t => { t.test('without clearProgress function', async t => { const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, read (opts, cb) { cb(null, 'y') }, @@ -916,7 +916,7 @@ t.test('prompt, refuses', async t => { const npxCache = resolve(testdir, 'npxCache') t.test('with clearProgress function', async t => { const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, npmlog: { clearProgress () { t.ok(true, 'should call clearProgress function') @@ -955,7 +955,7 @@ t.test('prompt, refuses', async t => { t.test('without clearProgress function', async t => { const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, read (opts, cb) { cb(null, 'n') }, @@ -1062,7 +1062,7 @@ t.test('no prompt if CI', async t => { const cache = resolve(testdir, 'cache') const npxCache = resolve(testdir, 'npxCache') const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => true, + 'ci-info': { isCI: true }, }) await mockexec({ @@ -1091,7 +1091,7 @@ t.test('no prompt if CI, multiple packages', async t => { const cache = resolve(testdir, 'cache') const npxCache = resolve(testdir, 'npxCache') const mockexec = t.mock('../lib/index.js', { - '@npmcli/ci-detect': () => true, + 'ci-info': { isCI: true }, 'proc-log': { warn (title, msg) { t.equal(title, 'exec', 'should warn exec title') diff --git a/workspaces/libnpmexec/test/run-script.js b/workspaces/libnpmexec/test/run-script.js index 4b1cafa0dec73..d360fc1a2025b 100644 --- a/workspaces/libnpmexec/test/run-script.js +++ b/workspaces/libnpmexec/test/run-script.js @@ -21,7 +21,7 @@ t.test('disable, enable log progress', t => { }), }) const runScript = t.mock('../lib/run-script.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') }, @@ -46,7 +46,7 @@ t.test('no package.json', t => { t.plan(1) const runScript = t.mock('../lib/run-script.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') }, @@ -60,7 +60,7 @@ t.test('colorized interactive mode msg', async t => { t.plan(2) const runScript = t.mock('../lib/run-script.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') }, @@ -83,7 +83,7 @@ t.test('no color interactive mode msg', async t => { t.plan(2) const runScript = t.mock('../lib/run-script.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') }, @@ -105,7 +105,7 @@ t.test('no tty', t => { t.plan(1) const runScript = t.mock('../lib/run-script.js', { - '@npmcli/ci-detect': () => false, + 'ci-info': { isCI: false }, '@npmcli/run-script': async () => { t.ok('should call run-script') }, @@ -119,7 +119,7 @@ t.test('ci env', t => { t.plan(2) const runScript = t.mock('../lib/run-script.js', { - '@npmcli/ci-detect': () => true, + 'ci-info': { isCI: true }, '@npmcli/run-script': async () => { throw new Error('should not call run-script') },