Module: Toys::CI::Mixin
- Includes:
- Mixin
- Defined in:
- lib/toys/ci/mixin.rb
Overview
A mixin that provides methods useful for implementing CI tools.
This mixin is a lower-level mechanism that depends on you to write your own run method and define any needed flags. For a more batteries-included experience, consider Template, which does that work for you.
To implement a CI tool using this mixin, you will:
- Include this mixin
- Call #toys_ci_init to initialize the tool
- Make calls to various
toys_ci_*_jobmethods to run CI jobs - Call #toys_ci_report_results to report final results
This mixin adds various public and private methods, and several instance
variables to the tool. All added method and instance variable names begin
with toys_ci_, so avoid that prefix for any other methods and variables
you are using in your tool.
Instance Attribute Summary collapse
-
#toys_ci_failed_jobs ⇒ Array<String>
readonly
The names of the failed jobs so far.
-
#toys_ci_skipped_jobs ⇒ Array<String>
readonly
The names of the skipped jobs so far.
-
#toys_ci_successful_jobs ⇒ Array<String>
readonly
The names of the successful jobs so far.
Instance Method Summary collapse
-
#toys_ci_cmd_job(name, cmd, trigger_paths: nil, env: nil, chdir: nil) ⇒ :success, ...
Run a CI job implemented by an external process, and record the results.
-
#toys_ci_github_event_base_sha ⇒ String?
Look for environment variables set by a GitHub workflow, and attempt to extract a suitable change base.
-
#toys_ci_init(fail_fast: false, limit_by_changes_since: nil) ⇒ self
Initialize the CI tool.
-
#toys_ci_job(name, trigger_paths: nil, &block) ⇒ :success, ...
Run a CI job implemented by a block, and record the results.
-
#toys_ci_report_results(exit: true) ⇒ Integer
Print out a final report of the results, including a summary of the failed jobs.
-
#toys_ci_tool_job(name, tool, trigger_paths: nil, env: nil, chdir: nil) ⇒ :success, ...
Run a CI job implemented by a tool, and record the results.
Instance Attribute Details
#toys_ci_failed_jobs ⇒ Array<String> (readonly)
Returns The names of the failed jobs so far.
253 254 255 |
# File 'lib/toys/ci/mixin.rb', line 253 def toys_ci_failed_jobs @toys_ci_failed_jobs end |
#toys_ci_skipped_jobs ⇒ Array<String> (readonly)
Returns The names of the skipped jobs so far.
263 264 265 |
# File 'lib/toys/ci/mixin.rb', line 263 def toys_ci_skipped_jobs @toys_ci_skipped_jobs end |
#toys_ci_successful_jobs ⇒ Array<String> (readonly)
Returns The names of the successful jobs so far.
258 259 260 |
# File 'lib/toys/ci/mixin.rb', line 258 def toys_ci_successful_jobs @toys_ci_successful_jobs end |
Instance Method Details
#toys_ci_cmd_job(name, cmd, trigger_paths: nil, env: nil, chdir: nil) ⇒ :success, ...
Run a CI job implemented by an external process, and record the results.
166 167 168 169 170 171 172 173 |
# File 'lib/toys/ci/mixin.rb', line 166 def toys_ci_cmd_job(name, cmd, trigger_paths: nil, env: nil, chdir: nil) toys_ci_job(name, trigger_paths: trigger_paths) do opts = {name: name} opts[:env] = env if env opts[:chdir] = chdir if chdir exec(cmd, **opts).success? end end |
#toys_ci_github_event_base_sha ⇒ String?
Look for environment variables set by a GitHub workflow, and attempt to extract a suitable change base. Returns a git SHA, or nil if one could not be obtained from the current environment.
This may read the GITHUB_EVENT_NAME and GITHUB_EVENT_PATH
environment variables, and may also read the event payload file if
found. However, the exact logic is not specified.
The result can be passed to the :limit_by_changes_since argument of
#toys_ci_init.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/toys/ci/mixin.rb', line 98 def toys_ci_github_event_base_sha event_path = ::ENV["GITHUB_EVENT_PATH"].to_s if event_path.empty? logger.info("GITHUB_EVENT_PATH is empty or unset; cannot determine event payload file") return nil end event_payload = toys_ci_read_event_payload_file(event_path) return nil unless event_payload event_name = ::ENV["GITHUB_EVENT_NAME"] case event_name when "push" logger.info("Getting change base from push event") event_payload["before"] when "pull_request" logger.info("Getting change base from pull_request event") event_payload.dig("pull_request", "base", "sha") else logger.info("Did not find a change base from event #{event_name.inspect}") nil end end |
#toys_ci_init(fail_fast: false, limit_by_changes_since: nil) ⇒ self
Initialize the CI tool. This must be called first before any other
toys_ci_ methods.
74 75 76 77 78 79 80 81 |
# File 'lib/toys/ci/mixin.rb', line 74 def toys_ci_init(fail_fast: false, limit_by_changes_since: nil) @toys_ci_fail_fast = fail_fast @toys_ci_changed_paths = toys_ci_find_changes_since(limit_by_changes_since) @toys_ci_successful_jobs = [] @toys_ci_failed_jobs = [] @toys_ci_skipped_jobs = [] self end |
#toys_ci_job(name, trigger_paths: nil, &block) ⇒ :success, ...
Run a CI job implemented by a block, and record the results.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/toys/ci/mixin.rb', line 192 def toys_ci_job(name, trigger_paths: nil, &block) unless defined?(@toys_ci_successful_jobs) raise ::Toys::ToolDefinitionError, "You must call toys_ci_init before running a job" end return :skipped unless toys_ci_check_trigger_paths(trigger_paths, name) puts("**** RUNNING: #{name}", :cyan, :bold) result = begin instance_exec(&block) rescue ::StandardError => e trace = e.backtrace write("#{trace.first}: ") puts("#{e.} (#{e.class})", :bold) Array(trace[1..]).each { |line| puts " from #{line}" } false end toys_ci_job_result(name, result) end |
#toys_ci_report_results(exit: true) ⇒ Integer
Print out a final report of the results, including a summary of the
failed jobs. By default, this will also exit and never return. You can
instead get the exit value by passing exit: false.
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/toys/ci/mixin.rb', line 220 def toys_ci_report_results(exit: true) # rubocop:disable Metrics/MethodLength unless defined?(@toys_ci_successful_jobs) raise ::Toys::ToolDefinitionError, "You must call toys_ci_init before reporting job results" end success_count = @toys_ci_successful_jobs.size failure_count = @toys_ci_failed_jobs.size skipped_count = @toys_ci_skipped_jobs.size total_job_count = success_count + failure_count + skipped_count result = if total_job_count.zero? puts("**** CI: NO JOBS REQUESTED", :red, :bold) puts("Try passing --help to see how to activate CI jobs.") 2 elsif failure_count.positive? puts("**** CI: SKIPPED #{skipped_count} OF #{total_job_count} JOBS", :bold) unless skipped_count.zero? puts("**** CI: FAILED #{failure_count} OF #{success_count + failure_count} RUNNABLE JOBS:", :red, :bold) @toys_ci_failed_jobs.each { |name| puts(name, :red) } 1 elsif success_count.positive? puts("**** CI: SKIPPED #{skipped_count} OF #{total_job_count} JOBS", :bold) unless skipped_count.zero? puts("**** CI: ALL #{success_count} RUNNABLE JOBS SUCCEEDED", :green, :bold) 0 else puts("**** CI: ALL #{skipped_count} JOBS SKIPPED", :yellow, :bold) 0 end self.exit(result) if exit result end |
#toys_ci_tool_job(name, tool, trigger_paths: nil, env: nil, chdir: nil) ⇒ :success, ...
Run a CI job implemented by a tool, and record the results.
139 140 141 142 143 144 145 146 |
# File 'lib/toys/ci/mixin.rb', line 139 def toys_ci_tool_job(name, tool, trigger_paths: nil, env: nil, chdir: nil) toys_ci_job(name, trigger_paths: trigger_paths) do opts = {name: name} opts[:env] = env if env opts[:chdir] = chdir if chdir exec_separate_tool(tool, **opts).success? end end |