diff --git a/Library/Homebrew/rubocops/cask/url.rb b/Library/Homebrew/rubocops/cask/url.rb new file mode 100644 index 00000000000000..23375ea374680c --- /dev/null +++ b/Library/Homebrew/rubocops/cask/url.rb @@ -0,0 +1,37 @@ +# typed: true +# frozen_string_literal: true + +require "forwardable" + +module RuboCop + module Cop + module Cask + # This cop checks that a cask's `url` stanza is formatted correctly. + class Url < Base + extend AutoCorrector + extend Forwardable + include OnUrlStanza + + def on_url_stanza(stanza) + return if stanza.stanza_node.block_type? + + hash_node = stanza.stanza_node.last_argument + return unless hash_node.hash_type? + + hash_node.each_pair do |key_node, value_node| + next unless key_node.source == "verified" + next unless value_node.str_type? + next unless value_node.source.start_with?("\"https:/", "\"http:/") + + add_offense( + value_node.source_range, + message: "Verified URL parameter value should not start with https:// or http://.", + ) do |corrector| + corrector.replace(value_node.source_range, value_node.source.gsub(%r{^"https?://}, "\"")) + end + end + end + end + end + end +end diff --git a/Library/Homebrew/rubocops/rubocop-cask.rb b/Library/Homebrew/rubocops/rubocop-cask.rb index ed7b7fe74959e4..2a3a9cefd35f1a 100644 --- a/Library/Homebrew/rubocops/rubocop-cask.rb +++ b/Library/Homebrew/rubocops/rubocop-cask.rb @@ -18,5 +18,6 @@ require_relative "cask/on_system_conditionals" require_relative "cask/stanza_order" require_relative "cask/stanza_grouping" +require_relative "cask/url" require_relative "cask/url_legacy_comma_separators" require_relative "cask/variables" diff --git a/Library/Homebrew/test/rubocops/cask/url_spec.rb b/Library/Homebrew/test/rubocops/cask/url_spec.rb new file mode 100644 index 00000000000000..390d0d7c558ac2 --- /dev/null +++ b/Library/Homebrew/test/rubocops/cask/url_spec.rb @@ -0,0 +1,47 @@ +# typed: false +# frozen_string_literal: true + +require "rubocops/rubocop-cask" +require "test/rubocops/cask/shared_examples/cask_cop" + +describe RuboCop::Cop::Cask::Url do + include CaskCop + + subject(:cop) { described_class.new } + + context "when url 'verified' value does not start with a protocol" do + let(:source) do + <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "example.com" + end + CASK + end + + include_examples "does not report any offenses" + end + + context "when url 'verified' value starts with a protocol" do + let(:source) do + <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "https://example.com" + end + CASK + end + + let(:expected_offenses) do + [{ + message: "Verified URL parameter value should not start with https:// or http://.", + severity: :convention, + line: 3, + column: 4, + source: "verified: \"https://example.com\"", + }] + end + + include_examples "reports offenses" + end +end