diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d00f6bd08c..9e28bec589 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,22 @@ name: CI -on: pull_request +on: + pull_request: + workflow_dispatch: + inputs: + casks: + description: List of casks to audit (comma-separated) + required: true + skip-install: + description: Skip installation of casks + required: false + default: true + type: boolean + new-cask: + description: Apply new cask audit + required: false + default: false + type: boolean env: HOMEBREW_DEVELOPER: 1 @@ -38,7 +54,12 @@ jobs: - name: Generate CI matrix id: generate-matrix run: | - brew ruby -- "$(brew --repository homebrew/cask)/cmd/lib/generate-matrix.rb" "${{ github.event.pull_request.url }}" + if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]] + then + brew ruby -- "$(brew --repository homebrew/cask)/cmd/lib/generate-matrix.rb" ${{ github.event.inputs.skip_install && '--skip-install' }} ${{ github.event.inputs.new_cask && '--new-cask' }} --casks=${{ github.event.inputs.casks }} + else + brew ruby -- "$(brew --repository homebrew/cask)/cmd/lib/generate-matrix.rb" --url="${{ github.event.pull_request.url }}" + fi test: name: ${{ matrix.name }} diff --git a/cmd/lib/ci_matrix.rb b/cmd/lib/ci_matrix.rb index 60e51ca548..6acd2d397f 100644 --- a/cmd/lib/ci_matrix.rb +++ b/cmd/lib/ci_matrix.rb @@ -101,7 +101,7 @@ module CiMatrix end end - def self.generate(tap, labels: []) + def self.generate(tap, labels: [], cask_names: [], skip_install: false, new_cask: false) odie "This command must be run from inside a tap directory." unless tap tap.extend(ChangedFiles) @@ -123,16 +123,22 @@ module CiMatrix odie "Found Ruby files in wrong directory:\n#{ruby_files_in_wrong_directory.join("\n")}" end - modified_cask_files = changed_files[:modified_cask_files] + cask_files_to_check = if cask_names.any? + cask_names.map do |cask_name| + Cask::CaskLoader.load(cask_name).sourcefile_path + end + else + changed_files[:modified_cask_files] + end - jobs = modified_cask_files.count + jobs = cask_files_to_check.count odie "Maximum job matrix size exceeded: #{jobs}/#{MAX_JOBS}" if jobs > MAX_JOBS - modified_cask_files.flat_map do |path| + cask_files_to_check.flat_map do |path| cask_token = path.basename(".rb") audit_args = ["--online"] - audit_args << "--new-cask" if changed_files[:added_files].include?(path) + audit_args << "--new-cask" if changed_files[:added_files].include?(path) || new_cask audit_args << "--signing" @@ -167,7 +173,7 @@ module CiMatrix }, audit_args: audit_args + arch_args, fetch_args: arch_args, - skip_install: labels.include?("ci-skip-install") || !native_runner_arch, + skip_install: labels.include?("ci-skip-install") || !native_runner_arch || skip_install, skip_readall: !native_runner_arch, runner: runner.fetch(:name), } diff --git a/cmd/lib/generate-matrix.rb b/cmd/lib/generate-matrix.rb index 326f42dd18..3df5f0c337 100755 --- a/cmd/lib/generate-matrix.rb +++ b/cmd/lib/generate-matrix.rb @@ -2,52 +2,91 @@ require "tap" require "utils/github/api" - +require "cli/parser" require_relative "ci_matrix" -pr_url, = ARGV +module Homebrew + module_function -labels = if pr_url - pr = GitHub::API.open_rest(pr_url) - pr.fetch("labels").map { |l| l.fetch("name") } -else - [] -end + def generate_matrix_args + Homebrew::CLI::Parser.new do + description <<~EOS + Generate a GitHub Actions matrix for a given pull request URL or list of cask names. + EOS -tap = Tap.fetch(ENV.fetch("GITHUB_REPOSITORY")) + flag "--url=", + description: "URL of a pull request to generate a matrix for." + comma_array "--casks", + description: "Comma-separated list of casks to test." + switch "--skip-install", + description: "Skip installing casks" + switch "--new-cask", + description: "Run new cask checks" -runner = CiMatrix.random_runner[:name] -syntax_job = { - name: "syntax", - tap: tap.name, - runner: runner, - skip_readall: false, -} - -matrix = [syntax_job] - -unless labels.include?("ci-syntax-only") - cask_jobs = CiMatrix.generate(tap, labels: labels) - - if cask_jobs.any? - # If casks were changed, skip `audit` for whole tap. - syntax_job[:skip_audit] = true - - # If casks were cahnged, skip `readall` in the syntax job. - syntax_job[:skip_readall] = true - - # The syntax job only runs `style` at this point, which should work on Linux. - # Running on macOS is currently faster though, since `homebrew/cask` and - # `homebrew/core` are already tapped on macOS CI machines. - # syntax_job[:runner] = "ubuntu-latest" + conflicts "--url", "--casks" + end end - matrix += cask_jobs + def generate_matrix + args = generate_matrix_args.parse + + skip_install = args.skip_install? + new_cask = args.new_cask? + casks = args.casks if args.casks&.any? + + if args.url.present? + pr_url = args.url + + labels = if pr_url + pr = GitHub::API.open_rest(pr_url) + pr.fetch("labels").map { |l| l.fetch("name") } + else + [] + end + end + + tap = Tap.fetch(ENV.fetch("GITHUB_REPOSITORY")) + + runner = CiMatrix.random_runner[:name] + syntax_job = { + name: "syntax", + tap: tap.name, + runner: runner, + skip_readall: false, + } + + matrix = [syntax_job] + + unless labels&.include?("ci-syntax-only") + cask_jobs = if args.casks&.any? + CiMatrix.generate(tap, labels: labels, cask_names: casks, skip_install: skip_install, new_cask: new_cask) + else + CiMatrix.generate(tap, labels: labels, skip_install: skip_install, new_cask: new_cask) + end + + if cask_jobs.any? + # If casks were changed, skip `audit` for whole tap. + syntax_job[:skip_audit] = true + + # If casks were cahnged, skip `readall` in the syntax job. + syntax_job[:skip_readall] = true + + # The syntax job only runs `style` at this point, which should work on Linux. + # Running on macOS is currently faster though, since `homebrew/cask` and + # `homebrew/core` are already tapped on macOS CI machines. + # syntax_job[:runner] = "ubuntu-latest" + end + + matrix += cask_jobs + end + + syntax_job[:name] += " (#{syntax_job[:runner]})" + + puts JSON.pretty_generate(matrix) + File.open(ENV.fetch("GITHUB_OUTPUT"), "a") do |f| + f.puts "matrix=#{JSON.generate(matrix)}" + end + end end -syntax_job[:name] += " (#{syntax_job[:runner]})" - -puts JSON.pretty_generate(matrix) -File.open(ENV.fetch("GITHUB_OUTPUT"), "a") do |f| - f.puts "matrix=#{JSON.generate(matrix)}" -end +Homebrew.generate_matrix