Skip to main content

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.

info

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):

PatternDescription
productionProduction environment branch
main, masterDefault development branches
developIntegration 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):

PatternDescription
All push branches aboveSame 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 build and database jobs print df -h in 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.

note

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:

InputDescription
deploy_targetBranch name (e.g., develop) or PR reference (e.g., PR-123, case-insensitive)
override_dbOverride 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.

note

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.