[rubygems/rubygems] Introduce the Gem::CIDetector
This is based on the list in Gem::UpdateSuggestion and Bundler::Fetcher; these have similar purposes (determining whether/what CI we're executing in), and can benefit from being combined and updated (they're both slightly out of date). Noteable changes: * We'll consider ourselves to be on a CI in more cases - if CI_NAME or TASKCLUSTER_ROOT_URL are set specifically, since those represent two cases that were either overlooked or are no longer covered by the existing implementation. (Or possibly TaskCluster still does provide RUN_ID, but failed to document it) * We will notice/track a few additional services in ci_strings (cirrus, dsari, taskcluster), stop tracking 'snap' (they went under in 2017), and update buildbox to buildkite (they've been called that for 8 years, and the BUILDBOX envs have been deprecated for 3). * We'll also sort/uniq/downcase the values (all of which only matter because of the special case of CI_NAME). https://github.com/rubygems/rubygems/commit/60652b942f
This commit is contained in:
parent
82072254a0
commit
b1b78c4f9f
@ -1290,6 +1290,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
|
||||
MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze
|
||||
|
||||
autoload :ConfigFile, File.expand_path("rubygems/config_file", __dir__)
|
||||
autoload :CIDetector, File.expand_path("rubygems/ci_detector", __dir__)
|
||||
autoload :Dependency, File.expand_path("rubygems/dependency", __dir__)
|
||||
autoload :DependencyList, File.expand_path("rubygems/dependency_list", __dir__)
|
||||
autoload :Installer, File.expand_path("rubygems/installer", __dir__)
|
||||
|
75
lib/rubygems/ci_detector.rb
Normal file
75
lib/rubygems/ci_detector.rb
Normal file
@ -0,0 +1,75 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Gem
|
||||
module CIDetector
|
||||
# NOTE: Any changes made here will need to be made to both lib/rubygems/ci_detector.rb and
|
||||
# bundler/lib/bundler/ci_detector.rb (which are enforced duplicates).
|
||||
# TODO: Drop that duplication once bundler drops support for RubyGems 3.4
|
||||
#
|
||||
# ## Recognized CI providers, their signifiers, and the relevant docs ##
|
||||
#
|
||||
# Travis CI - CI, TRAVIS https://docs.travis-ci.com/user/environment-variables/#default-environment-variables
|
||||
# Cirrus CI - CI, CIRRUS_CI https://cirrus-ci.org/guide/writing-tasks/#environment-variables
|
||||
# Circle CI - CI, CIRCLECI https://circleci.com/docs/variables/#built-in-environment-variables
|
||||
# Gitlab CI - CI, GITLAB_CI https://docs.gitlab.com/ee/ci/variables/
|
||||
# AppVeyor - CI, APPVEYOR https://www.appveyor.com/docs/environment-variables/
|
||||
# CodeShip - CI_NAME https://docs.cloudbees.com/docs/cloudbees-codeship/latest/pro-builds-and-configuration/environment-variables#_default_environment_variables
|
||||
# dsari - CI, DSARI https://github.com/rfinnie/dsari#running
|
||||
# Jenkins - BUILD_NUMBER https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
|
||||
# TeamCity - TEAMCITY_VERSION https://www.jetbrains.com/help/teamcity/predefined-build-parameters.html#Predefined+Server+Build+Parameters
|
||||
# Appflow - CI_BUILD_ID https://ionic.io/docs/appflow/automation/environments#predefined-environments
|
||||
# TaskCluster - TASKCLUSTER_ROOT_URL https://docs.taskcluster.net/docs/manual/design/env-vars
|
||||
# Semaphore - CI, SEMAPHORE https://docs.semaphoreci.com/ci-cd-environment/environment-variables/
|
||||
# BuildKite - CI, BUILDKITE https://buildkite.com/docs/pipelines/environment-variables
|
||||
# GoCD - GO_SERVER_URL https://docs.gocd.org/current/faq/dev_use_current_revision_in_build.html
|
||||
# GH Actions - CI, GITHUB_ACTIONS https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
|
||||
#
|
||||
# ### Some "standard" ENVs that multiple providers may set ###
|
||||
#
|
||||
# * CI - this is set by _most_ (but not all) CI providers now; it's approaching a standard.
|
||||
# * CI_NAME - Not as frequently used, but some providers set this to specify their own name
|
||||
|
||||
# Any of these being set is a reasonably reliable indicator that we are
|
||||
# executing in a CI environment.
|
||||
ENV_INDICATORS = [
|
||||
"CI",
|
||||
"CI_NAME",
|
||||
"CONTINUOUS_INTEGRATION",
|
||||
"BUILD_NUMBER",
|
||||
"CI_APP_ID",
|
||||
"CI_BUILD_ID",
|
||||
"CI_BUILD_NUMBER",
|
||||
"RUN_ID",
|
||||
"TASKCLUSTER_ROOT_URL",
|
||||
].freeze
|
||||
|
||||
# For each CI, this env suffices to indicate that we're on _that_ CI's
|
||||
# containers. (A few of them only supply a CI_NAME variable, which is also
|
||||
# nice). And if they set "CI" but we can't tell which one they are, we also
|
||||
# want to know that - a bare "ci" without another token tells us as much.
|
||||
ENV_DESCRIPTORS = {
|
||||
"TRAVIS" => "travis",
|
||||
"CIRCLECI" => "circle",
|
||||
"CIRRUS_CI" => "cirrus",
|
||||
"DSARI" => "dsari",
|
||||
"SEMAPHORE" => "semaphore",
|
||||
"JENKINS_URL" => "jenkins",
|
||||
"BUILDKITE" => "buildkite",
|
||||
"GO_SERVER_URL" => "go",
|
||||
"GITLAB_CI" => "gitlab",
|
||||
"GITHUB_ACTIONS" => "github",
|
||||
"TASKCLUSTER_ROOT_URL" => "taskcluster",
|
||||
"CI" => "ci",
|
||||
}.freeze
|
||||
|
||||
def self.ci?
|
||||
ENV_INDICATORS.any? {|var| ENV.include?(var) }
|
||||
end
|
||||
|
||||
def self.ci_strings
|
||||
matching_names = ENV_DESCRIPTORS.select {|env, _| ENV[env] }.values
|
||||
matching_names << ENV["CI_NAME"].downcase if ENV["CI_NAME"]
|
||||
matching_names.reject(&:empty?).sort.uniq
|
||||
end
|
||||
end
|
||||
end
|
44
test/rubygems/test_gem_ci_detector.rb
Normal file
44
test/rubygems/test_gem_ci_detector.rb
Normal file
@ -0,0 +1,44 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "helper"
|
||||
require "rubygems"
|
||||
|
||||
class TestCiDetector < Test::Unit::TestCase
|
||||
def test_ci?
|
||||
with_env("FOO" => "bar") { assert_equal(false, Gem::CIDetector.ci?) }
|
||||
with_env("CI" => "true") { assert_equal(true, Gem::CIDetector.ci?) }
|
||||
with_env("CONTINUOUS_INTEGRATION" => "1") { assert_equal(true, Gem::CIDetector.ci?) }
|
||||
with_env("RUN_ID" => "0", "TASKCLUSTER_ROOT_URL" => "2") do
|
||||
assert_equal(true, Gem::CIDetector.ci?)
|
||||
end
|
||||
end
|
||||
|
||||
def test_ci_strings
|
||||
with_env("FOO" => "bar") { assert_empty(Gem::CIDetector.ci_strings) }
|
||||
with_env("TRAVIS" => "true") { assert_equal(["travis"], Gem::CIDetector.ci_strings) }
|
||||
with_env("CI" => "true", "CIRCLECI" => "true", "GITHUB_ACTIONS" => "true") do
|
||||
assert_equal(["ci", "circle", "github"], Gem::CIDetector.ci_strings)
|
||||
end
|
||||
with_env("CI" => "true", "CI_NAME" => "MYCI") do
|
||||
assert_equal(["ci", "myci"], Gem::CIDetector.ci_strings)
|
||||
end
|
||||
with_env("GITHUB_ACTIONS" => "true", "CI_NAME" => "github") do
|
||||
assert_equal(["github"], Gem::CIDetector.ci_strings)
|
||||
end
|
||||
with_env("TASKCLUSTER_ROOT_URL" => "https://foo.bar", "DSARI" => "1", "CI_NAME" => "") do
|
||||
assert_equal(["dsari", "taskcluster"], Gem::CIDetector.ci_strings)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_env(overrides, &block)
|
||||
@orig_env = ENV.to_h
|
||||
ENV.replace(overrides)
|
||||
begin
|
||||
block.call
|
||||
ensure
|
||||
ENV.replace(@orig_env)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user