๐ GitHub Actions Workflows
HyperShift uses GitHub Actions for lightweight CI checks that run on every pull request. These workflows complement the heavier Prow-based e2e tests by providing fast feedback on code quality, formatting, and documentation.
๐๏ธ Reusable Workflow Architecture
All GHA workflows follow a caller + reusable pattern:
- Caller workflow (e.g.,
lint.yaml) โ defines triggers (pull_request, branch filters) and delegates to a reusable workflow pinned at@main. - Reusable workflow (e.g.,
lint-reusable.yaml) โ contains the actual job steps. Triggered viaworkflow_calland optionally onpushtomainfor post-merge runs.
flowchart LR
subgraph "Caller (lint.yaml)"
A["on: pull_request"] --> B["uses: ...lint-reusable.yaml@main"]
end
subgraph "Reusable (lint-reusable.yaml)"
B --> C["on: workflow_call"]
C --> D["Checkout + Run lint"]
end
This pattern provides:
- โ Consistency โ all PR and push workflows share the same job definitions.
- ๐ง Maintainability โ job logic is defined once in the reusable workflow and updated in a single place.
- ๐ Security โ callers pin reusable workflows to
@main, reducing the risk of PRs altering reusable job logic. Caller workflows are protected by branch protection rules and CODEOWNERS.
๐ Workflows
The PR validation workflows run on self-hosted ARC runners. Most target main and release-4.22; only the OCP and vanilla Kubernetes envtest workflows also target release-5.0.
Pull request callers resolve their reusable workflows from main, while post-merge runs use the reusable workflow stored on the pushed branch. Keep branch-local matrices synchronized with main; release-5.0 envtests must include Kubernetes 1.36 for consistent pull request and post-merge coverage.
๐งน Code Quality
| Caller | Reusable | Purpose |
|---|---|---|
codespell.yaml |
codespell-reusable.yaml |
Spell checking across the codebase |
gitlint.yaml |
gitlint-reusable.yaml |
Commit message format validation |
lint.yaml |
lint-reusable.yaml |
Go linting via golangci-lint |
verify.yaml |
verify-reusable.yaml |
Full verification (make verify) |
๐งช Testing
| Caller | Reusable | Purpose |
|---|---|---|
test.yaml |
test-reusable.yaml |
Unit tests with race detection and Codecov upload |
envtest-ocp.yaml |
envtest-ocp-reusable.yaml |
CRD validation tests against OpenShift k8s versions |
envtest-kube.yaml |
envtest-kube-reusable.yaml |
CRD validation tests against vanilla k8s versions |
๐ Documentation
| Caller | Reusable | Purpose |
|---|---|---|
docs-build.yaml |
docs-build-reusable.yaml |
Build Zensical site in strict mode |
Info
The docs-deploy.yaml workflow is not a reusable workflow pair โ it triggers via workflow_run after the Docs Build completes to deploy the preview. See Documentation Preview for details.
๐ง Other
| Caller | Reusable | Purpose |
|---|---|---|
cpo-container-sync.yaml |
cpo-container-sync-reusable.yaml |
Validate CPO container image references are in sync |
dependabot-commit-fix.yaml |
dependabot-commit-fix-reusable.yaml |
Rewrite dependabot commit messages to pass gitlint |
gocacheprog-test.yaml |
gocacheprog-test-reusable.yaml |
Tests for the contrib/ci/gocacheprog build cache tool (path-filtered) |
validate-cpo-overrides.yaml |
โ | Validate CPO override images contain the PRs claimed in the PR description |
Note
The sync-community-fork.yaml workflow runs on push to main only (not on PRs) and does not use the reusable pattern. See Sync Community Fork for details.
โ Adding a New Workflow
To add a new GHA workflow:
- Create the reusable workflow (e.g.,
my-check-reusable.yaml) withon: workflow_call. This is where all the job logic lives. - Create the caller workflow (e.g.,
my-check.yaml) that uses the reusable workflow pinned at@main. - Add branch filters for
mainand each release branch where the workflow is intended to run. Do not assume every workflow should target every release branch. - Use
arc-runner-setas the runner.
Post-merge runs
If your workflow should also run after PRs merge to main (e.g., for Codecov baseline uploads or post-merge validation), add on: push triggers to the reusable workflow, not the caller. This lets the reusable workflow run directly on push events without needing a separate caller.
Why callers pin to @main
Callers reference the reusable workflow at @main (e.g., uses: openshift/hypershift/.github/workflows/my-check-reusable.yaml@main). This means a PR cannot modify the reusable workflow logic that runs against itself โ it always executes the version from main. This is a deliberate security measure: it prevents a PR from weakening checks to make itself pass.
Implication for new workflows
When you add a new reusable workflow, the caller in the same PR will not be able to reference it until it lands on main. You'll need to merge the reusable workflow first (or together with the caller, accepting that the first PR run will use a stale/missing reference).
Example caller workflow
name: My Check
on:
pull_request:
branches:
- main
- release-4.22
jobs:
my-check:
uses: openshift/hypershift/.github/workflows/my-check-reusable.yaml@main
permissions:
contents: read
Example reusable workflow with post-merge support
name: My Check (Reusable)
on:
workflow_call:
push:
branches:
- main
- release-4.22
permissions:
contents: read
jobs:
my-check:
name: My Check
runs-on: arc-runner-set
timeout-minutes: 60
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- run: echo "Run your check here"