Module: CIRunner::TestRunFinder

Extended by:
TestRunFinder
Included in:
TestRunFinder
Defined in:
lib/ci_runner/test_run_finder.rb

Constant Summary collapse

GITHUB_ACTION =
"github-actions"

Instance Method Summary collapse

Instance Method Details

#detect_runner(ci_log) ⇒ Runners::MinitestRunner, Runners::RSpec

Try to guess which runner (Minitest, RSpec) was responsible for this log output.

The runner is the most important part of CI Runner. It’s what determine the failures for a CI log, as well as how to rerun those only.

Parameters:

  • ci_log (String)

    The log output from CI.

Returns:

Raises:

  • (Error)

    In case none of the runners could detect the log output.



103
104
105
106
107
108
109
110
111
# File 'lib/ci_runner/test_run_finder.rb', line 103

def detect_runner(ci_log)
  raise_if_not_found = lambda { raise(Error, "Couldn't detect the test runner") }

  runner = [Runners::MinitestRunner, Runners::RSpec].find(raise_if_not_found) do |runner|
    runner.match?(ci_log)
  end

  runner.new(ci_log)
end

#fetch_ci_checks(repository, commit, &block) ⇒ Array<Check::Base>

Makes a request to GitHub to retrieve the checks for a commit. Display a nice UI with a spinner while the user wait.

Parameters:

  • repository (String)

    The full repository name, including the owner (i.e. rails/rails)

  • commit (String)

    The Git commit that has been pushed to GitHub and for which we’ll retrieve the CI checks.

  • block (Proc, Lambda)

    A proc that will be called in case we can’t retrieve the CI Checks. This allows the CLI to prematurely exit and let the CLI::UI closes its frame.

Returns:

  • (Array<Check::Base>)

    Array filled with Check::Base subclasses.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/ci_runner/test_run_finder.rb', line 18

def fetch_ci_checks(repository, commit, &block)
  error = nil
  ci_checks = []
  title = "Fetching failed CI checks from GitHub for commit {{info:#{commit[..12]}}}"

  ::CLI::UI.spinner(title, auto_debrief: false) do
    ci_checks = github_ci(repository, commit)
    ci_checks += other_ci(repository, commit)
  rescue Client::Error, StandardError => e
    error = e

    ::CLI::UI::Spinner::TASK_FAILED
  end

  block.call(error) if error

  ci_checks
end

#find(ci_checks, run_name) ⇒ Check::Base

Find the CI check the user requested from the list of upstream checks. This method is useful only when the user passes the ‘–run-name` flag to `ci-runner`. This makes sure the CI check actually exists.

Parameters:

  • ci_checks (Array<Check::Base>)

    A list of CI checks.

  • run_name (String)

    The name of the CI run that the user would like to retry on its machine.

Returns:

  • (Check::Base)

    A single check run from the list of ci_checks

Raises:

  • (Error)

    If no CI checks with the given run_name could be found.

  • (Error)

    If the CI check was successfull. No point to continue as there should be no tests to rerun.



85
86
87
88
89
90
91
# File 'lib/ci_runner/test_run_finder.rb', line 85

def find(ci_checks, run_name)
  check_run = ci_checks.find { |check| check.name == run_name }
  raise(Error, no_check_message(ci_checks, run_name)) if check_run.nil?
  raise(Error, check_succeed(run_name)) unless check_run.failed?

  check_run
end

#github_ci(repository, commit) ⇒ Array<Check::Github>

Download the GitHub checks. This is used in case a project uses GitHub itself as its CI provider.

Parameters:

  • repository (String)

    The full repository name, including the owner (i.e. rails/rails)

  • commit (String)

    The Git commit that has been pushed to GitHub and for which we’ll retrieve the CI checks.

Returns:

See Also:



45
46
47
48
49
50
51
52
53
54
# File 'lib/ci_runner/test_run_finder.rb', line 45

def github_ci(repository, commit)
  github_client = Client::Github.new(Configuration::User.instance.github_token)
  ci_checks = github_client.check_runs(repository, commit)["check_runs"]

  ci_checks.filter_map do |check_run|
    next unless check_run.dig("app", "slug") == GITHUB_ACTION

    Check::Github.new(repository, commit, *check_run.values_at("name", "conclusion", "id"))
  end
end

#other_ci(repository, commit) ⇒ Array<Check::CircleCI, Check::Unsupported>

Download the Commit Statuses for this commit. Some CI provider (like GitHub or Buildkite), doesn’t use the GitHub Check API, but instead this API.

Parameters:

  • repository (String)

    The full repository name, including the owner (i.e. rails/rails)

  • commit (String)

    The Git commit that has been pushed to GitHub and for which we’ll retrieve the CI checks.

Returns:

See Also:



65
66
67
68
69
70
71
72
# File 'lib/ci_runner/test_run_finder.rb', line 65

def other_ci(repository, commit)
  github_client = Client::Github.new(Configuration::User.instance.github_token)
  commit_statuses = github_client.commit_statuses(repository, commit)

  commit_statuses.map do |commit_status|
    check_class_from_url(commit_status, repository, commit)
  end.compact
end