CI workflow¶
The CI pipeline runs on every pull request to main and on pushes to main. It validates code quality, builds artefacts, scans for vulnerabilities, and runs UI tests - all orchestrated through reusable GitHub Actions workflows.
Pipeline overview¶
graph TD
A[generate_project_matrix] --> B[lint_test_build_and_scan]
B --> C[build_docker_image]
C --> D[docker_security_check]
C --> E[run_ui_tests]
A --> F[generate_summary]
B --> F
C --> F
D --> F
E --> F
F --> G[report-results]
F --> H[status_check]
classDef layer-api fill:#4a90d926,stroke:#4a90d9,stroke-width:2px
classDef layer-domain fill:#7ed32126,stroke:#7ed321,stroke-width:2px
classDef layer-infra fill:#f5a6232e,stroke:#f5a623,stroke-width:2px
classDef layer-external fill:#9b9b9b2e,stroke:#9b9b9b,stroke-width:2px
classDef neutral fill:#c8c8c826,stroke:#999999,stroke-width:1.5px
class A layer-api
class B layer-domain
class C layer-infra
class D layer-external
class E layer-domain
class F,G,H neutral
Diagram key
- Blue (API layer): Project matrix generation - orchestration entry point
- Green (Domain): Lint, test, build, scan and UI tests - validation jobs
- Orange (Infrastructure): Docker image build
- Grey (External): Docker security check - external vulnerability scanning
- Light grey (Neutral): Summary generation, reporting, and status check
Jobs¶
1. Generate project matrix¶
Workflow: generate-project-matrix.yml
Uses Nx to detect which projects are affected by the current changes. This matrix drives all downstream jobs - if a project isn't affected, its jobs are skipped entirely.
On pushes to main (or in CD mode), all projects are included regardless of changes.
2. Lint, test, build and scan¶
Workflow: lint-test-build-and-scan.yml
Runs in parallel for each affected project using a matrix strategy (max 4 parallel jobs):
- Lint - ESLint with the project's flat config
- Test - Jest with code coverage
- Build - Nx build target
- SonarQube Scan - Static analysis and coverage upload (skipped for Dependabot PRs)
3. Build Docker image¶
Workflow: docker-build.yml
Condition: Only runs when petfolio-business is affected
Builds a multi-stage Docker image for the Next.js application and uploads it as a CI artefact for downstream jobs. Runs after lint/test/build to avoid wasting time building an image from broken code.
4. Docker security check¶
Workflow: docker-security-check.yml
Condition: Only runs when petfolio-business is affected
Scans the built Docker image for vulnerabilities using Trivy:
- Counts vulnerabilities by severity (critical, high, medium, low)
- Identifies fixable vulnerabilities
- Applies a security gate - fails on any critical vulnerabilities or more than 10 high vulnerabilities
- Uploads the full Trivy JSON report as an artefact (30 day retention)
- Creates a GitHub issue on
mainbranch failures
Results are included in the unified PR summary comment under a collapsible Docker Security Scan section.
5. UI tests¶
Workflow: ui-tests.yml
Condition: Only runs when petfolio-business is affected
Runs Playwright end-to-end tests against the built Docker image:
- Downloads the Docker image artefact
- Starts the container via the
start-docker-containercomposite action - Installs Playwright chromium browser
- Runs
npx nx e2e petfolio-ui-tests -- --project=chromiumwithBASE_URLpointing at the container - Parses JUnit XML results to extract test counts and any failure details
- Uploads Playwright HTML report and test results as artefacts (7 day retention)
- Stops and removes the container
Results are included in the unified PR summary comment under a collapsible UI Test Results section, showing failed test names and error messages when there are failures.
6. Generate summary and report results¶
Workflow: workflow-summary-template.yml
Collects outputs from all upstream jobs and builds a unified markdown summary with collapsible sections:
| Section | Headline | Detail (collapsible) |
|---|---|---|
| Workflow Status | Job pass/fail/skip counts | Failed job names with links |
| Docker Security Scan | Vulnerability severity counts | Full scan report with CVE table |
| UI Test Results | Test/failure/error counts | Failed test names with error messages |
This summary is posted as a single PR comment (updated on each push) and used to create GitHub issues for main branch failures.
7. Status check¶
A required check that gates PR merges. It inspects the results of all upstream jobs and fails if any job failed or was cancelled.
Composite actions¶
start-docker-container¶
Location: .github/actions/start-docker-container/action.yml
Reusable composite action for starting a Docker container with health checking:
| Input | Required | Default | Description |
|---|---|---|---|
imageName |
yes | - | Docker image to run |
port |
yes | 4200:4200 |
Port mapping |
containerName |
yes | - | Container name |
environmentVariables |
no | - | Space-separated KEY=value pairs |
Behaviour:
- Runs the container in detached mode with optional environment variables
- Polls until the container is running (up to 60 seconds)
- Polls the Docker healthcheck status (up to 90 seconds)
- On healthcheck failure, captures container logs and uploads them as an artefact
Concurrency¶
- PR branches use
cancel-in-progress: true- pushing a new commit cancels the in-progress run - The
mainbranch allows parallel runs so concurrent merges don't cancel each other
Reusable workflow pattern¶
All CI jobs use the workflow_call trigger, making them reusable workflows that can be composed. The CI workflow (ci.yml) also supports being called from a CD pipeline via workflow_call with a cdMode input that includes all projects regardless of affected detection.
Key files¶
| File | Purpose |
|---|---|
.github/workflows/ci.yml |
Main orchestrator |
.github/workflows/generate-project-matrix.yml |
Nx affected detection |
.github/workflows/lint-test-build-and-scan.yml |
Per-project validation |
.github/workflows/docker-build.yml |
Docker image build |
.github/workflows/docker-security-check.yml |
Trivy vulnerability scanning |
.github/workflows/ui-tests.yml |
Playwright E2E tests |
.github/workflows/workflow-summary-template.yml |
PR comment and issue creation |
.github/actions/start-docker-container/action.yml |
Container lifecycle composite action |