Module: Kettle::Dev::CIHelpers
- Defined in:
- lib/kettle/dev/ci_helpers.rb
Overview
CI-related helper functions used by Rake tasks and release tooling.
This module only exposes module-functions (no instance state) and is intentionally small so it can be required by both Rake tasks and the kettle-release executable.
Class Method Summary collapse
-
.current_branch ⇒ String?
Current git branch name, or nil when not in a repository.
-
.default_token ⇒ String?
Default GitHub token sourced from environment.
-
.exclusions ⇒ Array<String>
List of workflow files to exclude from interactive menus and checks.
-
.failed?(run) ⇒ Boolean
Whether a run has completed with a non-success conclusion.
-
.latest_run(owner:, repo:, workflow_file:, branch: nil, token: default_token) ⇒ Hash{String=>String,Integer}?
Fetch latest workflow run info for a given workflow and branch via GitHub API.
-
.project_root ⇒ String
Determine the project root directory.
-
.repo_info ⇒ Array(String, String)?
Parse the GitHub owner/repo from the configured origin remote.
-
.success?(run) ⇒ Boolean
Whether a run has completed successfully.
-
.workflows_list(root = project_root) ⇒ Array<String>
List workflow YAML basenames under .github/workflows at the given root.
Class Method Details
.current_branch ⇒ String?
Current git branch name, or nil when not in a repository.
54 55 56 57 |
# File 'lib/kettle/dev/ci_helpers.rb', line 54 def current_branch out, status = Open3.capture2("git", "rev-parse", "--abbrev-ref", "HEAD") status.success? ? out.strip : nil end |
.default_token ⇒ String?
Default GitHub token sourced from environment.
166 167 168 |
# File 'lib/kettle/dev/ci_helpers.rb', line 166 def default_token ENV["GITHUB_TOKEN"] || ENV["GH_TOKEN"] end |
.exclusions ⇒ Array<String>
List of workflow files to exclude from interactive menus and checks.
For reference…
A list of all worlflows,
with each marked relative to if they exist in this repo,
or at the top of the README marked.
- ancient (+)
- auto-assign.yml (-)
- codeql-analysis.yml (-)
- coverage.yml (+)
- current.yml (+)
- danger.yml (x)
- dependency-review.yml (-)
- discord-notifier.yml (-)
- heads.yml (+)
- jruby.yml (+)
- legacy.yml (+)
- locked_deps.yml (+)
- opencollective.yml (-)
- style.yml (+)
- supported.yml (+)
- truffle.yml (+)
- unlocked_deps.yml (+)
- unsupported.yml (+)
All those marked as (-) or (x) are excluded from interactive menus and checks. The (x) exist because they may be common in other repos.
108 109 110 111 112 113 114 115 116 117 |
# File 'lib/kettle/dev/ci_helpers.rb', line 108 def exclusions %w[ auto-assign.yml codeql-analysis.yml danger.yml dependency-review.yml discord-notifier.yml opencollective.yml ] end |
.failed?(run) ⇒ Boolean
Whether a run has completed with a non-success conclusion.
160 161 162 |
# File 'lib/kettle/dev/ci_helpers.rb', line 160 def failed?(run) run && run["status"] == "completed" && run["conclusion"] && run["conclusion"] != "success" end |
.latest_run(owner:, repo:, workflow_file:, branch: nil, token: default_token) ⇒ Hash{String=>String,Integer}?
Fetch latest workflow run info for a given workflow and branch via GitHub API.
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/kettle/dev/ci_helpers.rb', line 127 def latest_run(owner:, repo:, workflow_file:, branch: nil, token: default_token) return unless owner && repo b = branch || current_branch return unless b uri = URI("https://api.github.com/repos/#{owner}/#{repo}/actions/workflows/#{workflow_file}/runs?branch=#{URI.encode_www_form_component(b)}&per_page=1") req = Net::HTTP::Get.new(uri) req["User-Agent"] = "kettle-dev/ci-helpers" req["Authorization"] = "token #{token}" if token && !token.empty? res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) } return unless res.is_a?(Net::HTTPSuccess) data = JSON.parse(res.body) run = data["workflow_runs"]&.first return unless run { "status" => run["status"], "conclusion" => run["conclusion"], "html_url" => run["html_url"], "id" => run["id"], } rescue StandardError nil end |
.project_root ⇒ String
Determine the project root directory.
Prefers the directory Rake was invoked from (Rake.application.original_dir) so that tasks shipped with this gem operate relative to the host project. Falls back to the current working directory when Rake context is absent.
25 26 27 28 29 30 31 32 33 |
# File 'lib/kettle/dev/ci_helpers.rb', line 25 def project_root # Too difficult to test every possible branch here, so ignoring # :nocov: dir = if defined?(Rake) && Rake&.application&.respond_to?(:original_dir) Rake.application.original_dir end # :nocov: dir || Dir.pwd end |
.repo_info ⇒ Array(String, String)?
Parse the GitHub owner/repo from the configured origin remote.
Supports SSH (git@github.com:owner/repo(.git)) and HTTPS (github.com/owner/repo(.git)) forms.
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/kettle/dev/ci_helpers.rb', line 41 def repo_info out, status = Open3.capture2("git", "config", "--get", "remote.origin.url") return unless status.success? url = out.strip if url =~ %r{git@github.com:(.+?)/(.+?)(\.git)?$} [Regexp.last_match(1), Regexp.last_match(2).sub(/\.git\z/, "")] elsif url =~ %r{https://github.com/(.+?)/(.+?)(\.git)?$} [Regexp.last_match(1), Regexp.last_match(2).sub(/\.git\z/, "")] end end |
.success?(run) ⇒ Boolean
Whether a run has completed successfully.
153 154 155 |
# File 'lib/kettle/dev/ci_helpers.rb', line 153 def success?(run) run && run["status"] == "completed" && run["conclusion"] == "success" end |
.workflows_list(root = project_root) ⇒ Array<String>
List workflow YAML basenames under .github/workflows at the given root.
Excludes maintenance workflows defined by #exclusions.
65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/kettle/dev/ci_helpers.rb', line 65 def workflows_list(root = project_root) workflows_dir = File.join(root, ".github", "workflows") files = if Dir.exist?(workflows_dir) Dir[File.join(workflows_dir, "*.yml")] + Dir[File.join(workflows_dir, "*.yaml")] else [] end basenames = files.map { |p| File.basename(p) } basenames = basenames.uniq - exclusions basenames.sort end |