Configure CI
The Test workflow in .github/workflows/test.yml works as it is. This page covers the settings you're most likely to change: which runner runs which tool, which steps may fail and where the coverage goes.
Distribute tools across CI runners
Each leg of the test job's matrix is a CI runner of its own, with 1 PHP and Drupal pair. The env block at the top of the job sets which tools run on which runner:
env:
CI_RUNNER_INDEX: ${{ strategy.job-index }}
CI_RUNNER_TOTAL: ${{ strategy.job-total }}
CI_IS_JEST_RUNNER: true
CI_IS_PHPUNIT_RUNNER: true
The test job runs 2 tools, Jest and PHPUnit. Each tool has a CI_IS_<TOOL>_RUNNER flag, and its steps run only on a runner where the flag is true. Every flag is true, so every tool runs on every runner and tests every PHP and Drupal pair. The linters run in the lint jobs, which have no flags.
To run a tool on 1 runner only, replace its true with an expression that's true on that runner alone. The following flag compares the runner's matrix.name with the name of 1 job, so Jest runs on that job only:
CI_IS_JEST_RUNNER: ${{ matrix.name == 'test-php-max-d11-stable' }}
CI_RUNNER_INDEX holds the runner's position in the matrix, counting from 0. CI_RUNNER_TOTAL holds the number of runners. The shipped steps leave both unused. They're for a step of your own that splits 1 tool's tests across several runners, called sharding.
A sharded tool often gives runner 0 the tests that no other runner picks up. To give another tool a runner of its own, take the last runner, so runner 0 keeps running those tests.
GitHub names each status check after the leg's name. So when you add or rename runners, change the required checks in your branch protection rules too.
Allow a CI step to fail
To let a lint or test step fail without failing its job, create the repository variable that the following table names for that step. Set it to 1 under Settings > Secrets and variables > Actions > Variables. With any other value, a failure of the step still fails the job.
The step still runs and reports what it finds, and the steps after it run too. That helps while you work through a backlog of findings from a tool you've added.
The following table lists the variables and the step each one covers:
| Variable | Step |
|---|---|
CI_CSPELL_IGNORE_FAILURE | CSpell |
CI_PHPCS_IGNORE_FAILURE | PHPCS |
CI_PHPSTAN_IGNORE_FAILURE | PHPStan |
CI_RECTOR_IGNORE_FAILURE | Rector |
CI_TWIGCSFIXER_IGNORE_FAILURE | Twig CS Fixer |
CI_NODEJS_LINT_IGNORE_FAILURE | ESLint and Stylelint |
CI_NODEJS_TEST_IGNORE_FAILURE | Jest |
CI_TEST_IGNORE_FAILURE | PHPUnit |
Your workflow has only the steps of the tools you kept, and so only their variables.
Upload coverage to Codecov
Every test job that runs PHPUnit uploads its coverage reports as a workflow artifact. The upload to Codecov runs only when the CODECOV_TOKEN secret is set. To send the reports to Codecov too:
- Copy the upload token from your repository's settings on Codecov.
- Add the token as the
CODECOV_TOKENsecret under Settings > Secrets and variables > Actions > Secrets.
A failed upload fails the job, so a broken upload shows up in CI.
Deprecations on newer PHP
Test jobs on PHP 8.4 or newer set SYMFONY_DEPRECATIONS_HELPER to disabled, which turns off the deprecation checks of Symfony's PHPUnit Bridge. Deprecated code explains what that changes for each Drupal major and how to tune it to your project's deprecation policy.