The fundamental unit of work in SaturnCI is a job. A job is a Ruby script that runs inside an environment. Workflows are what start jobs.
Defining a job
A job lives in a directory under .saturnci/jobs/. The
directory holds a config.yml, which names the environment
the job runs in, and a script named after the job. Here is a job named
hello_world:
# .saturnci/jobs/hello_world/config.yml
environment: ruby
# .saturnci/jobs/hello_world/hello_world_job.rb
class HelloWorldJob
def perform
puts "hello world"
end
end
if $PROGRAM_NAME == __FILE__
HelloWorldJob.new.perform
end
SaturnCI runs the script directly, so the $PROGRAM_NAME
guard is what actually invokes the job. The job passes or fails on the
script's exit status.
A job that shells out can exit on the result of the command:
# .saturnci/jobs/rubocop/rubocop_job.rb
class RubocopJob
def perform
system("bundle exec rubocop")
end
end
if $PROGRAM_NAME == __FILE__
exit RubocopJob.new.perform
end
Starting a job
Jobs are started from your workflow:
hello_world_job_run = workflow_run.job_runs.create(
job_name: "hello_world",
task_adapter_name: "shell",
idempotent: true
)
hello_world_job_run.start
Task adapters
Every job run names a task adapter, which is what SaturnCI uses to run the job and interpret its output.
-
shell— runs the job's script. This is the adapter for deployments, linters, image builds, and anything else that passes or fails as a whole. -
rails_rspec— runs a Rails app's RSpec suite, splitting it across test runners and reporting individual test results. Use this one withworkflow_run.test_suite_runs.create; see test suite jobs. -
rails_minitest— the same, for Minitest.
Test suite jobs
A test suite job has no script and no config.yml. Everything
that defines it is on the create call in your workflow: the environment
it runs in, the Docker Compose service in that environment that runs the
tests, and the command that runs them.
test_suite_run = workflow_run.test_suite_runs.create(
job_name: "test_suite",
task_adapter_name: "rails_rspec",
environment_name: "rspec",
service_name: "saturnci_test_app",
command: "bundle exec rspec",
idempotent: true
)
test_suite_run.start
SaturnCI runs the command once with --dry-run to list the
examples, splits them across test runners, and then runs the command on
each runner's share, adding the flags it needs to collect results.
Anything that invokes RSpec works as the command, e.g.
bundle exec appraisal rails-7.1 rspec.