Custom Runners
The runs_on key of a workflow selects the CI runner that runs its plans and applies. On GitHub Actions it becomes the job's runs-on value. On GitLab CI it is a list of runner tags. Use it to:
- Run sensitive workloads on self-hosted runners, for security, compliance, or network reasons.
- Target runner labels or tags for specific hardware or preinstalled tools.
- Spread work across runner pools.
- Meet policies that require on-premises execution.
Without runs_on, Stategraph Orchestration runs on GitHub-hosted ubuntu-latest runners on GitHub. On GitLab, the job has no runner tags, so any runner that accepts untagged jobs can take it.
Configuration
Set runs_on on a workflow entry in .stategraph/config.yml. See the workflows reference. On GitHub, runs_on accepts any valid GitHub Actions runner specification:
workflows:
- tag_query: ""
runs_on: ubuntu-latest
On GitLab, write runs_on as a list of runner tags, even for a single tag, because the RUNS_ON pipeline input is an array.
Self-hosted runner
On GitHub, a single label can be a plain string:
workflows:
- tag_query: "production"
runs_on: self-hosted
plan:
- type: init
- type: plan
apply:
- type: init
- type: apply
Multiple labels
To match several labels on GitHub, or several tags on GitLab, use a list:
workflows:
- tag_query: "production"
runs_on: [self-hosted, linux, x64, gpu]
plan:
- type: init
- type: plan
Single label as a list
A single label can also be a list:
workflows:
- tag_query: ""
runs_on: ["self-hosted"]
Environment-specific runners
Give each environment its own runner selection, for example when environments have different security requirements:
workflows:
- tag_query: "dev"
runs_on: ubuntu-latest
plan:
- type: init
- type: plan
apply:
- type: init
- type: apply
- tag_query: "staging"
runs_on: [self-hosted, staging, linux]
plan:
- type: init
- type: plan
apply:
- type: init
- type: apply
- tag_query: "production"
runs_on: [self-hosted, production, secure, linux]
plan:
- type: init
- type: plan
apply:
- type: init
- type: apply
Development runs on GitHub-hosted runners, staging on self-hosted runners with the staging label, and production on a dedicated pool with the production and secure labels.
On GitLab, leave runs_on unset on an entry that can run on any runner that accepts untagged jobs:
workflows:
- tag_query: "dev"
- tag_query: "staging"
runs_on: [staging, linux]
- tag_query: "production"
runs_on: [production, secure, linux]
Development runs on any runner that accepts untagged jobs, staging on runners with the tags staging and linux, and production on runners with the tags production, secure, and linux.
CI file requirements
Orchestration sends the runs_on value of the matching workflow entry with each run that it starts. The CI file in your repository must pass it to the job.
GitHub
Orchestration passes the value as JSON in the runs_on input of the workflow dispatch. The standard .github/workflows/terrateam.yml declares that input with the default '"ubuntu-latest"', and sets runs-on: ${{ fromJSON(github.event.inputs.runs_on) }} on the job. GitHub reusable workflows shows the same input in a reusable workflow.
GitLab
Orchestration passes the value in the RUNS_ON pipeline input, only when runs_on is set.
- The
.gitlab-ci.ymlfrom the console declaresRUNS_ONunderspec.inputsas an array with an empty default. It passes the value to the included template as the runner tags. The Stategraph Cloud quickstart shows the full file. - If
runs_onis set and.gitlab-ci.ymldoes not declareRUNS_ON, the pipeline does not start. Orchestration then comments on the merge request with thespecandincludeblocks that the file needs.
Next steps
- Private runners: set up self-hosted GitHub Actions runners for Orchestration.
- Tags and tag queries: the
tag_queryvalues used above. - workflows reference