secpick 3.53 KB
Newer Older
1
#!/usr/bin/env ruby
2

James Lopez's avatar
James Lopez committed
3 4 5
# frozen_string_literal: false

require 'active_support/core_ext/object/to_query'
6 7 8 9 10
require 'optparse'
require 'open3'
require 'rainbow/refinement'
using Rainbow

11 12
module Secpick
  BRANCH_PREFIX = 'security'.freeze
13
  STABLE_SUFFIX = 'stable'.freeze
14 15
  DEFAULT_REMOTE = 'dev'.freeze
  NEW_MR_URL = 'https://dev.gitlab.org/gitlab/gitlabhq/merge_requests/new'.freeze
16

17 18 19 20
  class SecurityFix
    def initialize
      @options = self.class.options
    end
21

22 23 24
    def ee?
      File.exist?('./CHANGELOG-EE.md')
    end
25

26 27 28
    def dry_run?
      @options[:try] == true
    end
29

30 31 32
    def original_branch
      @options[:branch].strip
    end
33

34 35 36 37 38
    def source_branch
      branch = "#{original_branch}-#{@options[:version]}"
      branch.prepend("#{BRANCH_PREFIX}-") unless branch.start_with?("#{BRANCH_PREFIX}-")
      branch.freeze
    end
39

40
    def stable_branch
41
      "#{@options[:version]}-#{STABLE_SUFFIX}".tap do |name|
42 43 44
        name << "-ee" if ee?
      end.freeze
    end
45

46
    def git_commands
47
      ["git fetch #{@options[:remote]} #{stable_branch}",
48
       "git checkout -B #{source_branch} #{@options[:remote]}/#{stable_branch}",
49 50 51 52
       "git cherry-pick #{@options[:sha]}",
       "git push #{@options[:remote]} #{source_branch}",
       "git checkout #{original_branch}"]
    end
53

54 55
    def gitlab_params
      {
56
        issuable_template: 'Security Release',
57 58
        merge_request: {
          source_branch: source_branch,
59
          target_branch: stable_branch
60 61 62
        }
      }
    end
63

64 65 66 67 68 69 70
    def new_mr_url
      if ee?
        NEW_MR_URL.sub('gitlabhq', 'gitlab-ee')
      else
        NEW_MR_URL
      end
    end
71

72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    def create!
      if dry_run?
        puts git_commands.join("\n").green
        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
93

94 95 96 97 98 99 100
    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
101

102 103 104
          opts.on('-b', '--branch security-fix-branch', 'Original branch name (optional, defaults to current)') do |branch|
            options[:branch] = branch
          end
105

106 107 108
          opts.on('-s', '--sha abcd', 'SHA to cherry pick') do |sha|
            options[:sha] = sha
          end
109

110 111 112
          opts.on('-r', '--remote abcd', 'Git remote name of dev.gitlab.org (optional, defaults to `dev`)') do |remote|
            options[:remote] = remote
          end
113

114 115 116
          opts.on('-d', '--dry-run', 'Only show Git commands, without calling them') do |remote|
            options[:try] = true
          end
117

118 119
          opts.on('-h', '--help', 'Displays Help') do
            puts opts
James Lopez's avatar
James Lopez committed
120

121 122 123
            exit
          end
        end
124

125
        parser.parse!
126

127 128
        options[:branch] ||= `git rev-parse --abbrev-ref HEAD`
        options[:remote] ||= DEFAULT_REMOTE
129

130 131
        abort("Missing options. Use #{$0} --help to see the list of options available".red) if options.values.include?(nil)
        abort("Wrong version format #{options[:version].bold}".red) unless options[:version] =~ /\A\d*\-\d*\Z/
132 133 134
      end
    end
  end
James Lopez's avatar
James Lopez committed
135 136
end

137
Secpick::SecurityFix.new.create!