0f751f6f17
Optionally compiling assets when needed for qa jobs proved unworkable so instead we fall back on compiling them for all qa jobs.
234 lines
5.4 KiB
Ruby
Executable file
234 lines
5.4 KiB
Ruby
Executable file
#!/usr/bin/env ruby
|
|
# frozen_string_literal: true
|
|
|
|
require 'gitlab'
|
|
|
|
#
|
|
# Configure credentials to be used with gitlab gem
|
|
#
|
|
Gitlab.configure do |config|
|
|
config.endpoint = 'https://gitlab.com/api/v4'
|
|
end
|
|
|
|
module Trigger
|
|
def self.ee?
|
|
ENV['CI_PROJECT_NAME'] == 'gitlab-ee' || File.exist?('CHANGELOG-EE.md')
|
|
end
|
|
|
|
class Base
|
|
def invoke!(post_comment: false)
|
|
pipeline = Gitlab.run_trigger(
|
|
downstream_project_path,
|
|
trigger_token,
|
|
ref,
|
|
variables)
|
|
|
|
puts "Triggered downstream pipeline: #{pipeline.web_url}\n"
|
|
puts "Waiting for downstream pipeline status"
|
|
|
|
Trigger::CommitComment.post!(pipeline, access_token) if post_comment
|
|
Trigger::Pipeline.new(downstream_project_path, pipeline.id, access_token)
|
|
end
|
|
|
|
private
|
|
|
|
# Must be overridden
|
|
def downstream_project_path
|
|
raise NotImplementedError
|
|
end
|
|
|
|
# Must be overridden
|
|
def ref
|
|
raise NotImplementedError
|
|
end
|
|
|
|
# Must be overridden
|
|
def trigger_token
|
|
raise NotImplementedError
|
|
end
|
|
|
|
# Must be overridden
|
|
def access_token
|
|
raise NotImplementedError
|
|
end
|
|
|
|
# Can be overridden
|
|
def extra_variables
|
|
{}
|
|
end
|
|
|
|
# Can be overridden
|
|
def version_param_value(version_file)
|
|
File.read(version_file).strip
|
|
end
|
|
|
|
def variables
|
|
base_variables.merge(extra_variables).merge(version_file_variables)
|
|
end
|
|
|
|
def base_variables
|
|
{
|
|
'GITLAB_REF_SLUG' => ENV['CI_COMMIT_REF_SLUG'],
|
|
'TRIGGERED_USER' => ENV['TRIGGERED_USER'] || ENV['GITLAB_USER_NAME'],
|
|
'TRIGGER_SOURCE' => ENV['CI_JOB_URL'],
|
|
'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'],
|
|
'TOP_UPSTREAM_SOURCE_JOB' => ENV['CI_JOB_URL'],
|
|
'TOP_UPSTREAM_SOURCE_SHA' => ENV['CI_COMMIT_SHA']
|
|
}
|
|
end
|
|
|
|
# Read version files from all components
|
|
def version_file_variables
|
|
Dir.glob("*_VERSION").each_with_object({}) do |version_file, params|
|
|
params[version_file] = version_param_value(version_file)
|
|
end
|
|
end
|
|
end
|
|
|
|
class Omnibus < Base
|
|
private
|
|
|
|
def downstream_project_path
|
|
'gitlab-org/omnibus-gitlab'
|
|
end
|
|
|
|
def ref
|
|
ENV['OMNIBUS_BRANCH'] || 'master'
|
|
end
|
|
|
|
def trigger_token
|
|
ENV['BUILD_TRIGGER_TOKEN']
|
|
end
|
|
|
|
def access_token
|
|
ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
|
|
end
|
|
|
|
def extra_variables
|
|
{
|
|
'GITLAB_VERSION' => ENV['CI_COMMIT_SHA'],
|
|
'ALTERNATIVE_SOURCES' => 'true',
|
|
'ee' => Trigger.ee? ? 'true' : 'false',
|
|
'QA_BRANCH' => ENV['QA_BRANCH'] || 'master'
|
|
}
|
|
end
|
|
end
|
|
|
|
class CNG < Base
|
|
private
|
|
|
|
def downstream_project_path
|
|
ENV['CNG_PROJECT_PATH'] || 'gitlab-org/build/CNG-mirror'
|
|
end
|
|
|
|
def ref
|
|
ENV['CNG_BRANCH'] || 'master'
|
|
end
|
|
|
|
def trigger_token
|
|
ENV['BUILD_TRIGGER_TOKEN']
|
|
end
|
|
|
|
def access_token
|
|
ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
|
|
end
|
|
|
|
def extra_variables
|
|
edition = Trigger.ee? ? 'EE' : 'CE'
|
|
|
|
{
|
|
"GITLAB_#{edition}_VERSION" => ENV['CI_COMMIT_REF_NAME'],
|
|
"#{edition}_PIPELINE" => 'true'
|
|
}
|
|
end
|
|
|
|
def version_param_value(_version_file)
|
|
raw_version = super
|
|
|
|
# if the version matches semver format, treat it as a tag and prepend `v`
|
|
if raw_version =~ Regexp.compile(/^\d+\.\d+\.\d+(-rc\d+)?(-ee)?$/)
|
|
"v#{raw_version}"
|
|
else
|
|
raw_version
|
|
end
|
|
end
|
|
end
|
|
|
|
class CommitComment
|
|
def self.post!(downstream_pipeline, access_token)
|
|
Gitlab.private_token = access_token
|
|
|
|
Gitlab.create_commit_comment(
|
|
ENV['CI_PROJECT_PATH'],
|
|
ENV['CI_COMMIT_SHA'],
|
|
"The [`#{ENV['CI_JOB_NAME']}`](#{ENV['CI_JOB_URL']}) job from pipeline #{ENV['CI_PIPELINE_URL']} triggered #{downstream_pipeline.web_url} downstream.")
|
|
|
|
rescue Gitlab::Error::Error => error
|
|
puts "Ignoring the following error: #{error}"
|
|
end
|
|
end
|
|
|
|
class Pipeline
|
|
INTERVAL = 60 # seconds
|
|
MAX_DURATION = 3600 * 3 # 3 hours
|
|
|
|
attr_reader :project, :id, :api_token
|
|
|
|
def initialize(project, id, api_token)
|
|
@project = project
|
|
@id = id
|
|
@api_token = api_token
|
|
@start = Time.now.to_i
|
|
|
|
# gitlab-bot's token "GitLab multi-project pipeline polling"
|
|
Gitlab.private_token = api_token
|
|
end
|
|
|
|
def wait!
|
|
loop do
|
|
raise "Pipeline timed out after waiting for #{duration} minutes!" if timeout?
|
|
|
|
case status
|
|
when :created, :pending, :running
|
|
print "."
|
|
sleep INTERVAL
|
|
when :success
|
|
puts "Pipeline succeeded in #{duration} minutes!"
|
|
break
|
|
else
|
|
raise "Pipeline did not succeed!"
|
|
end
|
|
|
|
STDOUT.flush
|
|
end
|
|
end
|
|
|
|
def timeout?
|
|
Time.now.to_i > (@start + MAX_DURATION)
|
|
end
|
|
|
|
def duration
|
|
(Time.now.to_i - @start) / 60
|
|
end
|
|
|
|
def status
|
|
Gitlab.pipeline(project, id).status.to_sym
|
|
rescue Gitlab::Error::Error => error
|
|
puts "Ignoring the following error: #{error}"
|
|
# Ignore GitLab API hiccups. If GitLab is really down, we'll hit the job
|
|
# timeout anyway.
|
|
:running
|
|
end
|
|
end
|
|
end
|
|
|
|
case ARGV[0]
|
|
when 'omnibus'
|
|
Trigger::Omnibus.new.invoke!(post_comment: true).wait!
|
|
when 'cng'
|
|
Trigger::CNG.new.invoke!.wait!
|
|
else
|
|
puts "Please provide a valid option:
|
|
omnibus - Triggers a pipeline that builds the omnibus-gitlab package
|
|
cng - Triggers a pipeline that builds images used by the GitLab helm chart"
|
|
end
|