Commit 1fef4e4a authored by John Skarbek's avatar John Skarbek Committed by Robert Speicher

Adds ability to find green masters and trigger builds

* Adds a rake task with the ability to trigger deploys based on being
able to find a green build
  * Uses existing logic for determining if a project should be skipped
  * Contains a defaulted dry run option
* End goal would be to trigger a build w/i `omnibus-gitlab`
parent dfc4b153
......@@ -5,6 +5,7 @@ stages:
- deploy
- automation
- chatops
- green-master-build-trigger
cache: &global-cache
key: "ruby-25"
......@@ -175,3 +176,23 @@ chatops:
cache:
<<: *global-cache
policy: pull
# nightly green master builds -------------------------------------------------
ee-green-master-build-trigger:
<<: *with-bundle
stage: green-master-build-trigger
script:
- bundle exec green_master:ee[true]
only:
variables:
- $EE_GREEN_MASTER_BUILD_TRIGGER == "true"
ce-green-master-build-trigger:
<<: *with-bundle
stage: green-master-build-trigger
script:
- bundle exec green_master:ce[true]
only:
variables:
- $CE_GREEN_MASTER_BUILD_TRIGGER == "true"
......@@ -19,6 +19,46 @@ unless ENV['CI'] || Rake.application.top_level_tasks.include?('default') || Rele
abort('Please use the master branch and make sure you are up to date.'.colorize(:red))
end
namespace :green_master do
desc "Trigger a green master build for EE"
task :ee, [:trigger_build] do |_t, args|
commit = ReleaseTools::Commits.new(ReleaseTools::Project::GitlabEe).latest_successful
raise 'No recent master builds have green pipelines' if commit.nil?
$stdout.puts "Found EE Green Master at #{commit.id}"
if args.trigger_build
ReleaseTools::Pipeline.new(
ReleaseTools::Project::GitlabEe,
commit.id
).trigger
end
end
desc "Trigger a green master build for CE"
task :ce, [:trigger_build] do |_t, args|
commit = ReleaseTools::Commits.new(ReleaseTools::Project::GitlabCe).latest_successful
raise 'No recent master builds have green pipelines' if commit.nil?
$stdout.puts "Found CE Green Master at #{commit.id}"
if args.trigger_build
ReleaseTools::Pipeline.new(
ReleaseTools::Project::GitlabCe,
commit.id
).trigger
end
end
desc "Trigger a green master build for both CE and EE"
task :all, [:trigger_build] do |_t, args|
Rake::Task['green_master:ee'].invoke(args.trigger_build)
Rake::Task['green_master:ce'].invoke(args.trigger_build)
end
end
desc "Tag a new GitLab release"
task :tag, [:version] do |_t, args|
version = get_version(args)
......
......@@ -58,6 +58,57 @@ bundle exec rake "cherry_pick[11.4.0-rc6]"
bundle exec rake "cherry_pick[11.3.6]"
```
## `green_master:<ee|ce|all>[trigger_build]`
This task will show us the selected `sha` associated with the latest `master`
branch that had a successful pipeline run. When `trigger_build` is `true`, it
will send the signal to `omnibus-gitlab` to start that build.
When running `green_master:all`, it will run both the CE and EE builds
synchronously. Keep this in mind if on a time constraint.
### Examples
```sh
# Informational gathering only
% bundle exec rake green_master:ee
Found EE Green Master at 50b5b74315b8e8c440305d48cc8d26c3ef843bf4
% bundle exec rake green_master:ce
Found CE Green Master at 5ff775fdef99eeec1f25bea7baf5480fa402f714
% bundle exec rake green_master:all[true]
Found EE Green Master at 50b5b74315b8e8c440305d48cc8d26c3ef843bf4
Found CE Green Master at 5ff775fdef99eeec1f25bea7baf5480fa402f714
# Actually triggers a build (Example output)
% bundle exec rake green_master:ee[true]
Found EE Green Master at 50b5b74315b8e8c440305d48cc8d26c3ef843bf4
trigger build: 50b5b74315b8e8c440305d48cc8d26c3ef843bf4 for Project::GitlabCe
Pipeline triggered: https://dev.gitlab.org/gitlab/omnibus-gitlab/pipelines/205527
...........................................
Pipeline succeeded in 43 minutes.
% bundle exec rake green_master:ce[true]
Found CE Green Master at 5ff775fdef99eeec1f25bea7baf5480fa402f714
trigger build: 5ff775fdef99eeec1f25bea7baf5480fa402f714 for Project::GitlabCe
Pipeline triggered: https://dev.gitlab.org/gitlab/omnibus-gitlab/pipelines/205528
...........................................
Pipeline succeeded in 43 minutes.
% bundle exec rake green_master:all[true]
Found EE Green Master at 50b5b74315b8e8c440305d48cc8d26c3ef843bf4
trigger build: 50b5b74315b8e8c440305d48cc8d26c3ef843bf4 for Project::GitlabCe
Pipeline triggered: https://dev.gitlab.org/gitlab/omnibus-gitlab/pipelines/205527
...........................................
Pipeline succeeded in 43 minutes.
Found CE Green Master at 5ff775fdef99eeec1f25bea7baf5480fa402f714
trigger build: 5ff775fdef99eeec1f25bea7baf5480fa402f714 for Project::GitlabCe
Pipeline triggered: https://dev.gitlab.org/gitlab/omnibus-gitlab/pipelines/205528
...........................................
Pipeline succeeded in 43 minutes.
```
## `monthly_issue[version]`
This task will either return the URL of a monthly release issue if one already
......
......@@ -46,6 +46,7 @@ require 'release_tools/cherry_pick/console_notifier'
require 'release_tools/cherry_pick/result'
require 'release_tools/cherry_pick/service'
require 'release_tools/commit_author'
require 'release_tools/commits'
require 'release_tools/gitlab_client'
require 'release_tools/gitlab_dev_client'
require 'release_tools/helm/chart_file'
......@@ -60,6 +61,7 @@ require 'release_tools/monthly_issue'
require 'release_tools/omnibus_gitlab_version'
require 'release_tools/packages/publish_service'
require 'release_tools/patch_issue'
require 'release_tools/pipeline'
require 'release_tools/pick_into_label'
require 'release_tools/preparation_merge_request'
require 'release_tools/project/base_project'
......
# frozen_string_literal: true
module ReleaseTools
class Commits
attr_reader :project
def initialize(project)
@project = project
end
def latest_successful
filter_for_green_builds
end
private
def commit_list
@commit_list ||= ReleaseTools::GitlabClient.commits(
project.path,
{
per_page: 1,
ref_name: 'master'
})
end
def filter_for_green_builds
commit_list.auto_paginate do |commit|
commit = ReleaseTools::GitlabClient.commit(@project, ref: commit.id)
return commit if commit.status == "success"
end
end
end
end
......@@ -8,6 +8,7 @@ module ReleaseTools
class << self
extend Forwardable
def_delegator :client, :commits
def_delegator :client, :pipelines
def_delegator :client, :pipeline_jobs
def_delegator :client, :job_play
......@@ -42,6 +43,14 @@ module ReleaseTools
client.merge_request_approvals(project_path(project), iid)
end
def self.pipeline(project = Project::GitlabCe, id)
client.pipeline(project_path(project), id)
end
def self.run_trigger(project = Project::GitlabCe, token, ref, options)
client.run_trigger(project_path(project), token, ref, options)
end
def self.commit_merge_requests(project = Project::GitlabCe, sha:)
client.commit_merge_requests(project_path(project), sha)
end
......
module ReleaseTools
class Pipeline
attr_reader :project, :sha
def initialize(project, sha)
@project = project
@sha = sha
@token = ENV.fetch('OMNIBUS_BUILD_TRIGGER_TOKEN') { |name| raise "Missing environment variable `#{name}`" }
end
def trigger
$stdout.puts "trigger build: #{sha} for #{project.path}"
trigger = ReleaseTools::GitlabDevClient.run_trigger(
ReleaseTools::Project::OmnibusGitlab,
@token,
"master",
{
GITLAB_VERSION: sha,
NIGHTLY: "true",
ee: project == ReleaseTools::Project::GitlabEe
})
$stdout.puts "Pipeline triggered: #{trigger.web_url}"
wait(trigger.id)
end
def status(id)
ReleaseTools::GitlabDevClient.pipeline(ReleaseTools::Project::OmnibusGitlab, id).status
end
def wait(id)
interval = 60 # seconds
max_duration = 3600 * 3 # 3 hours
start = Time.now.to_i
loop do
raise "Pipeline timeout after waiting for #{max_duration} seconds." if ReleaseTools::TimeUtil.timeout?(start, max_duration)
case status(id)
when 'created', 'pending', 'running'
print '.'
sleep interval
when 'success'
$stdout.puts "Pipeline succeeded in #{max_duration} seconds."
break
else
raise 'Pipeline did not suceed.'
end
$stdout.flush
end
end
end
end
......@@ -4,6 +4,10 @@ module ReleaseTools
module TimeUtil
extend self
def timeout?(start, max_duration)
Time.now.to_i > (start + max_duration)
end
def time_ago(time, precision: 1)
return unless time
......
......@@ -6,6 +6,17 @@ describe ReleaseTools::TimeUtil do
ex.run
end
end
describe '.timeout?' do
let(:start_time) { Time.now.to_i - 600 }
it 'returns false as it has not been exceeded' do
expect(described_class.timeout?(start_time, 900)).to eq(false)
end
it 'returns true as it has been exceeded' do
expect(described_class.timeout?(start_time, 9)).to eq(true)
end
end
describe '.time_ago' do
context 'when delta is less than a minute' do
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment