- Staging: continuous deployment — commits to the default branch are deployed automatically to staging.
- Production: continuous delivery — production deployments are gated by manual approval.
STAGING_ENABLED=1) and choose an incremental rollout in manual mode. This allows you to step the production rollout percentage up or down during the deployment lifecycle.
What is an incremental rollout (canary)?
A canary deployment releases a new version to a small subset of running pods/instances first, verifies behavior, then increases the percentage of traffic (or replicas) routed to the new version. If issues appear you reduce or abort the rollout; if the release behaves correctly you continue until 100% of traffic or replicas run the new version.

- 10% → 1 pod runs the new version, 9 run the old version.
- You can advance to 25%, 50%, etc.
- If something goes wrong you can reduce the rollout percentage. After a 100% rollout the only way to return to the previous version is a rollback to a prior deployment revision.

- In GitLab, open your project → Settings → CI/CD → Auto DevOps.
- Select “Automatically deploy to staging, manually deploy to production” (the third strategy).
- Save changes.

- Protected branches and protected environments enforce approvals for production.
- Production environments are usually protected, requiring manual approval before deployment.

index.html— replaced an animated GIF with a static PNG and commented out the rotation animation.app.js— cleaned up logging, ensured static assets are served, and added robust DB fallbacks.tests/hyphen-test.js— Mocha + Chai integration tests (use ofletcorrected).
- Commit with a descriptive message such as
testing autodevops canary release. - Push as a feature branch (e.g.,
feature/canary-deployment) and create a merge request in the GitLab UI.


Dependency scanning generates a Software Bill of Materials (SBOM) in CycloneDX format (
gl-sbom-*.cdx.json) and dependency reports listing package names and versions. DAST uses OWASP ZAP to spider and scan a deployed review environment URL for runtime vulnerabilities.

gl-dast-report.json artifact summarizing findings.
Example (truncated) DAST log excerpt:
-review-feature-...), enabling manual inspection and runtime scans. Confirm the front-end change (e.g., static background and no rotation) at the review app URL — the environment’s unique pod/identifier is often present in the URL.

- View the deployed review app.
- Inspect license compliance details for dependencies.
- Review consolidated security findings (SAST, DAST, container scanning, dependency scanning, secret detection) and create issues from findings.

- SAST findings: e.g., potential Node NoSQL injection.
- DAST warnings: medium/high runtime issues.
- Secret detection: critical findings such as exposed SSH/RSA private keys.
- Container/dependency CVEs flagged by Trivy, Gemnasium, or comparable scanners.




- Merging to the protected default branch triggers a pipeline that requires manual approval for production deploys. The production job will be gated by environment protection.
- In Part 2 we will merge the feature branch into the protected branch and observe the protected job and the UI-driven incremental rollout (canary) behavior for production. We’ll demonstrate manually stepping rollout percentages in the GitLab UI and handling a rollback.

Protect production environments and require approvals. Manual gates prevent unreviewed changes from reaching production and give you control over canary steps and rollbacks.
- GitLab Auto DevOps: https://docs.gitlab.com/ee/topics/autodevops/
- GitLab CI/CD Environments: https://docs.gitlab.com/ee/ci/environments/