Skip to the content.

CI/CD Baseline

Project: MCPg Baseline created: 2026-09-01 Last audited: 2026-09-01 ci-cd-plumber skill version: 0.1.0 (from agent-skills repo at audit time) Maturity target: high-assurance (production, long-lived, multi-channel release)

Platform & triggers

Pipeline layers (observed)

  1. PR / main validation (ci.yml)
    • lint — ruff check + format –check, mypy on src/mcpg
    • security — pip-audit –strict (runtime deps), bandit SAST, non-blocking pip-licenses
    • test — matrix PG 14–18 (required) + experimental PG 19 and WarehousePG; coverage gate fail_under=90
  2. Static / supply-chain security
    • codeql.yml — CodeQL python + actions languages on PR + main + schedule
    • actions-security.yml — zizmor (SARIF) + actionlint (reporting mode)
    • scorecard.yml — OpenSSF Scorecard, publish_results + code-scanning upload
    • ClusterFuzzLite (cflite_pr.yml, cflite_batch.yml)
  3. Release / promotion (publish.yml on v*.*.* tags)
    • build sdist+wheel → version-tag sanity check → CycloneDX SBOM → build-provenance attestation
    • TestPyPI (OIDC) → smoke install (hash-pinned, simple-index poll) → human-gated PyPI (OIDC environment protection)
    • GitHub Release (notes from CHANGELOG.md section) + attach dist + SBOM + .mcpb
    • MCP Registry (OIDC), GHCR image (:version + :latest), optional Smithery / HF Space refresh
  4. Docs sitepages.yml
  5. Dependency automation — Dependabot (pip + github-actions + docker), weekly, grouped minor/patch; Conventional Commit prefixes

Security posture (recorded decisions)

Release documentation

Deliberate exceptions (do not treat as regressions unless intent changes)

  1. zizmor / actionlint in reporting mode — see TODO below before promoting to blocking.
  2. Harden-Runner egress-policy: audit — see TODO below before block mode on publish.
  3. PG 19 and WarehousePG matrix lanescontinue-on-error: true / experimental; non-gating by design until GA / image stability.
  4. Parameterized CI Postgres Dockerfile (.github/ci-postgres.Dockerfile) — intentionally not digest-pinned (driven by PG_MAJOR matrix); other Dockerfiles use digests where fixed.
  5. Docker build-push provenance: false on GHCR job — intentional to keep package page as a single clean manifest.
  6. Manual tag-based release rather than release-please — matches documented release-process.md; not a gap unless automation is later desired.

TODO (deferred from 2026-09-01 ci-cd-plumber audit)

Do not treat these as open defects until you choose to schedule them. Order matches increasing operational risk.

  1. [M2] Promote zizmor / actionlint to blocking
    • Precondition: confirm Security → Code scanning (zizmor category) is clean, or triage remaining findings / waivers.
    • Then in .github/workflows/actions-security.yml: remove continue-on-error: true on the zizmor step; set actionlint fail-on-error: true.
    • Avoid promoting while known open findings remain (otherwise every PR fails for no new value).
  2. [L1] Harden-Runner block mode on publish.yml first
    • Precondition: review egress audit logs from real publish runs; build an allow-list covering PyPI, TestPyPI, GHCR, MCP registry, uv/npx, attestation endpoints, etc.
    • Only then switch egress-policy: block on publish jobs (not on guesswork — a bad list breaks tagged releases).
  3. Optional (leave unless priorities change)
    • [L2] Path filters / paths-ignore on ci.yml for pure-docs changes (trade-off: some doc PRs skip the test matrix).
    • [L3] Re-enable Docker build-push provenance on GHCR if multi-manifest package UI is acceptable.
    • [L4] release-please / similar only if release cadence or contributor count grows enough to justify automation.

Drift log