...
 
Commits (4)
......@@ -90,6 +90,22 @@ pages:
# automation ------------------------------------------------------------------
security-sync:
<<: *with-bundle
stage: automation
script:
- source scripts/setup_ssh.sh
- echo "$RELEASE_BOT_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- git config --global user.email "robert+release-tools@gitlab.com"
- git config --global user.name "GitLab Release Tools Bot"
- bundle exec rake security:sync[$RELEASE_VERSION]
only:
variables:
- $SECURITY_SYNC
cache:
<<: *global-cache
policy: pull
release-managers:
<<: *with-bundle
stage: automation
......
......@@ -70,27 +70,6 @@ task :tag_security, [:version] do |t, args|
deprecate_as 'security:tag', t, args
end
desc "Sync master branch in remotes"
task :sync do
if skip?('ee')
$stdout.puts 'Skipping sync for EE'.colorize(:yellow)
else
ReleaseTools::Sync.new(ReleaseTools::Project::GitlabEe.remotes).execute
end
if skip?('ce')
$stdout.puts 'Skipping sync for CE'.colorize(:yellow)
else
ReleaseTools::Sync.new(ReleaseTools::Project::GitlabCe.remotes).execute
end
if skip?('og')
$stdout.puts 'Skipping sync for Omnibus Gitlab'.colorize(:yellow)
else
ReleaseTools::Sync.new(ReleaseTools::Project::OmnibusGitlab.remotes).execute
end
end
task :monthly_issue, [:version] do |t, args|
deprecate_as 'release:issue', t, args
end
......
......@@ -107,7 +107,7 @@ require 'release_tools/slack/chatops_notification'
require 'release_tools/slack/tag_notification'
require 'release_tools/slack/upstream_merge_notification'
require 'release_tools/support/tasks_helper'
require 'release_tools/sync'
require 'release_tools/security_sync'
require 'release_tools/team'
require 'release_tools/team_member'
require 'release_tools/time_util'
......
......@@ -19,7 +19,7 @@ module ReleaseTools
CanonicalRemote = Struct.new(:name, :url)
GitCommandResult = Struct.new(:output, :status)
def self.get(remotes, repository_name = nil, global_depth: 1)
def self.get(remotes, repository_name = nil, global_depth: 1, branch: nil)
repository_name ||= remotes
.values
.first
......@@ -27,15 +27,16 @@ module ReleaseTools
.last
.sub(/\.git\Z/, '')
new(File.join('/tmp', repository_name), remotes, global_depth: global_depth)
new(File.join('/tmp', repository_name), remotes, global_depth: global_depth, branch: branch)
end
attr_reader :path, :remotes, :canonical_remote, :global_depth
attr_reader :path, :remotes, :canonical_remote, :global_depth, :branch
def initialize(path, remotes, global_depth: 1)
def initialize(path, remotes, global_depth: 1, branch: nil)
$stdout.puts 'Pushes will be ignored because of TEST env'.colorize(:yellow) if SharedStatus.dry_run?
@path = path
@global_depth = global_depth
@branch = branch
cleanup
......@@ -259,6 +260,7 @@ module ReleaseTools
cmd = %w[clone --quiet]
cmd << "--depth=#{global_depth}" if global_depth
cmd << "--branch=#{branch}" if branch
cmd << '--origin' << canonical_remote.name.to_s << canonical_remote.url << path
output, status = self.class.run_git(cmd)
......
# frozen_string_literal: true
module ReleaseTools
class SecuritySync
SECURITY_SOURCE = :dev
def initialize(project)
@project = project
end
# Sync stable branch and tag for from a security repository to all remotes
#
# Fetches the stable branch for the specified version from all remotes, then
# merges the branch from the security remote and pushes the branch and tag
# to all remotes, bringing them all back in sync after a security release.
def execute(version)
branch = version.stable_branch
# NOTE: We have to use the `REMOTES` constant, as the `remotes` method
# would only return `dev` during a security release.
repository = RemoteRepository
.get(@project::REMOTES, global_depth: 200, branch: branch)
repository.pull_from_all_remotes(branch)
merge_result = repository
.merge("#{SECURITY_SOURCE}/#{branch}", branch, no_ff: true)
if merge_result.status.success?
repository.push_to_all_remotes(branch)
repository.push_to_all_remotes(version.tag)
else
warn "Bad merge of `#{SECURITY_SOURCE}/#{branch}`".colorize(:red)
warn merge_result.output.colorize(:red).indent(4)
end
end
end
end
# frozen_string_literal: true
module ReleaseTools
class Sync
attr_reader :remotes
def initialize(remotes)
@remotes = remotes
end
def execute(branch = 'master')
sync(branch)
end
private
def sync(branch)
repository = RemoteRepository.get(remotes, "gitlab-sync-#{Time.now.to_i}")
repository.pull_from_all_remotes(branch)
repository.push_to_all_remotes(branch)
end
end
end
......@@ -42,6 +42,18 @@ namespace :security do
Rake::Task['release:qa'].invoke(*args)
end
desc 'Sync stable branches from security to production'
task :sync, [:version] => :force_security do |_t, args|
version = get_version(args)
ob_version = ReleaseTools::OmnibusGitlabVersion.new(version.to_omnibus)
sync = ReleaseTools::SecuritySync
sync.new(ReleaseTools::Project::GitlabEe).execute(version.to_ee)
sync.new(ReleaseTools::Project::GitlabCe).execute(version.to_ce)
sync.new(ReleaseTools::Project::OmnibusGitlab).execute(ob_version.to_ee)
sync.new(ReleaseTools::Project::OmnibusGitlab).execute(ob_version.to_ce)
end
desc 'Tag a new security release'
task :tag, [:version] => :force_security do |_t, args|
$stdout
......
......@@ -42,10 +42,18 @@ describe ReleaseTools::RemoteRepository do
end
it 'accepts a :global_depth option' do
expect(described_class).to receive(:new).with(anything, anything, global_depth: 100)
expect(described_class).to receive(:new)
.with(anything, anything, a_hash_including(global_depth: 100))
described_class.get(remotes, global_depth: 100)
end
it 'accepts a :branch option' do
expect(described_class).to receive(:new)
.with(anything, anything, a_hash_including(branch: 'foo'))
described_class.get(remotes, branch: 'foo')
end
end
describe 'initialize', :silence_stdout do
......