class GithubActions::JobRunner
Runs GitHub Actions job in a container locally
Attributes
Public Class Methods
constructor @param job [GithubActions::Job] the job to run @param image [String,nil] override the Docker image to use,
if `nil` it by default uses the image specified in the job
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 32 def initialize(job, image = nil) @job = job @image = image end
Public Instance Methods
run the job in a container @return [Boolean] ‘true` if all steps were successfully executed,
`false` otherwise
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 40 def run stage("Running \"#{job.name}\" job from file #{job.workflow.file}") start_container result = true job.steps.each do |step| result &= run_step(step) end print_result(result) container.stop result end
Private Instance Methods
replace the ${{ matrix.<value> }} placeholders in the image name
@param image_name [String] name of the Docker image @return [String] name with replaced values
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 88 def expand_name(image_name) image_name.gsub(/\$\{\{\s*matrix\.[^}]*\}\}/) do |subst| name = /\$\{\{\s*matrix\.([^}]*)\}\}/.match(subst)[1].strip value = job.matrix ? job.matrix[name] : subst # if the value is an Array use the first value by default replacement = value.is_a?(Array) ? value.first : value.to_s puts "Using ${{matrix.#{name}}} value: #{replacement.inspect}" replacement end end
Get the container configuration @return [Container] container which should run the job
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 68 def find_container # prefer the custom image if requested image_name = if image image elsif job.container.is_a?(String) job.container elsif job.container.is_a?(Hash) options = job.container["options"] job.container["image"] else abort "Unsupported container definition: #{job.container.inspect}" end Container.new(expand_name(image_name), options.to_s) end
print the job result @param success [Boolean] status of the job
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 117 def print_result(success) if success success("Job result: SUCCESS") else error("Job result: FAILURE!") end end
run a job step @param step [GithubActions::Step] the step to run @return [Boolean] ‘true` if the step succeeded, `false` otherwise
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 103 def run_step(step) info("Step \"#{step.name}\"") # run "uses" step if present run_uses_step(step.uses) if step.uses # run "run" step if present return true unless step.run container.run(step.run) end
workarounds for some special Javascript actions which are otherwise not supported in general @param uses [String] name of the “uses” action
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 128 def run_uses_step(uses) case uses when CHECKOUT_ACTION # emulate the Git checkout action, just copy the current checkout # into the current directory in the running container container.copy_current_dir when COVERALLS_ACTION # skip the coveralls action, do not send the code coverage report # when running locally info("Skipping the Coveralls step") else # this should actually never happen, we already checked for # the unsupported steps before starting the job raise "Unsupported action \"#{uses}\"" end end
pull the Docker image and start the container
# File lib/tasks/github_actions/github_actions/job_runner.rb, line 60 def start_container @container = find_container container.pull container.start end