GitHub Actions
GitHub Actions is GitHub's built-in continuous integration and delivery platform that automates the build, test, and deployment process directly from your repository.
For general GitHub Actions documentation, refer to the GitHub Actions Documentation.
For information about the CI workflow structure, jobs, and caching strategy, see the Continuous integration overview.
Onboarding
GitHub Actions onboarding is part of the project setup flow. See Set up continuous integration in the Installation guide and select GitHub Actions.
Maintenance
Update trigger branches
The workflow triggers on pushes and pull requests to specific branches defined
in the on.push.branches and on.pull_request.branches sections of
.github/workflows/build-test-deploy.yml:
Push triggers (direct pushes and merges):
| Pattern | Description |
|---|---|
production | Production environment branch |
main, master | Default development branches |
develop | Integration branch for ongoing work |
release/** | Release preparation branches (e.g., release/1.2.3, release/2023-04-17) |
hotfix/** | Urgent production fixes (e.g., hotfix/1.2.4, hotfix/2023-04-17) |
project/** | Long-lived project branches for large initiatives |
Pull request triggers (PRs targeting these branches):
| Pattern | Description |
|---|---|
| All push branches above | Same as push triggers |
feature/** | New feature branches (e.g., feature/login, feature/123-new-ui) |
bugfix/** | Non-urgent bug fix branches (e.g., bugfix/fix-auth, bugfix/456-crash) |
Short-lived branches like feature/** and bugfix/** only trigger CI through
pull requests, not on direct pushes.
To add or remove branches, update the push and pull_request sections
in the workflow file.
Security audit workflow
Security checks live in a second workflow, .github/workflows/audit.yml, which
triggers on the same branches and tags as the main workflow and can also be
started on demand from Actions → Security audit → Run workflow.
See Security audit for what it runs and how to make it block merges and deployments.
Update nightly database schedule
The nightly database job caches a fresh database dump for faster builds the next
day. To change when this runs, update the schedule.cron value (
cron format, UTC timezone):
schedule:
- cron: '0 18 * * *' # 6 PM UTC daily
Change runner size
For faster builds, you can use larger runners in the job configuration. Note that this may affect your GitHub billing:
runs-on: ubuntu-latest-4-cores # Options: ubuntu-latest, ubuntu-latest-4-cores, etc.
Larger runners also come with more disk, which matters for projects whose provisioning is disk-heavy. See Runner disk space.
Runner disk space
GitHub-hosted runners start with most of their root volume already consumed:
measured on one ubuntu-latest image, preinstalled software occupied 59 GB of
a 72 GB volume, leaving the job around 13 GB. Pulled container images, database
dumps, and every file created while provisioning share what is left.
Vortex keeps the build within that budget:
- The
buildanddatabasejobs printdf -hin a Report disk usage step, so the disk state is on the record for every run. - The Docker build cache and dangling images are pruned once the stack is up.
- The database dump is removed from the runner as soon as it has been copied into the container, so only one copy is held during provisioning.
Reclaim the preinstalled toolchains
The build and database jobs can remove the preinstalled toolchains no
Vortex job uses - GHCup, Swift, PowerShell, .NET and CodeQL - before doing
anything else. In the measurement above this freed about 15 GB in around 14
seconds, taking the job from roughly 13 GB of headroom to 28 GB.
The removal is destructive to the runner for the rest of the job, so it is off
by default. Turn it on by setting the CI_FREE_DISK_SPACE variable to 1 in
Settings → Secrets and variables → Actions → Variables. Leave it unset on a
project whose workflow runs a step that needs Haskell, Swift, PowerShell, .NET
or CodeQL.
Every figure here comes from one runner image at one point in time, and GitHub reissues that image regularly. Read the Report disk usage output of a recent run for the current numbers - if the reclaimed amount has shrunk, the path list needs revisiting.
Free even more space
With CI_FREE_DISK_SPACE enabled, the Android SDK is the single largest
remaining tree at about 10 GB, but removing it takes around 50 seconds. It
ships commented out in the workflow for that reason - uncomment the line in the
Free up disk space on the runner step of both the build and database
jobs to enable it:
set -- "$@" /host/usr/local/lib/android
The removal runs through a container that bind-mounts the runner's root filesystem, because the job itself runs in a container and cannot see the host's directories directly. This is also why the general-purpose disk-cleanup actions available on the Marketplace have no effect in a Vortex job.
When space still runs out
If a build dies during provisioning without reporting an error, suspect the disk and read the Report disk usage output. The most reliable fix is to reduce what has to fit: a sanitized dump or a database container image instead of a full dump. A larger runner also comes with more disk.
Change test parallelism
To speed up test execution, you can increase the number of parallel runners in the build job matrix. See Using a matrix for your jobs for more information:
strategy:
matrix:
instance: [0, 1, 2, 3] # Run tests across 4 containers
Every added container that runs Behat also needs a matching pN profile in
behat.yml. See Test parallelism for the full procedure,
how scenarios are balanced across containers, and how to move a tool onto a
different container.
Manual deployment
The workflow supports triggering deployments directly from the GitHub UI without
running the lint, database, or build jobs. Navigate to Actions → Database,
Build, Test and Deploy → Run workflow and provide:
| Input | Description |
|---|---|
deploy_target | Branch name (e.g., develop) or PR reference (e.g., PR-123, case-insensitive) |
override_db | Override the existing database in the deployment environment |
When deploy_target is set, all other jobs are skipped and only the deploy
job runs. For PR targets, the workflow resolves the PR's head branch and
commit SHA automatically.
When override_db is checked, the database in the existing deployment
environment will be overridden with a fresh copy taken from the production
environment.
Artifact-based deployments do not work with manual deploys as the build job is skipped.
Terminal access for debugging
The workflow includes a tmate session for debugging. Trigger a manual workflow
run with the Enable terminal session for CI jobs option checked to get SSH
connection details in the build logs. See action-tmate
for more information.
Adjust build timeout
If builds are timing out, increase the timeout-minutes value for long-running
steps:
- name: Long running task
run: ./scripts/long-task.sh
timeout-minutes: 60 # Default is 360 (6 hours)
Code coverage threshold
The workflow enforces a minimum code coverage threshold. If coverage falls below the threshold, the build fails.
Configure the threshold by setting the VORTEX_CI_CODE_COVERAGE_THRESHOLD
variable in Settings → Secrets and variables → Actions → Variables. Default
is 90 (percent).
Coverage reports are automatically posted as PR comments. Each new report
replaces the previous one - older comments are minimized to keep the PR
timeline clean. To disable this, set VORTEX_CI_CODE_COVERAGE_PR_COMMENT_SKIP
to 1.
Test results
PHPUnit and Behat results are published to the Checks tab of each run, so a failed check links directly to the failing tests and their messages instead of requiring you to download artifacts or search through logs. Results are read from the JUnit reports the test tools already generate, so no extra setup is required.
Tests run across parallel build instances, so a separate check is created for
each instance (for example, Test results (0) and Test results (1)). To
disable publishing, set VORTEX_CI_TEST_RESULTS_SKIP to 1 in Settings →
Secrets and variables → Actions → Variables.