From 7ee4b21f4ec74828c73a9678c8c777294d4d22f4 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 24 May 2024 08:59:48 +0100 Subject: [PATCH] Improve shared configuration syncing. - Improve code style to match `brew style` norms. - General code refactoring/cleanup. - Fail script on invalid parameters. - Provide custom handling for `.rubocop.yml` and `.ruby-version` from Homebrew/brew's repository. We want to match the RuboCop and (Portable) Ruby version (without revision) usage from there. - Ensure that this workflow is always tested (but PRs not created) when triggered by a pull request. - Check code style with `brew style` in CI. --- .github/actions/sync/shared-config.rb | 81 +++++++++++++++--------- .github/workflows/sync-shared-config.yml | 11 +++- .rubocop.yml | 80 +++++++++++++++++++++++ 3 files changed, 140 insertions(+), 32 deletions(-) create mode 100644 .rubocop.yml diff --git a/.github/actions/sync/shared-config.rb b/.github/actions/sync/shared-config.rb index 4719a267..d90227b4 100755 --- a/.github/actions/sync/shared-config.rb +++ b/.github/actions/sync/shared-config.rb @@ -1,59 +1,80 @@ #!/usr/bin/env ruby +# frozen_string_literal: true -require 'fileutils' -require 'open3' -require 'pathname' +require "English" +require "fileutils" +require "open3" +require "pathname" +# This makes sense for a standalone script. +# rubocop:disable Style/TopLevelMethodDefinition def git(*args) - system 'git', *args - exit $?.exitstatus unless $?.success? + system "git", *args + exit $CHILD_STATUS.exitstatus unless $CHILD_STATUS.success? end +# rubocop:enable Style/TopLevelMethodDefinition -target_dir = Pathname(ARGV[0]) -source_dir = ARGV[1] +target_directory = ARGV[0] +target_directory_path = Pathname(target_directory) +homebrew_directory_path = Pathname(ARGV[1]) -puts 'Detecting changes…' +if !target_directory_path.directory? || !homebrew_directory_path.directory? || ARGV[2] + abort "Usage: #{$PROGRAM_NAME} " +end + +ruby_version = ".ruby-version" +rubocop_yml = ".rubocop.yml" + +homebrew_ruby_version = + (homebrew_directory_path/"Library/Homebrew/vendor/portable-ruby-version").read.chomp.sub(/_\d+$/, "") +homebrew_rubocop_config = homebrew_directory_path/"Library/Homebrew/#{rubocop_yml}" + +puts "Detecting changes…" [ - '.github/workflows/lock-threads.yml', - '.github/workflows/stale-issues.yml', - '.ruby-version', -].each do |glob| - src_paths = Pathname.glob(glob) - dst_paths = Pathname.glob(target_dir.join(glob)) - - dst_paths.each do |path| - FileUtils.rm_f path - end + ruby_version, + rubocop_yml, + ".github/workflows/lock-threads.yml", + ".github/workflows/stale-issues.yml", +].each do |file| + FileUtils.rm_f file + + target_path = target_directory_path/file + target_path.dirname.mkpath - src_paths.each do |path| - target_dir.join(path.dirname).mkpath - FileUtils.cp path, target_dir.join(path) + case file + when ruby_version + path.write("#{homebrew_ruby_version}\n") + when rubocop_yml + FileUtils.cp homebrew_rubocop_config, path + else + FileUtils.cp file, target_path end end -out, err, status = Open3.capture3('git', '-C', target_dir.to_s, 'status', '--porcelain', '--ignore-submodules=dirty') +out, err, status = Open3.capture3("git", "-C", target_directory, "status", "--porcelain", "--ignore-submodules=dirty") raise err unless status.success? -target_dir_changed = !out.chomp.empty? +target_directory_path_changed = !out.chomp.empty? -unless target_dir_changed - puts 'No changes detected.' +unless target_directory_path_changed + puts "No changes detected." exit end -git '-C', target_dir.to_s, 'add', '--all' +git "-C", target_directory, "add", "--all" -out, err, status = Open3.capture3('git', '-C', target_dir.to_s, 'diff', '--name-only', '--staged') +out, err, status = Open3.capture3("git", "-C", target_directory, "diff", "--name-only", "--staged") raise err unless status.success? modified_paths = out.lines.map(&:chomp) modified_paths.each do |modified_path| puts "Detected changes to #{modified_path}." - git '-C', target_dir.to_s, 'commit', modified_path, '--message', "#{File.basename(modified_path)}: update to match main configuration", '--quiet' + git "-C", target_directory, "commit", modified_path, "--message", + "#{File.basename(modified_path)}: update to match main configuration", "--quiet" end puts -File.open(ENV.fetch('GITHUB_OUTPUT'), 'a') do |f| - f.puts 'pull_request=true' +File.open(ENV.fetch("GITHUB_OUTPUT"), "a") do |f| + f.puts "pull_request=true" end diff --git a/.github/workflows/sync-shared-config.yml b/.github/workflows/sync-shared-config.yml index 6a2b1a93..107bd670 100644 --- a/.github/workflows/sync-shared-config.yml +++ b/.github/workflows/sync-shared-config.yml @@ -4,6 +4,7 @@ on: push: branches: - master + pull_request: permissions: contents: read @@ -45,6 +46,12 @@ jobs: - Homebrew/rubydoc.brew.sh fail-fast: false steps: + - name: Set up Homebrew + id: set-up-homebrew + uses: Homebrew/actions/setup-homebrew@master + + - run: brew style .github/actions/sync/*.rb + - name: Clone main repository uses: actions/checkout@v4 with: @@ -71,10 +78,10 @@ jobs: id: detect_changes env: HOMEBREW_GPG_PASSPHRASE: ${{ secrets.BREWTESTBOT_GPG_SIGNING_SUBKEY_PASSPHRASE }} - run: ./.github/actions/sync/shared-config.rb 'vendor/${{ matrix.repo }}' '${{ matrix.repo }}' 'sync-shared-config' + run: ./.github/actions/sync/shared-config.rb 'vendor/${{ matrix.repo }}' '${{ steps.set-up-homebrew.outputs.repository-path }}' - name: Create pull request - if: ${{ steps.detect_changes.outputs.pull_request == 'true' }} + if: ${{ github.ref == 'refs/heads/master' && steps.detect_changes.outputs.pull_request == 'true' }} uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e with: path: vendor/${{ matrix.repo }} diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000..a35001a9 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,80 @@ +inherit_from: + - ../.rubocop.yml + +Bundler/GemFilename: + Enabled: false + +Homebrew/MoveToExtendOS: + Enabled: true + Exclude: + - "{extend,test,requirements}/**/*" + - "os.rb" + +Naming/PredicateName: + inherit_mode: + merge: + - AllowedMethods + AllowedMethods: + - is_32_bit? + - is_64_bit? + +# Only enforce documentation for public APIs. +# Checked by the tests.yml syntax job +Style/Documentation: + AllowedConstants: + - Homebrew + Include: + - cask/cask.rb + - cask/dsl.rb + - cask/dsl/version.rb + - cask/url.rb + - development_tools.rb + - download_strategy.rb + - extend/ENV/super.rb + - extend/kernel.rb + - extend/pathname.rb + - formula.rb + - formula_assertions.rb + - formula_free_port.rb + - language/go.rb + - language/java.rb + - language/node.rb + - language/perl.rb + - language/python.rb + - livecheck/strategy/apache.rb + - livecheck/strategy/bitbucket.rb + - livecheck/strategy/cpan.rb + - livecheck/strategy/crate.rb + - livecheck/strategy/extract_plist.rb + - livecheck/strategy/git.rb + - livecheck/strategy/github_latest.rb + - livecheck/strategy/github_releases.rb + - livecheck/strategy/gnome.rb + - livecheck/strategy/gnu.rb + - livecheck/strategy/hackage.rb + - livecheck/strategy/json.rb + - livecheck/strategy/launchpad.rb + - livecheck/strategy/npm.rb + - livecheck/strategy/page_match.rb + - livecheck/strategy/pypi.rb + - livecheck/strategy/sourceforge.rb + - livecheck/strategy/sparkle.rb + - livecheck/strategy/xml.rb + - livecheck/strategy/xorg.rb + - livecheck/strategy/yaml.rb + - os.rb + - resource.rb + - utils/inreplace.rb + - utils/shebang.rb + - utils/string_inreplace_extension.rb + - version.rb + - tap.rb + +Homebrew/NegateInclude: + Exclude: + # YARD runs stand-alone. + - yard/docstring_parser.rb + +Style/DocumentationMethod: + Include: + - "formula.rb"