Commit b69f4be7 authored by Robert Speicher's avatar Robert Speicher 🌴

Add `release` and `security` task namespaces

This creates a more logical separation of existing tasks into tasks
either for security releases, or normal releases.

Old tasks will continue to work, albeit with a deprecation warning, so
that we can gradually update documentation, ChatOps, and CI schedule
configurations.

See https://gitlab.com/gitlab-org/release/framework/issues/257
parent 44ae3067
......@@ -64,7 +64,7 @@ specs:
- cp .env.example .env
- git config --global user.email "you@example.com"
- git config --global user.name "Your Name"
- bundle exec rake
- bundle exec rspec
artifacts:
paths:
- coverage/assets
......
......@@ -512,6 +512,10 @@ Style/StringMethods:
intern: to_sym
Enabled: true
Style/SymbolArray:
Exclude:
- 'lib/tasks/**/*.rake'
# This cop checks for trailing comma in array and hash literals.
Style/TrailingCommaInLiteral:
Enabled: false
......
......@@ -5,20 +5,17 @@ require_relative 'lib/release_tools/support/tasks_helper'
Dir.glob('lib/tasks/*.rake').each { |task| import(task) }
begin
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task default: :spec
rescue LoadError
# no rspec available
end
unless ENV['CI'] || Rake.application.top_level_tasks.include?('default') || ReleaseTools::LocalRepository.ready?
abort('Please use the master branch and make sure you are up to date.'.colorize(:red))
end
def deprecate_as(new_task, args)
warn "This task has been deprecated in favor of " \
"`#{new_task.colorize(:green)}` and will soon be removed."
Rake::Task[new_task].invoke(*args)
end
namespace :green_master do
desc "Trigger a green master build for EE"
task :ee, [:trigger_build] do |_t, args|
......@@ -59,46 +56,14 @@ namespace :green_master do
end
end
desc "Tag a new GitLab release"
task :tag, [:version] do |_t, args|
version = get_version(args)
if ReleaseTools::SharedStatus.security_release?
$stdout.puts "Security Release - using dev.gitlab.org only!".colorize(:red)
$stdout.puts
end
if skip?('ee')
$stdout.puts 'Skipping release for EE'.colorize(:red)
else
ee_version = version.to_ee
$stdout.puts 'EE release'.colorize(:blue)
ReleaseTools::Release::GitlabEeRelease.new(ee_version).execute
ReleaseTools::Slack::TagNotification.release(ee_version) unless dry_run?
end
if skip?('ce')
$stdout.puts 'Skipping release for CE'.colorize(:red)
else
ce_version = version.to_ce
$stdout.puts 'CE release'.colorize(:blue)
ReleaseTools::Release::GitlabCeRelease.new(ce_version).execute
ReleaseTools::Slack::TagNotification.release(ce_version) unless dry_run?
end
deprecate_as 'release:tag', args
end
desc "Tag a new GitLab security release"
task :tag_security, [:version] do |_t, args|
ENV['SECURITY'] = 'true'
Rake::Task[:tag].invoke(args[:version])
deprecate_as 'security:tag', args
end
# For legacy reasons, alias `[security_]release` to `tag[_security]`
task :release, [:version] => :tag
task :security_release, [:version] => :tag_security
desc "Sync master branch in remotes"
task :sync do
if skip?('ee')
......@@ -120,99 +85,44 @@ task :sync do
end
end
desc "Create the monthly release issue"
task :monthly_issue, [:version] do |_t, args|
version = get_version(args)
issue = ReleaseTools::MonthlyIssue.new(version: version)
create_or_show_issue(issue)
deprecate_as 'release:issue', args
end
desc "Create a patch issue"
task :patch_issue, [:version] do |_t, args|
version = get_version(args)
issue = ReleaseTools::PatchIssue.new(version: version)
create_or_show_issue(issue)
deprecate_as 'release:issue', args
end
desc "Create a QA issue"
task :qa_issue, [:from, :to, :version] do |_t, args|
# Attempt to infer the version from the `to` ref
version = get_version(args.with_defaults(version: args[:to].sub(/\Av/, '')))
issue = ReleaseTools::Qa::Services::BuildQaIssueService.new(
version: version,
from: args[:from],
to: args[:to],
issue_project: ReleaseTools::Qa::ISSUE_PROJECT,
projects: ReleaseTools::Qa::PROJECTS
).execute
create_or_show_issue(issue)
deprecate_as 'release:qa', args
end
desc "Create a QA issue for a security release"
task :security_qa_issue, [:from, :to, :version] do |_t, args|
ENV['SECURITY'] = 'true'
Rake::Task[:qa_issue].invoke(args[:from], args[:to], args[:version])
deprecate_as 'security:qa', args
end
desc 'Closes expired QA issues'
# Undocumented; executed via CI schedule
task :close_expired_qa_issues do
ReleaseTools::Qa::IssueCloser.new.execute
end
desc "Create preparation merge requests in CE and EE for a patch release"
task :patch_merge_request, [:version] do |_t, args|
# CE
version = get_version(args).to_ce
merge_request = ReleaseTools::PreparationMergeRequest.new(version: version)
merge_request.create_branch!
create_or_show_merge_request(merge_request)
# EE
version = version.to_ee
merge_request = ReleaseTools::PreparationMergeRequest.new(version: version)
merge_request.create_branch!
create_or_show_merge_request(merge_request)
deprecate_as 'release:prepare', args
end
desc "Cherry-pick merge requests into preparation branches"
task :cherry_pick, [:version] do |_t, args|
icon = -> (result) { result.success? ? "✓" : "✗" }
# CE
version = get_version(args).to_ce
$stdout.puts "--> Picking for #{version}..."
results = ReleaseTools::CherryPick::Service.new(ReleaseTools::Project::GitlabCe, version).execute
results.each do |result|
$stdout.puts " #{icon.call(result)} #{result.url}"
end
# EE
version = version.to_ee
$stdout.puts "--> Picking for #{version}..."
results = ReleaseTools::CherryPick::Service.new(ReleaseTools::Project::GitlabEe, version).execute
results.each do |result|
$stdout.puts " #{icon.call(result)} #{result.url}"
end
deprecate_as 'release:merge', args
end
task :security_cherry_pick, [:version] do |_t, args|
ENV['SECURITY'] = 'true'
Rake::Task[:cherry_pick].invoke(args[:version])
deprecate_as 'security:merge', args
end
desc "Create a security patch issue"
task :security_patch_issue, [:version] do |_t, args|
version = get_version(args)
issue = ReleaseTools::SecurityPatchIssue.new(version: version)
create_or_show_issue(issue)
deprecate_as 'security:issue', args
end
desc "Create a CE upstream merge request on EE"
# Undocumented; executed via CI schedule
task :upstream_merge do
result = ReleaseTools::Services::UpstreamMergeService
.new(dry_run: dry_run?, mention_people: !no_mention?, force: force?)
......@@ -247,29 +157,6 @@ task :upstream_merge do
end
end
namespace :release_managers do
desc "Verify release manager authorization"
task :auth, [:username] do |_t, args|
unless args[:username].present?
abort "You must provide a username to verify!"
end
unless ReleaseTools::ReleaseManagers::Definitions.allowed?(args[:username])
abort "#{args[:username]} is not an authorized release manager!"
end
end
desc "Sync Release Manager membership"
task :sync do
result = ReleaseTools::ReleaseManagers::Definitions.sync!
unless result.success?
$stdout.puts result.formatted_error_message
exit 1
end
end
end
namespace :helm do
desc "Create a chart release by passing in chart_version,gitlab_version"
task :tag_chart, [:version, :gitlab_version] do |_t, args|
......@@ -296,7 +183,7 @@ task :publish, [:version] do |_t, args|
.execute
end
desc 'Announce the feature freeze on Slack'
# Undocumented; executed via CI schedule
task :freeze do
require 'httparty'
require 'json'
......
# frozen_string_literal: true
namespace :prepare do
desc 'Prepare for a new monthly release'
task :monthly, [:version] do |_t, args|
version = get_version(args)
raise "`#{version}` is not a monthly version!" unless version.monthly?
service = ReleaseTools::Services::MonthlyPreparationService.new(version)
service.create_label
service.create_stable_branches
# Create the monthly and RC1 task issues
Rake::Task['monthly_issue'].execute(version: version)
Rake::Task['patch_issue'].execute(version: version.to_rc(1))
end
desc 'Prepare the next security release'
task :security do
issue_task = Rake::Task['security_patch_issue']
service = ReleaseTools::Services::SecurityPreparationService.new
service.next_versions.each do |version|
issue_task.execute(version: version)
end
end
end
namespace :release do
desc 'Create a release task issue'
task :issue, [:version] do |_t, args|
version = get_version(args)
if version.monthly?
issue = ReleaseTools::MonthlyIssue.new(version: version)
else
issue = ReleaseTools::PatchIssue.new(version: version)
end
create_or_show_issue(issue)
end
desc 'Merges valid merge requests into preparation branches'
task :merge, [:version] do |_t, args|
icon = ->(result) { result.success? ? "✓" : "✗" }
# CE
version = get_version(args).to_ce
$stdout.puts "--> Picking for #{version}..."
results = ReleaseTools::CherryPick::Service
.new(ReleaseTools::Project::GitlabCe, version)
.execute
results.each do |result|
$stdout.puts " #{icon.call(result)} #{result.url}"
end
# EE
version = version.to_ee
$stdout.puts "--> Picking for #{version}..."
results = ReleaseTools::CherryPick::Service
.new(ReleaseTools::Project::GitlabEe, version)
.execute
results.each do |result|
$stdout.puts " #{icon.call(result)} #{result.url}"
end
end
desc 'Prepare for a new release'
task :prepare, [:version] do |_t, args|
version = get_version(args)
Rake::Task['release:issue'].execute(version: version)
if version.monthly?
service = ReleaseTools::Services::MonthlyPreparationService.new(version)
service.create_label
service.create_stable_branches
Rake::Task['release:issue'].execute(version: version.to_rc(1))
else
# Create preparation MR for CE
version = version.to_ce
merge_request = ReleaseTools::PreparationMergeRequest.new(version: version)
merge_request.create_branch!
create_or_show_merge_request(merge_request)
# Create preparation MR for EE
version = version.to_ee
merge_request = ReleaseTools::PreparationMergeRequest.new(version: version)
merge_request.create_branch!
create_or_show_merge_request(merge_request)
end
end
desc 'Create a QA issue'
task :qa, [:from, :to] do |_t, args|
# Attempt to infer the version from the `to` ref
version = get_version(args.with_defaults(version: args[:to].sub(/\Av/, '')))
issue = ReleaseTools::Qa::Services::BuildQaIssueService.new(
version: version,
from: args[:from],
to: args[:to],
issue_project: ReleaseTools::Qa::ISSUE_PROJECT,
projects: ReleaseTools::Qa::PROJECTS
).execute
create_or_show_issue(issue)
end
desc 'Tag a new release'
task :tag, [:version] do |_t, args|
version = get_version(args)
if skip?('ee')
$stdout.puts 'Skipping release for EE'.colorize(:red)
else
ee_version = version.to_ee
$stdout.puts 'EE release'.colorize(:blue)
ReleaseTools::Release::GitlabEeRelease.new(ee_version).execute
ReleaseTools::Slack::TagNotification.release(ee_version) unless dry_run?
end
if skip?('ce')
$stdout.puts 'Skipping release for CE'.colorize(:red)
else
ce_version = version.to_ce
$stdout.puts 'CE release'.colorize(:blue)
ReleaseTools::Release::GitlabCeRelease.new(ce_version).execute
ReleaseTools::Slack::TagNotification.release(ce_version) unless dry_run?
end
end
end
# frozen_string_literal: true
namespace :release_managers do
desc "Verify release manager authorization"
task :auth, [:username] do |_t, args|
unless args[:username].present?
abort "You must provide a username to verify!"
end
unless ReleaseTools::ReleaseManagers::Definitions.allowed?(args[:username])
abort "#{args[:username]} is not an authorized release manager!"
end
end
desc "Sync Release Manager membership"
task :sync do
result = ReleaseTools::ReleaseManagers::Definitions.sync!
unless result.success?
$stdout.puts result.formatted_error_message
exit 1
end
end
end
namespace :security do
desc 'Validate security merge requests'
task :validate do
ReleaseTools::Security::MergeRequestsValidator.new.execute
# Undocumented; should be a pre-requisite for every task in this namespace!
task :force_security do
ENV['SECURITY'] = 'true'
end
desc 'Create a security release task issue'
task :issue, [:version] => :force_security do |_t, args|
version = get_version(args)
issue = ReleaseTools::SecurityPatchIssue.new(version: version)
create_or_show_issue(issue)
end
desc 'Merges valid security merge requests'
task :merge, [:merge_master] do |_, args|
task :merge, [:merge_master] => :force_security do |_t, args|
merge_master =
if args[:merge_master] && !args[:merge_master].empty?
true
......@@ -17,4 +26,35 @@ namespace :security do
.new(merge_master: merge_master)
.execute
end
desc 'Prepare for a new security release'
task :prepare, [:version] => :force_security do |_t, _args|
issue_task = Rake::Task['security:issue']
service = ReleaseTools::Services::SecurityPreparationService.new
service.next_versions.each do |version|
issue_task.execute(version: version)
end
end
desc 'Create a security QA issue'
task :qa, [:from, :to] => :force_security do |_t, args|
Rake::Task['release:qa'].invoke(*args)
end
desc 'Tag a new security release'
task :tag, [:version] => :force_security do |_t, args|
$stdout
.puts "Security Release - using security repository only!\n"
.colorize(:red)
Rake::Task['release:tag'].invoke(*args)
end
# Undocumented; executed via CI schedule
task validate: :force_security do
ReleaseTools::Security::MergeRequestsValidator
.new
.execute
end
end
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