diff options
author | Vladimir Shushlin <vshushlin@gitlab.com> | 2022-04-22 08:51:53 +0300 |
---|---|---|
committer | Vladimir Shushlin <vshushlin@gitlab.com> | 2022-04-22 08:51:53 +0300 |
commit | fc7766e6ba24ac34225234e3ce7cd1eb8edbaab2 (patch) | |
tree | d04efcff2073f38a2b87746b3b1f9cadf912bf76 | |
parent | bd0314a207e2e20a9fef5a9f4392e1eee2ca19f3 (diff) | |
parent | ce217e7245590455047c1dc4993762e7f8d8aec6 (diff) |
Merge branch 'kassio/add-secpick' into 'master'
Add scripts/secpick
See merge request gitlab-org/gitlab-pages!715
-rw-r--r-- | .tool-versions | 1 | ||||
-rwxr-xr-x | scripts/secpick | 143 |
2 files changed, 144 insertions, 0 deletions
diff --git a/.tool-versions b/.tool-versions index 108bdd0f..ff7a519d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1,2 @@ golang 1.17.7 +ruby 3.0.2 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! |