# CI/CD Pipeline DMARQ uses GitHub Actions for all continuous integration and delivery tasks. The pipeline is defined in two workflow files: | File | Purpose | Triggers | |------|---------|----------| | `.github/workflows/ci.yml` | Lint → Test → Security → Docker → GitOps | Push to `main`/`develop`, pull requests, weekly schedule | | `.github/workflows/release.yml` | Semantic versioning & changelog | Push to `main` | Use the [Release Checklist](../deployment/release-checklist.md) before merging production changes and after the deployment updates. --- ## Pipeline Stages ### Stage 1 — Lint (blocking gate) All subsequent jobs depend on this stage succeeding. | Tool | What it checks | |------|---------------| | **Black** | Code formatting (line length 100, target Python 3.13) | | **isort** | Import ordering (Black-compatible profile) | | **Flake8** | Style and complexity (`max-complexity=10`, E203/W503/E501 ignored) | | **Pylint** | Deeper static analysis (`continue-on-error` — advisory only) | The lint job auto-formats with Black and isort before running the `--check` step, so a failing lint job is usually caused by a Flake8 or Pylint issue. ### Stage 2 — Parallel quality gates These jobs run in parallel once lint passes. #### Test ```bash cd backend pytest --cov=app --cov-report=xml --cov-report=term-missing ``` Coverage results are uploaded to [Codecov](https://codecov.io). #### Security Scan - **Bandit** — Python security linter; the JSON report is uploaded as a workflow artifact (`bandit-security-report`) for every run. - **pip-audit** — checks all packages in `backend/requirements.txt` against known CVE databases. Both steps use `continue-on-error: true` so they are advisory; a finding will not block the build but will appear in the workflow summary. #### CodeQL Analysis GitHub's semantic code analysis scans the Python source for known vulnerability patterns (security and quality queries). Runs on push and PR events only — skipped on the weekly scheduled scan. #### Dependency Review Runs on pull requests only. Fails if any new dependency introduces a vulnerability of `moderate` severity or higher. ### Stage 3 — Docker Build & Publish Runs only on pushes to `main` after both **Test** and **Security** pass. - Builds from `./backend/Dockerfile` - Pushes to `ghcr.io//dmarq` with three tags: - `latest` (default branch only) - branch name (e.g. `main`) - short commit SHA (e.g. `a1b2c3d`) - Layer cache is stored via GitHub Actions cache (`type=gha`). ### Stage 4 — GitOps (Update K8s Manifest) Runs only on pushes to `main` after the Docker stage succeeds. Updates the image tag in the preprod Kubernetes manifest at `apps/dmarq/preprod/dmarq-stack.yaml` in the `christianlouis/k8s-cluster-state` repository. !!! note "Optional" This stage requires a `GH_PAT` repository secret with write access to the k8s-cluster-state repo. If the secret is absent or lacks access the step emits a warning and skips gracefully — it will never fail the pipeline. --- ## Release Workflow `release.yml` uses [python-semantic-release](https://python-semantic-release.readthedocs.io/) to automate versioning from [Conventional Commits](https://www.conventionalcommits.org/): - Bumps `version` in `pyproject.toml` - Generates/updates `CHANGELOG.md` - Creates a Git tag and a GitHub Release Commit prefixes that trigger a release: | Prefix | Version bump | |--------|-------------| | `fix:` | Patch (0.0.**x**) | | `feat:` | Minor (0.**x**.0) | | `feat!:` / `BREAKING CHANGE` | Major (**x**.0.0) | --- ## Scheduled Security Scan A cron job runs every Monday at 00:00 UTC and executes the **Lint**, **Security Scan**, and **Test** stages against the latest `main` code. CodeQL and Dependency Review are skipped on schedule events. --- ## Troubleshooting ### Lint failure 1. Pull the latest branch and run locally: ```bash black backend/app isort backend/app flake8 backend/app ``` 2. Commit the formatted files and push. Pylint failures are advisory (`continue-on-error: true`) and will not block the pipeline, but should still be investigated. ### Test failure 1. Reproduce locally: ```bash cd backend pytest --cov=app --cov-report=term-missing -x ``` 2. Check the test output in the **Test** job log for the failing assertion and stack trace. 3. The coverage XML is not uploaded as an artifact — run locally to inspect `htmlcov/index.html`. ### Security scan failure - **Bandit**: Download the `bandit-security-report` artifact from the workflow run's *Artifacts* panel and review `bandit-report.json`. - **pip-audit**: The finding is printed directly to the job log. Update or pin the affected dependency in `backend/requirements.txt`. ### Docker build failure Common causes: | Symptom | Fix | |---------|-----| | `pip install` error | Check `backend/requirements.txt` for unpinned or incompatible versions | | `COPY` file not found | Ensure the file exists and is not listed in `.dockerignore` | | Registry auth failure | Verify the workflow has `packages: write` permission | ### Dependency Review failure (PR only) The PR introduced a dependency with a known vulnerability. Either: - Remove the dependency, or - Upgrade to a patched version, or - If the finding is a false positive, discuss with a maintainer — the severity threshold (`moderate`) can be adjusted in the workflow. ### Release workflow not triggering Ensure your merge commit message follows Conventional Commits. The release workflow only creates a new version when `python-semantic-release` detects a `fix:`, `feat:`, or breaking-change commit since the last tag.