diff options
author | Kassio Borges <kborges@gitlab.com> | 2022-04-22 08:51:53 +0300 |
---|---|---|
committer | Vladimir Shushlin <vshushlin@gitlab.com> | 2022-04-22 08:51:53 +0300 |
commit | ce217e7245590455047c1dc4993762e7f8d8aec6 (patch) | |
tree | cbf36556420eb5bf71c51c409ae12d78b88ae444 /scripts | |
parent | dabfd71101d4598f31ab474f6a7bfc75bfa0a045 (diff) |
Add scripts/secpick
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/secpick | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/scripts/secpick b/scripts/secpick new file mode 100755 index 00000000..d219f487 --- /dev/null +++ b/scripts/secpick @@ -0,0 +1,143 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'bundler/inline' + +gemfile do + source 'https://rubygems.org' + + gem 'rainbow', '~> 3.0' + gem 'activesupport', '~> 6.1' +end + +require 'active_support/core_ext/object/to_query' +require 'optparse' +require 'open3' +require 'rainbow/refinement' +using Rainbow + +module Secpick + BRANCH_PREFIX = 'security' + STABLE_SUFFIX = 'stable' + + DEFAULT_REMOTE = 'security' + + SECURITY_MR_URL = 'https://gitlab.com/gitlab-org/security/gitlab-pages/-/merge_requests/new' + + class SecurityFix + def initialize + @options = self.class.options + end + + def dry_run? + @options[:try] == true + end + + def source_branch + branch = "#{@options[:branch]}-#{@options[:version]}" + branch = "#{BRANCH_PREFIX}-#{branch}" unless branch.start_with?("#{BRANCH_PREFIX}-") + branch + end + + def stable_branch + "#{@options[:version]}-#{STABLE_SUFFIX}" + end + + def git_commands + ["git fetch #{@options[:remote]} #{stable_branch}", + "git checkout -B #{source_branch} #{@options[:remote]}/#{stable_branch} --no-track", + "git cherry-pick #{@options[:sha]}", + "git push #{@options[:remote]} #{source_branch} --no-verify", + "git checkout #{@options[:branch]}"] + end + + def gitlab_params + { + issuable_template: 'Security Release', + merge_request: { + source_branch: source_branch, + target_branch: stable_branch + } + } + end + + def new_mr_url + SECURITY_MR_URL + end + + def create! + if dry_run? + puts "\nGit commands:".blue + puts git_commands.join("\n") + + puts "\nMerge request URL:".blue + puts new_mr_url + + puts "\nMerge request params:".blue + pp gitlab_params + else + cmd = git_commands.join(' && ') + stdin, stdout, stderr, wait_thr = Open3.popen3(cmd) + + puts stdout.read&.green + puts stderr.read&.red + + if wait_thr.value.success? + puts "#{new_mr_url}?#{gitlab_params.to_query}".blue + end + + stdin.close + stdout.close + stderr.close + end + end + + def self.options + { version: nil, branch: nil, sha: nil }.tap do |options| + parser = OptionParser.new do |opts| + opts.banner = "Usage: #{$0} [options]" + opts.on('-v', '--version 10.0', 'Version') do |version| + options[:version] = version&.tr('.', '-') + end + + opts.on('-b', '--branch security-fix-branch', 'Original branch name (optional, defaults to current)') do |branch| + options[:branch] = branch + end + + opts.on('-s', '--sha abcd', 'SHA or SHA range to cherry pick (optional, defaults to current)') do |sha| + options[:sha] = sha + end + + opts.on('-r', '--remote dev', "Git remote name of security repo (optional, defaults to `#{DEFAULT_REMOTE}`)") do |remote| + options[:remote] = remote + end + + opts.on('-d', '--dry-run', 'Only show Git commands, without calling them') do + options[:try] = true + end + + opts.on('-h', '--help', 'Displays Help') do + puts opts + + exit + end + end + + parser.parse! + + options[:sha] ||= `git rev-parse HEAD`.strip + options[:branch] ||= `git rev-parse --abbrev-ref HEAD`.strip + options[:remote] ||= DEFAULT_REMOTE + + nil_options = options.select {|_, v| v.nil? } + unless nil_options.empty? + abort("Missing: #{nil_options.keys.join(', ')}. Use #{$0} --help to see the list of options available".red) + end + + abort("Wrong version format #{options[:version].bold}".red) unless options[:version] =~ /\A\d*\-\d*\Z/ + end + end + end +end + +Secpick::SecurityFix.new.create! |