Developer Portal Build, Release and Deployment Runbook
This runbook explains build, release and deployment guidance for the main branch of:
- Repository: ministryofjustice/ministry-of-justice-developer-portal
- Branch scope:
main
Purpose
Use this runbook to:
- Understand the
mainbranch CI/CD flow. - Release via Release Please.
- Deploy to dev automatically.
- Deploy to prod manually.
- Troubleshoot and recover quickly.
High-Level Delivery Flow
flowchart TB
A[Change merged to main] --> B[CI workflows run]
B --> C[Build static app and container image in deploy workflows]
C --> D[Automatic deploy to dev workflow]
D --> E[Run health smoke test on dev]
E --> F[Release Please updates release PR and tags]
F --> G[Manual deploy to prod workflow dispatch]
G --> H[Run health smoke test on prod]
Main Branch Workflows
Key workflow files on main:
.github/workflows/lint.yml.github/workflows/unit-test.yml.github/workflows/sca.yml.github/workflows/release-please.yml.github/workflows/deploy-dev.yml.github/workflows/deploy-prod.yml.github/workflows/preview.yml(PR validation formain)
Pull Request Workflow
PR workflow file:
.github/workflows/preview.yml
Trigger:
pull_requesttargetingmain.
Behavior:
- Checks out PR code.
- Installs dependencies.
- Runs ingestion script.
- Builds the portal.
flowchart TB
A[Open or update PR to main] --> B[preview.yml triggered]
B --> C[Install dependencies]
C --> D[Run ingest]
D --> E[Build site]
E --> F[PR validation result]
Workflow Responsibilities Matrix
| Workflow | Purpose | Trigger conditions | Dependencies | Outputs |
|---|---|---|---|---|
preview.yml |
Validate PR ingest + build path | PR to main
|
Node runtime, npm dependencies, ingest/build scripts | PR build validation result |
lint.yml |
Code quality and formatting checks | Push to all branches | Node runtime, npm dependencies, lint/validate scripts | Lint/validation pass/fail signal |
unit-test.yml |
Unit tests with coverage | PR to main, push to main
|
Node runtime, npm dependencies, test suite | Test and coverage pass/fail signal |
sca.yml |
Security composition analysis | Scheduled, PR, manual, branch protection events | DevSecOps actions, dependency metadata | Security findings and pass/fail signal |
release-please.yml |
Manage release PR and version/tag lifecycle | Push to main
|
Conventional commit history | Release PR updates, release tags, GitHub release |
deploy-dev.yml |
Build/push/deploy to dev | Push to main, manual dispatch |
ECR config, dev kube secrets, deployment manifests | Dev deployment and smoke test result |
deploy-prod.yml |
Build/push/deploy to prod | Manual dispatch | ECR config, prod kube secrets, deployment manifests | Prod deployment and smoke test result |
Build and Validation Path
CI quality gates
flowchart TB
A[Push or PR event] --> B[Lint workflow]
A --> C[Unit test workflow]
A --> D[SCA workflow]
B --> E[Pass or fail]
C --> E
D --> E
What runs:
- Lint workflow: markdown, YAML, TypeScript checks, spellcheck.
- Unit tests workflow:
npm run test:coverage. - SCA workflow: dependency review, OWASP, secrets scanning, CodeQL, OpenSSF, SBOM.
Local build commands
From repository root:
make install
make build
Equivalent key npm command:
npm run build
Container test locally:
make docker-build IMAGE_URI=local/ministry-of-justice-developer-portal:dev
make docker-run IMAGE_URI=local/ministry-of-justice-developer-portal:dev
Release Guidance (Release Please)
Release workflow file:
.github/workflows/release-please.yml
Trigger:
- Push to
main.
Behavior:
- Updates or creates a Release PR using conventional commits.
- On release PR merge, creates/updates GitHub release and tags.
flowchart TB
A[Push to main] --> B[Release Please action runs]
B --> C[Create or update Release PR]
C --> D[Release PR reviewed and merged]
D --> E[GitHub tag and release published]
Operator checks:
- Ensure commit messages follow conventional commit style.
- Review generated release notes in the Release PR.
- Confirm release/tag creation in GitHub Releases.
Conventional commits and SemVer behavior
Typical version bump rules:
fix:-> patch bump.feat:-> minor bump.feat!:orBREAKING CHANGE:-> major bump.
Examples:
fix: correct retry timeout
-> v1.4.1
feat: add reporting endpoint
-> v1.5.0
feat!: replace authentication mechanism
-> v2.0.0
Release validation and approval model
Before merging a Release PR:
- Confirm CI validations are green.
- Confirm release notes and version bump are correct.
- Confirm change set is ready for deployment.
- Obtain required reviewer approval as defined by repository branch protection and team policy.
Deployment Guidance
Dev deployment (deploy-dev.yml)
Trigger:
- Automatic on push to
main. - Manual via
workflow_dispatch.
Workflow summary:
- Validates ECR config (
DEV_ECR_ROLE_TO_ASSUME,ECR_REGION,ECR_REPOSITORY). - Builds and pushes image tagged with
${github.sha}. - Configures
kubectlwith DEV cluster secrets. - Applies
k8s/dev/deployment.yamlwith image and namespace substitution. - Waits for rollout and runs smoke test against
https://dev.developer-portal.service.justice.gov.uk/healthz.
flowchart TB
A[Push to main or manual dispatch] --> B[Build amd64 Docker image]
B --> C[Push image to ECR with SHA tag]
C --> D[Configure kubectl for dev namespace]
D --> E[Apply k8s/dev deployment manifest]
E --> F[Wait for rollout status]
F --> G[Run dev health smoke test]
Prod deployment (deploy-prod.yml)
Trigger:
- Manual only via
workflow_dispatch.
Workflow summary:
- Validates ECR config (
PROD_ECR_ROLE_TO_ASSUME,ECR_REGION,ECR_REPOSITORY). - Builds and pushes image tagged with
${github.sha}. - Configures
kubectlwith PROD cluster secrets. - Applies
k8s/prod/deployment.yamlwith image and namespace substitution. - Waits for rollout and runs smoke test against
https://developer-portal.service.justice.gov.uk/healthz.
flowchart TB
A[Manual workflow dispatch] --> B[Build amd64 Docker image]
B --> C[Push image to ECR with SHA tag]
C --> D[Configure kubectl for prod namespace]
D --> E[Apply k8s/prod deployment manifest]
E --> F[Wait for rollout status]
F --> G[Run prod health smoke test]
Deployment Flow (End-to-End View)
flowchart TB
A[PR raised] --> B[preview.yml validates ingest and build]
B --> C[PR merged to main]
C --> D[lint/unit-test/sca workflows run]
D --> E[deploy-dev.yml builds image and deploys to dev]
E --> F[Dev smoke test]
F --> G[release-please.yml updates release lifecycle]
G --> H[Manual deploy-prod.yml dispatch]
H --> I[Prod rollout and smoke test]
Image Strategy and Traceability
Current implemented model:
- Deploy workflows build immutable images tagged by commit SHA:
${github.sha}. - Release lifecycle creates SemVer Git tags/releases via Release Please.
Traceability model:
- Source commit SHA -> container image tag.
- Same commit history -> Release Please SemVer tag.
- Deployment logs + workflow run IDs link environment state to commit/release.
Example identifiers:
ministry-of-justice-developer-portal:abc1234
v1.5.0
flowchart TB
A[Git commit SHA] --> B[Image tag with SHA]
A --> C[Release Please SemVer tag]
B --> D[Deployed workload image]
C --> E[GitHub release record]
D --> F[Operational traceability]
E --> F
Required Configuration
Repository variables:
NODE_VERSIONTIMEZONEECR_REGIONECR_REPOSITORY
Environment secrets (dev):
DEV_ECR_ROLE_TO_ASSUMEDEV_KUBE_CLUSTERDEV_KUBE_CERTDEV_KUBE_TOKENDEV_KUBE_NAMESPACE
Environment secrets (prod):
PROD_ECR_ROLE_TO_ASSUMEPROD_KUBE_CLUSTERPROD_KUBE_CERTPROD_KUBE_TOKENPROD_KUBE_NAMESPACE
Security and Governance Controls
Controls reflected in workflows and platform configuration:
- Least-privilege workflow permissions declared per workflow/job.
- Environment-scoped secrets for dev and prod deployment jobs.
- Manual production deployment trigger (
workflow_dispatch) to enforce change control. - Validation gates before deployment (lint, tests, SCA, PR build checks).
- Branch protection and required reviewers for release/deployment governance (configured in repository settings).
- Production environment approval gates and reviewer requirements (configured in GitHub environment settings, where enabled).
flowchart TB
A[Code change] --> B[PR validation gates]
B --> C[Branch protection and approvals]
C --> D[Main merge]
D --> E[Environment-scoped deployment workflow]
E --> F[Manual production promotion control]
Standard Operating Procedure
Promote changes from main to dev
- Merge PR into
main. - Confirm
deploy-dev.ymlstarts and succeeds. - Verify
/healthzand smoke-test step pass.
Promote changes from main to prod
- Confirm latest
maincommit is stable in dev. - Trigger
Deploy to Prodworkflow manually. - Monitor rollout and smoke test.
- Confirm production health endpoint and key pages.
Rollback Guidance
Preferred rollback path:
- Re-run prod deploy workflow using a previously known-good commit SHA.
- Redeploy the known-good image tag.
Approval and recovery expectations:
- Use the same operational approval model as forward prod deployment.
- Prioritize restoration of service before root-cause deep dive.
- Record rollback SHA, time, reason, and follow-up actions in incident notes.
flowchart TB
A[Prod issue detected] --> B[Identify last known good SHA]
B --> C[Trigger Deploy to Prod on known good SHA]
C --> D[Apply manifest with known good image]
D --> E[Wait rollout complete]
E --> F[Run smoke test and verify health]
Troubleshooting
1. Deploy workflow fails at configuration validation
Likely cause:
- Missing ECR variable or role secret.
Action:
- Check workflow logs for missing variable/secret name.
- Update Actions variables or environment secrets.
2. Rollout timeout
Likely cause:
- Pod startup failure or image pull issue.
Action:
- Check deployment events and pod logs in target namespace.
- Validate image URI exists in ECR.
- Roll back using known-good SHA if needed.
3. Smoke test fails
Likely cause:
- Ingress/DNS propagation or unhealthy app endpoint.
Action:
- Confirm rollout success first.
- Verify
/healthzresponse manually. - Re-run deploy if infrastructure timing issue is transient.
Related Commands (Portal Repo)
Useful commands from the portal repo Makefile:
make validate
make build
make docker-build IMAGE_URI=<registry/repo:tag>
make k8s-apply-dev IMAGE_URI=<registry/repo:tag>
make k8s-apply-prod IMAGE_URI=<registry/repo:tag>
make smoke-dev
make smoke-prod
Support
- Slack:
#developer-experience-alerts - Raise issue in
ministry-of-justice-developer-portalfor workflow bugs or deployment defects.