This is the implementation counterpart to what Drupal DevSecOps actually means. It describes the stages, what each one is for, and the decisions that have to be made by a person rather than configured.
Azure DevOps is used as the worked example because its model maps cleanly onto what an enterprise needs: Microsoft describes a pipeline as being made up of stages, with control over whether a stage runs exercised through approvals and checks, and describes an environment as a group of resources you can target with deployments from a pipeline. The same shape can be built in other tools, as the comparison sets out.
Before the first stage: three prerequisites
A pipeline built on top of an estate that does not meet these will fight you continuously.
- The build is reproducible. Dependencies resolve identically every time. Composer describes itself as a tool for dependency management in PHP, and the lock file is what makes the resolution deterministic. If the lock file is absent or routinely ignored, fix that first.
- Configuration is in the repository. Site configuration is exported and imported on deploy rather than changed in production. Without this, the pipeline automates half a release.
- Nobody edits production directly. If they do, the pipeline will be overwritten by hand and blamed for the inconsistency.
Stage 1. Validation on the pull request
Everything cheap runs here, because a finding on a pull request costs a comment.
- Dependency manifest and lock file agree, and the tree resolves.
- Coding standards, on changed files at minimum.
- Static analysis, tuned so it reports real defects rather than style opinions.
- Unit tests.
- Configuration sanity: the exported configuration imports cleanly into a fresh database.
That last check is Drupal specific and repays itself quickly. A configuration export that will not import is a broken release that would otherwise be discovered in staging, after a queue has formed behind it.
Stage 2. Security validation
Still on the pull request or immediately after merge, and this is the stage that makes the pipeline a DevSecOps pipeline rather than a CI pipeline.
- Software composition analysis. OWASP describes Dependency-Check as a Software Composition Analysis tool suite that identifies project dependencies and checks whether any have known, publicly disclosed vulnerabilities. On a Drupal codebase this is the highest value check available, because most of the code was written elsewhere.
- Secret scanning. Credentials in a repository are the most reliably exploited defect in web estates, and the cheapest to detect.
- Software bill of materials. Generate and retain it. CycloneDX describes itself as a modular and extensible framework designed to represent a broad range of supply chain information, and its practical value is answering, months later, whether a newly disclosed vulnerability affects you.
NIST frames the whole stage well in SP 800-218, which recommends a core set of high-level secure software development practices that can be integrated into each SDLC implementation.
Stage 3. Build the artifact, once
This is the stage everything else depends on. Produce a single immutable artifact containing the resolved dependency tree, the application code and the compiled theme assets. Version it. Store it. Promote that same artifact through every environment.
If staging and production each build their own copy, the artifact you scanned in stage two is not the artifact that reached users, and every gate upstream became decorative. This is the single most common structural flaw in pipelines that otherwise look complete.
Attach provenance while you are here. SLSA is organized into a series of levels that provide increasing supply chain security guarantees, and its first build level is simply that provenance exists. Recording how an artifact was built is inexpensive and is the thing you will want during an incident.
Stage 4. Deploy to development, and run the Drupal sequence
Deploying Drupal is not copying files. Drush documents the ordered sequence its deploy command performs after the codebase is in place: database updates, configuration import, cache rebuild, then deployment hooks.
The order is load bearing. Configuration import expects the schema the database updates just created; the cache rebuild expects the configuration import just applied. A pipeline that runs these concurrently, or in a different order, will produce failures that look random.
Decide explicitly what happens if a step fails partway. A failed configuration import after a successful database update leaves the site in a state that is neither the old release nor the new one, and the pipeline should say what to do about that rather than exiting non-zero and leaving it.
Stage 5. Staging, and dynamic testing
Promote the same artifact to an environment that resembles production closely enough for the result to mean something. Then run the tests that need a running application: functional journeys, dynamic security testing, and performance against a realistic dataset.
Two Drupal specific cautions.
- Staging data. Refreshing staging from production is normal and copying personal data into a less protected environment is a legal problem, not a preference. Sanitize on the way in.
- Cache behavior. A performance result from a fully warmed cache and no edge is not a result. Test the shape you will actually run.
Stage 6. The approval gate
A deliberate human decision, recorded, before production. Microsoft describes this directly: control over whether a stage should run is exercised through approvals and checks.
The value of modeling approval as an object rather than a convention is that people who do not write pipelines can hold the authority. If your change process involves a group outside engineering, this is the stage that makes it real rather than parallel.
Decide the policy explicitly, because it is a governance decision and not a technical one:
- What severity of finding blocks a release outright?
- Who may override, and what is recorded when they do?
- What is the standing exception process, so that overrides do not become the norm?
A gate that never blocks trains everyone to ignore it. A gate that blocks on everything stops delivery within a week and is then disabled. The threshold is the decision, and it needs an owner with the authority to defend it.
Stage 7. Production, then verification
Deploy the same artifact. Run the Drupal sequence again. Then verify, automatically: the site answers, the expected release is live, key journeys work, and error rates have not moved.
Microsoft notes that deployment history of an environment can be used to identify the source of changes, which is the audit trail this stage produces almost for free. It is what turns "what is in production and how did it get there" from an investigation into a query.
Stage 8. Rollback
Rollback is a stage, not a hope. Redeploying the previous artifact is the easy half. The hard half is that Drupal database updates are frequently not reversible, so a rollback plan has to say what happens to the schema and to content created since the release.
In practice this means the plan is one of: a rehearsed restore to a known point, a forward fix, or a decision that this class of change is not rollable and therefore requires a heavier gate. All three are legitimate; not choosing is not. The reasoning is in cutover and rollback strategy.
Across many sites
An estate is many repositories that should behave identically. Use a shared, versioned pipeline template rather than copying a definition into each site, and decide who may change it and what happens to fifty sites when it changes.
The counterpart is the operations that act across the estate rather than within one site: bulk updates, scheduled maintenance, coordinated releases. Those belong with Drupal lifecycle automation rather than in the per site pipeline.
Where the agents run, and under what identity
A detail that decides more designs than it should. The build agent has to be able to reach the target, and it has to authenticate as something.
If the destination is a public cloud account, hosted agents are usually sufficient and the identity question becomes how the pipeline obtains credentials. Prefer a federated identity over a long lived secret stored in the pipeline: a static key in a variable group is a credential with no expiry and no owner, and it will outlive the person who created it.
If the destination is private infrastructure, a restricted network or a government region, hosted agents may have no route at all. Self-hosted agents solve reachability and introduce their own obligations: the agent host is now part of the production path and needs patching, hardening and monitoring like anything else in it. An unpatched build agent with deployment credentials is a serious exposure wearing an innocuous name.
Two rules worth adopting whatever the topology:
- Least privilege per environment. The identity that deploys to development should not be able to deploy to production. If one service principal can reach everything, the approval gate protects a door that has another way round it.
- Secrets are referenced, not stored. The pipeline holds a reference to a secret in a managed store; it does not hold the secret. That is what makes rotation possible without editing pipelines.
Both belong to the runtime side of the picture as much as to the pipeline, which is covered in Drupal cloud security architecture.
What good looks like
Four properties, all testable by demonstration rather than by document.
- A dependency vulnerability can stop a release without a person deciding to stop it.
- The artifact in production is provably the artifact that was scanned.
- A non-engineer can approve a production deployment, and the approval is recorded.
- The team has performed a rollback recently enough to remember doing it.
Building this during a platform move is considerably cheaper than retrofitting it afterwards, which is why enterprise Drupal modernization and DevSecOps services are one capability rather than two. If you would like a review of an existing pipeline against these four, that is a useful place to start.
Sources
The external statements on this page are quoted from the following, each re-read on 10 September 2026.
- Composer, Introduction, Composer documentation
- Microsoft, Define approvals and checks, Azure Pipelines documentation
- Microsoft, Create and target an environment, Azure Pipelines documentation
- Drush, Deploy command, Drush 13 documentation
- OWASP, OWASP Dependency-Check
- OWASP CycloneDX, Specification Overview
- SLSA, Security levels, SLSA specification v1.0
- NIST, Secure Software Development Framework (SSDF) Version 1.1, SP 800-218