#!/usr/bin/env ruby require "date" require "optparse" def run(command, abort_on_fail: true) puts "> #{command}" if $VERBOSE system(command, exception: abort_on_fail) rescue StandardError => e raise "#{command.inspect} failed: #{e}" end channel = ENV.fetch("FOREM_RELEASE_CHANNEL", "stable") date = ENV.fetch("FOREM_RELEASE_DATE", Date.today.to_s).delete("-") hotfix = ENV.fetch("FOREM_RELEASE_HOTFIX", 0) remote = ENV.fetch("FOREM_RELEASE_REMOTE", "origin") source = ENV.fetch("FOREM_STAGING_FROM", "#{channel}-next") OptionParser.new ARGV.dup do |options| options.banner = <<~USAGE Usage: #{$PROGRAM_NAME} [options] Releases are named CHANNEL.DATE.HOTFIX_COUNT. Example: #{channel}.#{date}.#{hotfix} USAGE options.on "-c", "--channel CHANNEL", "Specify the release channel (defaults to #{channel.inspect})" do |release_channel| channel = release_channel end options.on "-d", "--date DATE", "Specify the release date (defaults to today)" do |release_date| date = release_date.delete("-") end options.on "-f", "--from BRANCH/COMMIT/TAG", "Specify the source branch for this release (defaults to #{source.inspect})" do |from_branch| source = from_branch end options.on "-h", "--hotfix HOTFIX", "Specify the hotfix count for this release branch (defaults to #{hotfix.inspect})" do |hotfix_opt| hotfix = hotfix_opt end options.on "-r", "--remote REMOTE", "Git remote to push to (defaults to #{remote.inspect})" do |git_remote| remote = git_remote end options.on "-v", "--verbose", "Enable verbose mode" do $VERBOSE = true end end.parse! original_branch = `git branch --show-current`.strip begin tag = "#{channel}.#{date}.#{hotfix}" puts "Building #{tag}..." [source, channel].each do |branch| run "git checkout --quiet #{branch}" run "git pull --quiet --ff-only #{remote} #{branch}" puts "Pulled latest #{branch.inspect}" end run "git merge --quiet #{source} --no-ff --message 'Merge #{source} into #{channel}'" puts "Merged #{source} into #{channel}" begin File.write ".release-version", tag run "git add .release-version" run "git commit --message 'Version #{tag}'" run "git tag #{tag}" puts "Tagged #{tag}" rescue StandardError # If `git tag` fails, it's because the tag already exists. In this case, git # will have already output an error that looks like this: # # fatal: tag 'stable.20210512.0' already exists # warn "Should the hotfix count be set to something other than #{hotfix}?" \ "Or maybe you need to delete the tag locally (hint: `git tag --delete #{tag}`)" exit 1 end run "git push --quiet #{remote} #{channel}" puts "Pushed #{channel} to #{remote}" run "git push --quiet #{remote} #{tag}" puts "Pushed #{tag} to #{remote}" ensure # Go back to the branch we were on before running this script run "git checkout --quiet #{original_branch}" end