From 37eaed5bb77a1e5fdb8fbd29f65fbd9bb8b190fb Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sun, 3 Aug 2025 22:51:29 +0100 Subject: [PATCH 1/3] Ensure that `head` Git URLs always specify a branch - There's a TODO on the "someday" list [1] to ensure that `head` Git URLs always specify a branch. - So I thought I'd automate this worry by adding an audit. - Since `resource` block URLs tend to be pinned to SHAs, if indeed they are Git URLs, this audit only applies to `head` URLs. [1]: https://github.com/orgs/Homebrew/projects/5?pane=issue&itemId=98789749 --- Library/Homebrew/formula.rb | 4 +- Library/Homebrew/resource_auditor.rb | 19 +++-- Library/Homebrew/test/dev-cmd/bump_spec.rb | 2 +- Library/Homebrew/test/formula_auditor_spec.rb | 85 ++++++++++++++++--- .../Homebrew/test/livecheck/livecheck_spec.rb | 4 +- .../test/livecheck/skip_conditions_spec.rb | 4 +- Library/Homebrew/test/livecheck_spec.rb | 2 +- .../rubocops/components_redundancy_spec.rb | 7 +- .../test/utils/ast/formula_ast_spec.rb | 8 +- docs/Formula-Cookbook.md | 2 +- 10 files changed, 102 insertions(+), 35 deletions(-) diff --git a/Library/Homebrew/formula.rb b/Library/Homebrew/formula.rb index 525fc58f9c..0da5baec21 100644 --- a/Library/Homebrew/formula.rb +++ b/Library/Homebrew/formula.rb @@ -3797,12 +3797,12 @@ class Formula # If called as a method this provides just the {url} for the {SoftwareSpec}. # If a block is provided you can also add {.depends_on} and {Patch}es just to the {.head} {SoftwareSpec}. # The download strategies (e.g. `:using =>`) are the same as for {url}. - # `master` is the default branch for Git and doesn't need stating with a `branch:` parameter. + # Git repositories must always specify `branch:`. # # ### Example # # ```ruby - # head "https://we.prefer.https.over.git.example.com/.git" + # head "https://we.prefer.https.over.git.example.com/.git", branch: "main" # ``` # # ```ruby diff --git a/Library/Homebrew/resource_auditor.rb b/Library/Homebrew/resource_auditor.rb index 8f20881f21..b3f2663f1c 100644 --- a/Library/Homebrew/resource_auditor.rb +++ b/Library/Homebrew/resource_auditor.rb @@ -178,18 +178,23 @@ module Homebrew end def audit_head_branch - return unless @online - return unless @strict return if spec_name != :head - return unless Utils::Git.remote_exists?(url) return if specs[:tag].present? return if specs[:revision].present? + # Skip `resource` URLs as they use SHAs instead of branch specifiers. + return if name != owner.name + return unless url.end_with?(".git") - branch = Utils.popen_read("git", "ls-remote", "--symref", url, "HEAD") - .match(%r{ref: refs/heads/(.*?)\s+HEAD})&.to_a&.second - return if branch.blank? || branch == specs[:branch] + problem "Git `head` URL must specify a branch name" if specs[:branch].blank? - problem "Specify the default branch as `branch: \"#{branch}\"`" + return unless @online + return unless Utils::Git.remote_exists?(url) + + detected_branch = Utils.popen_read("git", "ls-remote", "--symref", url, "HEAD") + .match(%r{ref: refs/heads/(.*?)\s+HEAD})&.to_a&.second + return if detected_branch.blank? || detected_branch == specs[:branch] + + problem "Detected a default branch \"#{detected_branch}\", not \"#{specs[:branch]}\"" end def problem(text) diff --git a/Library/Homebrew/test/dev-cmd/bump_spec.rb b/Library/Homebrew/test/dev-cmd/bump_spec.rb index 31e7447e23..abfaf735f8 100644 --- a/Library/Homebrew/test/dev-cmd/bump_spec.rb +++ b/Library/Homebrew/test/dev-cmd/bump_spec.rb @@ -11,7 +11,7 @@ RSpec.describe Homebrew::DevCmd::Bump do content = <<~RUBY desc "HEAD-only test formula" homepage "https://brew.sh" - head "https://github.com/Homebrew/brew.git" + head "https://github.com/Homebrew/brew.git", branch: "main" RUBY setup_test_formula("headonly", content) diff --git a/Library/Homebrew/test/formula_auditor_spec.rb b/Library/Homebrew/test/formula_auditor_spec.rb index a442e03d42..5b5124891d 100644 --- a/Library/Homebrew/test/formula_auditor_spec.rb +++ b/Library/Homebrew/test/formula_auditor_spec.rb @@ -285,7 +285,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "GPL-3.0-or-later" end RUBY @@ -301,7 +301,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license all_of: ["GPL-3.0-or-later", "MIT"] end RUBY @@ -317,7 +317,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "GPL-3.0-or-later" => { with: "LLVM-exception" } end RUBY @@ -332,7 +332,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "GPL-3.0-or-later" => { with: "zzz" } end RUBY @@ -351,7 +351,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "GPL-3.0-or-later" => { with: "#{deprecated_spdx_exception}" } end RUBY @@ -371,7 +371,7 @@ RSpec.describe Homebrew::FormulaAuditor do fa = formula_auditor "cask", <<~RUBY, spdx_license_data:, online: true, new_formula: true class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "GPL-3.0-or-later" end RUBY @@ -385,7 +385,7 @@ RSpec.describe Homebrew::FormulaAuditor do fa = formula_auditor "cask", <<~RUBY, spdx_license_data:, online: true, new_formula: true class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license any_of: ["GPL-3.0-or-later", "MIT"] end RUBY @@ -399,7 +399,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "0BSD" end RUBY @@ -416,7 +416,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license "0BSD" end RUBY @@ -433,7 +433,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license #{license_any_mismatch} end RUBY @@ -450,7 +450,7 @@ RSpec.describe Homebrew::FormulaAuditor do formula_text = <<~RUBY class Cask < Formula url "https://github.com/cask/cask/archive/v0.8.4.tar.gz" - head "https://github.com/cask/cask.git" + head "https://github.com/cask/cask.git", branch: "main" license #{license_any} end RUBY @@ -714,6 +714,63 @@ RSpec.describe Homebrew::FormulaAuditor do expect(fa.problems).to be_empty end + it "requires `branch:` to be specified for Git head URLs" do + fa = formula_auditor "foo", <<~RUBY + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" + head "https://github.com/example/foo.git" + end + RUBY + + fa.audit_specs + expect(fa.problems.first[:message]).to match("Git `head` URL must specify a branch name") + end + + it "suggests a detected default branch for Git head URLs" do + fa = formula_auditor "foo", <<~RUBY, online: true + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" + head "https://github.com/Homebrew/homebrew-core.git", branch: "master" + end + RUBY + + fa.audit_specs + # This is `.last` because the first problem is the unreachable stable URL. + expect(fa.problems.last[:message]).to match('Detected a default branch "main", not "master"') + end + + it "ignores `branch:` for non-Git head URLs" do + fa = formula_auditor "foo", <<~RUBY + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" + head "https://brew.sh/foo.tgz", branch: "develop" + end + RUBY + + fa.audit_specs + expect(fa.problems).not_to match("Git `head` URL must specify a branch name") + end + + it "ignores `branch:` for `resource` URLs" do + fa = formula_auditor "foo", <<~RUBY + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" + + resource "bar" do + url "https://raw.githubusercontent.com/Homebrew/homebrew-core/HEAD/Formula/bar.rb" + sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" + end + end + RUBY + + fa.audit_specs + expect(fa.problems).to be_empty + end + it "allows versions with no throttle rate" do fa = formula_auditor "bar", <<~RUBY, core_tap: true class Bar < Formula @@ -770,7 +827,7 @@ RSpec.describe Homebrew::FormulaAuditor do class Bar < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" end RUBY @@ -783,7 +840,7 @@ RSpec.describe Homebrew::FormulaAuditor do class BarAT1 < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" end RUBY @@ -796,7 +853,7 @@ RSpec.describe Homebrew::FormulaAuditor do class Foo < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" end RUBY diff --git a/Library/Homebrew/test/livecheck/livecheck_spec.rb b/Library/Homebrew/test/livecheck/livecheck_spec.rb index eab430f208..2371b1358d 100644 --- a/Library/Homebrew/test/livecheck/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck/livecheck_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Homebrew::Livecheck do desc "Test formula" homepage "https://brew.sh" url "https://brew.sh/test-0.0.1.tgz" - head "https://github.com/Homebrew/brew.git" + head "https://github.com/Homebrew/brew.git", branch: "main" livecheck do url "https://formulae.brew.sh/api/formula/ruby.json" @@ -252,7 +252,7 @@ RSpec.describe Homebrew::Livecheck do desc "Test formula with a duplicate URL" homepage "https://github.com/Homebrew/brew.git" url "https://brew.sh/test-0.0.1.tgz" - head "https://github.com/Homebrew/brew.git" + head "https://github.com/Homebrew/brew.git", branch: "main" end end diff --git a/Library/Homebrew/test/livecheck/skip_conditions_spec.rb b/Library/Homebrew/test/livecheck/skip_conditions_spec.rb index 94859b9404..eeb755d1cb 100644 --- a/Library/Homebrew/test/livecheck/skip_conditions_spec.rb +++ b/Library/Homebrew/test/livecheck/skip_conditions_spec.rb @@ -12,7 +12,7 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do desc "Test formula" homepage "https://brew.sh" url "https://brew.sh/test-0.0.1.tgz" - head "https://github.com/Homebrew/brew.git" + head "https://github.com/Homebrew/brew.git", branch: "main" livecheck do url "https://formulae.brew.sh/api/formula/ruby.json" @@ -34,7 +34,7 @@ RSpec.describe Homebrew::Livecheck::SkipConditions do head_only: formula("test_head_only") do desc "HEAD-only test formula" homepage "https://brew.sh" - head "https://github.com/Homebrew/brew.git" + head "https://github.com/Homebrew/brew.git", branch: "main" end, gist: formula("test_gist") do desc "Gist test formula" diff --git a/Library/Homebrew/test/livecheck_spec.rb b/Library/Homebrew/test/livecheck_spec.rb index 2a4b4b333c..6813ddcd25 100644 --- a/Library/Homebrew/test/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Livecheck do formula do homepage "https://brew.sh" url "https://brew.sh/test-0.0.1.tgz" - head "https://github.com/Homebrew/brew.git" + head "https://github.com/Homebrew/brew.git", branch: "main" end end let(:livecheck_f) { described_class.new(f.class) } diff --git a/Library/Homebrew/test/rubocops/components_redundancy_spec.rb b/Library/Homebrew/test/rubocops/components_redundancy_spec.rb index e65e31ae80..8e2b5076e6 100644 --- a/Library/Homebrew/test/rubocops/components_redundancy_spec.rb +++ b/Library/Homebrew/test/rubocops/components_redundancy_spec.rb @@ -25,7 +25,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do it "reports an offense if both `head` and `head do` are present" do expect_offense(<<~RUBY) class Foo < Formula - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" head do ^^^^^^^ FormulaAudit/ComponentsRedundancy: `head` and `head do` should not be simultaneously present # stuff @@ -50,7 +50,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do it "reports no offenses if `stable do` is present with a `head` method" do expect_no_offenses(<<~RUBY) class Foo < Formula - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" stable do # stuff @@ -92,7 +92,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do it "reports no offenses if `stable do` is present with `url` and `depends_on`" do expect_no_offenses(<<~RUBY) class Foo < Formula - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "trunk" stable do url "https://brew.sh/foo-1.0.tgz" @@ -109,6 +109,7 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do head do url "https://brew.sh/foo.git" + branch "develop" depends_on "bar" end end diff --git a/Library/Homebrew/test/utils/ast/formula_ast_spec.rb b/Library/Homebrew/test/utils/ast/formula_ast_spec.rb index e97a307364..09492ac1a2 100644 --- a/Library/Homebrew/test/utils/ast/formula_ast_spec.rb +++ b/Library/Homebrew/test/utils/ast/formula_ast_spec.rb @@ -193,6 +193,7 @@ RSpec.describe Utils::AST::FormulaAST do head do url "https://brew.sh/foo.git" + branch "develop" end end RUBY @@ -205,6 +206,7 @@ RSpec.describe Utils::AST::FormulaAST do head do url "https://brew.sh/foo.git" + branch "develop" end end RUBY @@ -355,7 +357,7 @@ RSpec.describe Utils::AST::FormulaAST do described_class.new <<~RUBY.chomp class Foo < Formula url "https://brew.sh/foo-1.0.tar.gz" - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" end RUBY end @@ -364,7 +366,7 @@ RSpec.describe Utils::AST::FormulaAST do <<~RUBY.chomp class Foo < Formula url "https://brew.sh/foo-1.0.tar.gz" - head "https://brew.sh/foo.git" + head "https://brew.sh/foo.git", branch: "develop" bottle do sha256 "f7b1fc772c79c20fddf621ccc791090bc1085fcef4da6cca03399424c66e06ca" => :sierra @@ -387,6 +389,7 @@ RSpec.describe Utils::AST::FormulaAST do head do url "https://brew.sh/foo.git" + branch "develop" end end RUBY @@ -403,6 +406,7 @@ RSpec.describe Utils::AST::FormulaAST do head do url "https://brew.sh/foo.git" + branch "develop" end end RUBY diff --git a/docs/Formula-Cookbook.md b/docs/Formula-Cookbook.md index 37f7a4b252..cc2f2feb88 100644 --- a/docs/Formula-Cookbook.md +++ b/docs/Formula-Cookbook.md @@ -841,7 +841,7 @@ end Formulae can specify an alternate download for the upstream project's development/cutting-edge source (e.g. `master`/`main`/`trunk`) using [`head`](https://rubydoc.brew.sh/Formula#head-class_method), which can be activated by passing `--HEAD` when installing. Specifying it is done in the same manner as [`url`](https://rubydoc.brew.sh/Formula#url-class_method), with added conventions for fetching from version control repositories: -* Git repositories need `branch:` specified to fetch a branch other than "master". If the repository is very large, specify `only_path` to [limit the checkout to one path](Cask-Cookbook.md#git-urls). +* Git repositories **must always** specify `branch:`. If the repository is very large, specify `only_path` to [limit the checkout to one path](Cask-Cookbook.md#git-urls). ```sh head "https://github.com/some/package.git", branch: "main" From 05b27aa847f673da47aa9c91fbb79e208cc3f819 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sun, 3 Aug 2025 22:52:05 +0100 Subject: [PATCH 2/3] Disallow `head do` blocks with only `url` and `branch` - Since `head` must now specify a url and branch, the `head do` block with only these stanzas can be condensed to the single-line `head "url", branch: "branch"` format. --- .../Homebrew/rubocops/components_redundancy.rb | 7 ++++--- .../test/rubocops/components_redundancy_spec.rb | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Library/Homebrew/rubocops/components_redundancy.rb b/Library/Homebrew/rubocops/components_redundancy.rb index 724f0af7bf..4a203ce17a 100644 --- a/Library/Homebrew/rubocops/components_redundancy.rb +++ b/Library/Homebrew/rubocops/components_redundancy.rb @@ -13,7 +13,7 @@ module RuboCop # - `bottle :unneeded`/`:disable` and `bottle do` should not be simultaneously present # - `stable do` should not be present without a `head` spec # - `stable do` should not be present with only `url|checksum|mirror|version` - # - `head do` should not be present with only `url` + # - `head do` should not be present with only `url|branch` class ComponentsRedundancy < FormulaCop HEAD_MSG = "`head` and `head do` should not be simultaneously present" BOTTLE_MSG = "`bottle :modifier` and `bottle do` should not be simultaneously present" @@ -54,8 +54,9 @@ module RuboCop head_block = find_block(body_node, :head) if head_block && !head_block.body.nil? child_nodes = head_block.body.begin_type? ? head_block.body.child_nodes : [head_block.body] - if child_nodes.all? { |n| n.send_type? && n.method_name == :url } - problem "`head do` should not be present with only `url`" + shorthand_head_methods = [:url, :branch] + if child_nodes.all? { |n| n.send_type? && shorthand_head_methods.include?(n.method_name) } + problem "`head do` should not be present with only #{shorthand_head_methods.join("/")}" end end diff --git a/Library/Homebrew/test/rubocops/components_redundancy_spec.rb b/Library/Homebrew/test/rubocops/components_redundancy_spec.rb index 8e2b5076e6..73b66318c9 100644 --- a/Library/Homebrew/test/rubocops/components_redundancy_spec.rb +++ b/Library/Homebrew/test/rubocops/components_redundancy_spec.rb @@ -82,13 +82,26 @@ RSpec.describe RuboCop::Cop::FormulaAudit::ComponentsRedundancy do end head do - ^^^^^^^ FormulaAudit/ComponentsRedundancy: `head do` should not be present with only `url` + ^^^^^^^ FormulaAudit/ComponentsRedundancy: `head do` should not be present with only url/branch url "https://brew.sh/foo.git" end end RUBY end + it "reports an offense if `head do` is present with only `url` and `branch`" do + expect_offense(<<~RUBY) + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + + head do + ^^^^^^^ FormulaAudit/ComponentsRedundancy: `head do` should not be present with only url/branch + url "https://brew.sh/foo.git", branch: "develop" + end + end + RUBY + end + it "reports no offenses if `stable do` is present with `url` and `depends_on`" do expect_no_offenses(<<~RUBY) class Foo < Formula From d0e9a2d7d66df2de655e7f56fae5f3aa81ebc660 Mon Sep 17 00:00:00 2001 From: Issy Long Date: Sun, 10 Aug 2025 21:46:53 +0100 Subject: [PATCH 3/3] Always suggest a HEAD branch name if we can find one - If a HEAD branch name isn't specified at all, then the user probably wants to shortcut adding one by being told what the default branch for the repo is. Otherwise they have to click the URL, look at the GitHub UI, then type the branch name into `branch: "foo"` syntax. --- Library/Homebrew/resource_auditor.rb | 11 +++---- Library/Homebrew/test/formula_auditor_spec.rb | 33 ++++++++++++++----- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Library/Homebrew/resource_auditor.rb b/Library/Homebrew/resource_auditor.rb index b3f2663f1c..0a6a9f83df 100644 --- a/Library/Homebrew/resource_auditor.rb +++ b/Library/Homebrew/resource_auditor.rb @@ -178,23 +178,22 @@ module Homebrew end def audit_head_branch + return unless @online return if spec_name != :head return if specs[:tag].present? return if specs[:revision].present? # Skip `resource` URLs as they use SHAs instead of branch specifiers. return if name != owner.name return unless url.end_with?(".git") - - problem "Git `head` URL must specify a branch name" if specs[:branch].blank? - - return unless @online return unless Utils::Git.remote_exists?(url) detected_branch = Utils.popen_read("git", "ls-remote", "--symref", url, "HEAD") .match(%r{ref: refs/heads/(.*?)\s+HEAD})&.to_a&.second - return if detected_branch.blank? || detected_branch == specs[:branch] - problem "Detected a default branch \"#{detected_branch}\", not \"#{specs[:branch]}\"" + message = "Git `head` URL must specify a branch name" + message += " - try `branch: \"#{detected_branch}\"`" if detected_branch.present? + + problem message if specs[:branch].blank? || detected_branch != specs[:branch] end def problem(text) diff --git a/Library/Homebrew/test/formula_auditor_spec.rb b/Library/Homebrew/test/formula_auditor_spec.rb index 5b5124891d..81bf79b8ff 100644 --- a/Library/Homebrew/test/formula_auditor_spec.rb +++ b/Library/Homebrew/test/formula_auditor_spec.rb @@ -715,16 +715,17 @@ RSpec.describe Homebrew::FormulaAuditor do end it "requires `branch:` to be specified for Git head URLs" do - fa = formula_auditor "foo", <<~RUBY + fa = formula_auditor "foo", <<~RUBY, online: true class Foo < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" - head "https://github.com/example/foo.git" + head "https://github.com/Homebrew/homebrew-test-bot.git" end RUBY fa.audit_specs - expect(fa.problems.first[:message]).to match("Git `head` URL must specify a branch name") + # This is `.last` because the first problem is the unreachable stable URL. + expect(fa.problems.last[:message]).to match("Git `head` URL must specify a branch name") end it "suggests a detected default branch for Git head URLs" do @@ -732,17 +733,31 @@ RSpec.describe Homebrew::FormulaAuditor do class Foo < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" - head "https://github.com/Homebrew/homebrew-core.git", branch: "master" + head "https://github.com/Homebrew/homebrew-test-bot.git", branch: "master" + end + RUBY + + message = "Git `head` URL must specify a branch name - try `branch: \"main\"`" + fa.audit_specs + # This is `.last` because the first problem is the unreachable stable URL. + expect(fa.problems.last[:message]).to match(message) + end + + it "ignores a pre-existing correct HEAD branch name" do + fa = formula_auditor "foo", <<~RUBY, online: true + class Foo < Formula + url "https://brew.sh/foo-1.0.tgz" + sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" + head "https://github.com/Homebrew/homebrew-test-bot.git", branch: "main" end RUBY fa.audit_specs - # This is `.last` because the first problem is the unreachable stable URL. - expect(fa.problems.last[:message]).to match('Detected a default branch "main", not "master"') + expect(fa.problems).not_to match("Git `head` URL must specify a branch name") end it "ignores `branch:` for non-Git head URLs" do - fa = formula_auditor "foo", <<~RUBY + fa = formula_auditor "foo", <<~RUBY, online: true class Foo < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" @@ -755,7 +770,7 @@ RSpec.describe Homebrew::FormulaAuditor do end it "ignores `branch:` for `resource` URLs" do - fa = formula_auditor "foo", <<~RUBY + fa = formula_auditor "foo", <<~RUBY, online: true class Foo < Formula url "https://brew.sh/foo-1.0.tgz" sha256 "31cccfc6630528db1c8e3a06f6decf2a370060b982841cfab2b8677400a5092e" @@ -768,7 +783,7 @@ RSpec.describe Homebrew::FormulaAuditor do RUBY fa.audit_specs - expect(fa.problems).to be_empty + expect(fa.problems).not_to match("Git `head` URL must specify a branch name") end it "allows versions with no throttle rate" do