Skip to main content
Version: v1

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:

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.

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:

  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
  • Deploy DB image
  • 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 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.