CI/CD Architecture
This document explains how .gitlab-ci.yml is structured and how it relates to the local scripts/testing/run-tests.sh runner.
Audience
This document is for CI operators who manage pipeline architecture, job orchestration, and CI hardening.
For other audiences: - Users/site administrators: README.md - Developers/maintainers: TODO.md, DESIGN.md, CHANGELOG.md - AI contributors/agents: AGENTS.md - Testers (local/suite execution): docs/testing.md
Documentation in this guide is maintained using Drupal documentation standards and best practices.
Design Rationale
Local Development (scripts/testing/run-tests.sh)
- Purpose: Fast feedback during development before pushing
- Behavior: Combines repository linting, documentation link checking, PHP syntax validation, Drupal coding standards, static analysis, and PHPUnit into a single runner
- Changed-files mode (
--changed): Skips files not impacted by local changes; runs only matching linters and only affected PHPUnit suites - Full mode (default): Runs all checks comprehensively, including repository-local docs link validation
- Advantages: Quick iteration, minimal noise, deterministic test suite selection
CI Pipeline (.gitlab-ci.yml)
- Purpose: Comprehensive validation across multiple Drupal core versions and PHP versions using the standard Drupal GitLab CI Templates
- Job structure: Fully defined by the included Drupal GitLab CI templates (
include.drupalci.main.yml,include.drupalci.variables.yml,include.drupalci.workflows.yml);pagesis provided by the templates viamkdocs.yml - Template reference:
https://project.pages.drupalcode.org/gitlab_templates/ - Composer contract: The template expands this repository's
composer.jsoninto a generated Drupal project before runningcomposer install, so committed Composer plugin policy must continue to allowcomposer/installersanddrupal/core-composer-scaffoldfor the standardweb/corelayout expected by later CI steps. Project Composer constraints must also avoid overriding the template's core-aligneddrupal/core-devselection with an unconstrained wildcard, because that can resolve an incompatible historical metapackage and drop BrowserTest or Kernel-test dependencies such asbehat/mink-browserkit-driverandmikey179/vfsstream. - Rationale:
- Leverages the Drupal Association's centrally-maintained job definitions and toolchain
- Automatically picks up future template improvements via the include mechanism
- Keeps project-specific CI minimal and focused on project-specific needs only
- Aligns with Drupal contribution standards and expectations for contrib modules on drupalcode.org
CI Jobs
The standard Drupal GitLab CI templates define and manage the following job categories automatically:
- Composer dependency resolution across supported PHP/Drupal version combinations
- PHPCS (Drupal, DrupalPractice) coding standards enforcement
- PHPStan static analysis
- PHPUnit Unit, Kernel, and Functional test suites
- ESLint and stylelint asset linting
- Compatibility matrix coverage across Drupal core versions
Refer to the Drupal GitLab Templates documentation for a full description of the jobs, stages, variables, and configuration options provided by the included templates.
pages (standard template)
- Provided by the included Drupal GitLab CI templates
- Publishes MkDocs documentation from
docs/to GitLab Pages using Material for MkDocs - Published URL:
https://project.pages.drupalcode.org/drupalforge_deploy/ - Configured via
mkdocs.ymlat the project root - Runs on the default branch; also runs as a manual job in MR pipelines for preview
- Separate from test jobs (can fail independently without blocking test results)
Differences from Template Baseline
This project follows the standard Drupal GitLab CI templates without modification. The pages job is also provided by the templates via the project's mkdocs.yml configuration:
- MkDocs documentation:
mkdocs.ymldefines the documentation site structure. The standard templatepagesjob builds and publishes it automatically. - Local development emphasis:
scripts/testing/run-tests.shruns linters and test suites locally, providing fast feedback before pushing to CI. - Changed-files optimization: Local runner has
--changedmode for speed; CI always runs the full suite.
Ready to Run (Pre-push)
Use this checklist to decide whether a branch is ready to push to GitLab CI.
Primary command:
scripts/testing/ready-to-run.sh
Local hierarchy line graph:
.githooks/pre-push
|
v
scripts/testing/ready-to-run.sh
|
+--> scripts/testing/check-orphan-test-assets.sh
|
+--> scripts/testing/run-tests.sh --changed (default)
|
+--> scripts/testing/run-tests.sh (--full)
Focused path:
scripts/testing/bootstrap-runtime.sh -> scripts/testing/run-phpunit.sh / scripts/testing/run-functional.sh
All items below must be true:
- Local hook wrapper succeeds:
scripts/testing/ready-to-run.shpasses for current branch changes- Local full suite command is runnable (when environment is available):
scripts/testing/run-tests.shcompletes, or any blocker is documented inTODO.md- Completed validation work is moved from
TODO.mdtoCHANGELOG.mdbefore commit - CI configuration consistency is preserved:
.gitlab-ci.ymlincludes the three standard Drupal CI template files;mkdocs.ymlis present for the templatepagesjob- GitLab Pipeline editor validation succeeds for current config:
Validate->Lint CI/CD sampleconfirms merged YAML syntax and include expansionValidate->Simulate pipeline creation for the default branchconfirms stage/needs/rules graph validity
- Documentation reflects actual behavior:
docs/testing.mdand this file match the current.gitlab-ci.yml- No unresolved editor diagnostics in modified files.
Interpretation: - Meeting this checklist means ready to run on GitLab. - It does not mean CI hardening is fully verified; final verification requires real GitLab pipeline results.
Future Enhancements
- Custom job overrides: If project-specific CI behavior is needed beyond what the standard Drupal templates provide, add override jobs or variables following the Drupal GitLab Templates extension pattern.
- Coverage publishing: Consider extending the
pagesjob to include test coverage reports alongside the static HTML docs once coverage thresholds are established. - Artifact collection: Add artifact/report collection if needed for metrics dashboards.