CircleCI
CircleCI is a hosted continuous integration and
delivery service. Vortex offers it whichever code host you use, while
GitHub Actions is offered only for repositories on GitHub. The pipeline
lives in .circleci/config.yml, and the security checks run there as a
separate audit workflow.
This page is for the lead or DevOps engineer who maintains a Vortex project's pipeline on CircleCI. It shows how to change the parts of the pipeline that are specific to CircleCI:
- Deployment branches and the nightly schedule
- The runner resource class and test parallelism
- SSH access for debugging and build timeouts
- The coverage threshold and test results
Running Renovate on CircleCI adds a second file,
.circleci/update-dependencies.yml, with a scheduled trigger of its own
(see Dependency updates > Setting up the self-hosted
service).
The jobs, the database cache, and the split of tests across containers work
the same on both providers; see the
Continuous integration overview. For CircleCI's own
reference, see the CircleCI documentation.
Onboarding
CircleCI onboarding is part of the project setup flow. See Set up continuous integration in the Installation guide and select CircleCI.
Maintenance
The following sections change how the pipeline runs on CircleCI. Most of
them edit .circleci/config.yml or set a project environment variable
under Project Settings → Environment Variables.
Update deployment branches
The database, lint, and build jobs of the commit workflow and the
audit job of the audit workflow run on every branch and every tag. The
deploy job runs only for branches that match a list of regular expressions
in the workflows section of .circleci/config.yml:
| Pattern | Description |
|---|---|
production | Production environment branch |
main, master | Default branches |
develop | Integration branch for ongoing work |
release/** | Release preparation branches (for example, release/1.2.3, release/2023-04-17) |
hotfix/** | Urgent production fixes (for example, hotfix/1.2.4, hotfix/2023-04-17) |
feature/** | New feature branches (for example, feature/login, feature/123-new-ui) |
bugfix/** | Non-urgent bug fix branches (for example, bugfix/fix-auth, bugfix/456-crash) |
project/** | Long-lived project branches for large initiatives |
ci* | Temporary CI testing branches (for example, ci, ci-debug) |
N.x | Major version branches (for example, 1.x, 2.x) |
The patterns in the table are shorthand for those expressions. release/**
and hotfix/** match only a version after the slash: 1.2.3, 1.2.3-rc.1,
2023-04-17, or 2023-04-17.1. feature/** and bugfix/** match a single
name made of letters, digits, -, ., ,, and _, so feature/a/b
doesn't deploy.
2 special cases apply on top of the branch filter:
- The
deployjob stops early for aproject/*branch when CircleCI setsCIRCLE_PULL_REQUEST, the URL of the pull request associated with the build. A long-lived project branch deploys only from builds that have no associated pull request. - Tags deploy through a separate
deploy-tagsjob, which runs only for tags named after a semantic version (1.2.3,1.2.3-rc.1) or a date (2023-04-17,2023-04-17.1). Thedeployjob itself ignores tags.
To change which branches deploy:
- In
.circleci/config.yml, update the regular expressions in theonlyfilter of thedeployjob. - In
tests/phpunit/CircleCiConfigTest.php, update the branch names indataProviderDeployBranchRegex()to match. The test checks every expression against them, and also checks that no filter pattern exceeds the 128-character limit of the CircleCI compiler.
Confirm that the test passes:
ahoy test-unit -- --filter=CircleCiConfigTest
PHPUnit reports OK with no failures.
Update nightly database schedule
The nightly-db workflow runs the database-nightly job: the regular
database job with the cache fallback turned off, so it always downloads a
fresh dump. It also skips the front-end build. For a project that stores
its database in a container image, it imports the dump into a clean base
image and pushes the result to the registry.
The job saves the dump under the current day's cache key, and CircleCI
never overwrites a saved key. If another database job already saved that
key earlier in the day, the fresh dump isn't cached, and the next day's
builds fall back to the earlier cache.
The workflow is scheduled against the develop branch. If your project
doesn't use one, change the branch in the filters.branches.only list of
the nightly-db workflow's triggers entry, in the workflows section at
the end of .circleci/config.yml. The workflow ships only when the site
provisions from a database dump.
To change when it runs, update the nightly_db_schedule YAML anchor in
.circleci/config.yml: a named value near the top of the file that the
workflow's trigger reuses
(cron format, UTC timezone):
- &nightly_db_schedule "0 18 * * *" # 6 PM UTC daily
Confirm that the next nightly-db workflow starts at the new time and runs
only the database-nightly job.
Change runner resource class
For faster builds, raise the runner resource
class in the shared
runner_config block that every job uses. It ships as medium. This might
affect your CircleCI billing. The following setting raises it to large:
resource_class: large # Options: small, medium, large, xlarge
Resource classes scale CPU and memory only. Disk space isn't tied to the resource class, so upgrading it doesn't help a job that runs out of space. See Runner disk space.
Change test parallelism
To get through the tests faster, raise the parallelism of the build
job in .circleci/config.yml, which ships as 2:
build:
parallelism: 4 # Run tests across 4 containers
See Running tests in
parallel for more
information. Confirm that the next build job shows 4 parallel runs.
Every added container that runs Behat also needs a matching pN profile in
behat.php; see Continuous integration > Adding more
containers for the full procedure.
Test parallelism also covers how scenarios
are balanced across containers and how to move a tool onto a different
container.
SSH access for debugging
CircleCI has built-in SSH access for debugging a failing build. To connect to a failed job:
- In the CircleCI web app, open the failed job.
- From the Rerun menu, select Rerun job with SSH. CircleCI runs the job again with SSH enabled.
- Copy the SSH command from the Enable SSH step in the job output.
- Run the command in your terminal.
Confirm that the command opens a shell in the job's container. The job stays available for SSH for 10 minutes after it finishes running. See Debugging with SSH for more information.
Adjust build timeout
CircleCI stops a step that prints nothing for 10 minutes. The shipped config raises that limit to 30 minutes for its long, quiet steps:
Fetch DBFetch migration DB, when the project has a migration databaseExport DBDeploy DB imageProvision siteTest with BehatDeploy, in both thedeployanddeploy-tagsjobs
If a step still times out, increase its no_output_timeout:
- run:
name: Long running task
command: ./scripts/long-task.sh
no_output_timeout: 60m # Default is 10m
Code coverage threshold
The build job fails when the line coverage that PHPUnit reports falls
below a threshold.
Set the threshold in the VORTEX_CI_CODE_COVERAGE_THRESHOLD environment
variable, under Project Settings → Environment Variables. It defaults to
90 (percent). Use a whole number: the check multiplies the value in shell
integer arithmetic, so a decimal such as 85.5 breaks the step.
The job can also post the coverage summary as a comment on a GitHub pull
request. That needs a GITHUB_TOKEN environment variable with permission
to post comments; without one, the step skips the comment. Each new report
replaces the previous one, and older comments are minimized, so the pull
request timeline stays clean. To turn the comment off, set
VORTEX_CI_CODE_COVERAGE_PR_COMMENT_SKIP to 1.
If you chose Codecov as the code coverage provider at install time, the job
also uploads the coverage reports to Codecov when CODECOV_TOKEN is set,
except on deps/* branches. The uploader runs with -Z, so a failed upload
fails the job.
Test results
The build job stores the JUnit reports of PHPUnit and Behat with
CircleCI's store_test_results step, so the job's Tests tab lists the
failing tests with their messages. Each parallel container stores its own
results. The logs, coverage reports, and screenshots stay attached to the
job on its Artifacts tab.