Skip to main content
Version: v2

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 database caching
  • 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 lint, test, 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:

PatternDescription
productionProduction environment branch
main, masterDefault branches
developIntegration 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.xMajor 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 deploy job stops early for a project/* branch when CircleCI sets CIRCLE_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-tags job, 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). The deploy job itself ignores tags.

To change which branches deploy:

  1. In .circleci/config.yml, update the regular expressions in the only filter of the deploy job.
  2. In tests/phpunit/CircleCiConfigTest.php, update the branch names in dataProviderDeployBranchRegex() 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.

Configure database caching​

The test job downloads a fresh database dump on the first build of the day and caches it, so the rest of that day's builds reuse the cached dump. The cache key includes a daily timestamp, so the cache refreshes each day. To change the cache window, update the VORTEX_CI_DB_CACHE_TIMESTAMP value, a date format string, in the runner_config environment in .circleci/config.yml:

VORTEX_CI_DB_CACHE_TIMESTAMP: +%Y%m%d # New cache each day

When the test job runs in parallel, only the first container stores the cache. CircleCI never overwrites a saved key, so the first dump saved under a day's key serves the rest of that day.

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 test job in .circleci/config.yml, which ships as 2:

test:
parallelism: 4 # Run tests across 4 containers

See Running tests in parallel for more information. Confirm that the next test 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:

  1. In the CircleCI web app, open the failed job.
  2. From the Rerun menu, select Rerun job with SSH. CircleCI runs the job again with SSH enabled.
  3. Copy the SSH command from the Enable SSH step in the job output.
  4. 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 DB
  • Fetch migration DB, when the project has a migration database
  • Export DB after fetch
  • Provision site
  • Test with Behat
  • Deploy, in both the deploy and deploy-tags jobs

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 test 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 in the CLI, 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 test 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.