Add CI quality gate: lint, unit+coverage, integration, security, benchmark#13
Conversation
…hmark Foundation for issue #10 mandatory quality gate. Adds .github/workflows/quality-gate.yml with required jobs: lint, unit tests with coverage + flaky-test auto-retry, distribution consistency audit as integration check, security scanning (bandit/pip-audit/gitleaks), and a benchmark with committed baseline + configurable regression threshold, fanned into one required quality-gate status check for branch protection. Also fixes the version.txt/simplicio-update-manifest.json drift the audit script already flagged as ERROR but nothing enforced, plus a regression test pinning that fix and unit tests for the audit/benchmark scripts (93% coverage on scripts/). docs/ci-quality-gate.md documents pipeline stages/time budget, coverage/regression-test/flaky-test/exception policies, the manual branch-protection step for a repo admin, and what is out of scope for this first slice. Closes #10 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Brings in PR #12 (unit test suite, CONTRIBUTING.md, testing-strategy docs, pyproject.toml, requirements-dev.txt, tests.yml workflow) alongside the existing CI quality-gate workflow from this branch. .gitignore merged to keep entries from both sides.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2ddb00f5e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| - name: Run distribution consistency audit | ||
| run: | | ||
| mkdir -p reports | ||
| python scripts/verify_distribution_consistency.py | tee reports/consistency-audit.txt |
There was a problem hiding this comment.
Preserve audit failures through tee
When verify_distribution_consistency.py returns 1 (for example, a future /main/ install URL or version mismatch), this step still succeeds because the pipeline's exit status is tee's and the step does not enable pipefail; locally, bash -e -c 'false | tee file' exits 0. That makes the integration job, and therefore the required quality-gate, go green while the uploaded audit report contains errors. Add set -o pipefail or capture/report the output without masking the Python exit code.
Useful? React with 👍 / 👎.
| def _load_audit_module(): | ||
| spec = importlib.util.spec_from_file_location("verify_distribution_consistency", SCRIPT_PATH) | ||
| module = importlib.util.module_from_spec(spec) | ||
| assert spec.loader is not None |
There was a problem hiding this comment.
Remove Bandit-triggering assert from scanned script
The new security job runs bandit -r scripts with the default profile, and Bandit documents that the profile defaults to executing all tests and that B101 checks uses of Python assert (CLI docs, B101 docs). Because this newly scanned production script contains the only assert under scripts/, the security job will fail on every run before the rest of the security gate can pass; replace this with an explicit exception or configure a justified Bandit skip.
Useful? React with 👍 / 👎.
| with: | ||
| python-version: "3.12" | ||
| - name: Run benchmark against committed baseline | ||
| run: python scripts/bench_verify_distribution_consistency.py | tee benchmark-report.txt |
There was a problem hiding this comment.
Preserve benchmark failures through tee
When the benchmark script exits 1 (for example, a real regression beyond the committed baseline), this single-line step still returns tee's successful exit status because pipefail is not enabled. That means the mandatory benchmark suite can report green even though the benchmark printed REGRESSION and exited non-zero; use set -o pipefail or avoid piping the command directly to tee.
Useful? React with 👍 / 👎.
Closes #10
Summary
This repo ships prebuilt release artifacts (binaries, npm/pypi/Homebrew wrapper packages, install scripts) rather than compiled application source, so this PR implements the foundation/first vertical slice of the quality gate scoped to what actually lives here today: the Python release-integrity tooling under
scripts/, plus the packaging/version metadata it audits..github/workflows/quality-gate.yml: required jobs forlint(ruff),unit(pytest + coverage, OS × Python matrix: ubuntu/windows/macos × 3.11/3.12, withpytest-rerunfailuresauto-retry for flaky tests),integration(runs the realscripts/verify_distribution_consistency.pyaudit),security(bandit + pip-audit + gitleaks secret scan), andbenchmark(runtime vs. committed baseline with a configurable regression threshold). All fan into one requiredquality-gatestatus check.version.txt(3.0.2) vs.simplicio-update-manifest.json(3.5.2) drift the audit script already flagged as an ERROR but that nothing enforced — and added a regression test (test_version_txt_matches_update_manifest_regression) pinning the fix, plus full unit test coverage for the audit and new benchmark scripts (93% coverage onscripts/, ≥85% enforced in CI).docs/ci-quality-gate.md: documents pipeline stages and expected total time budget (~3-6 min), coverage policy, the "every fixed bug needs a regression test" policy, flaky-test policy, the "no skipping tests without a registered justification" exception policy, and the manual branch-protection step a repo admin still needs to flip on (see below).Acceptance criteria status
quality-gatejob fans in lint/unit/integration/security/benchmark.--cov-fail-under=85in theunitjob.actions/upload-artifact.docs/ci-quality-gate.md.Out of scope / follow-ups (documented in
docs/ci-quality-gate.md)install.sh/install.ps1) running in disposable containers/VMs — heavier scope, separate PR.docs/ci-quality-gate.md.Test plan
pytest tests/ --cov=scripts --cov-report=term-missing --cov-fail-under=85passes locally (93% coverage, 13 tests).ruff check .passes locally.python scripts/verify_distribution_consistency.pyexits 0 against this checkout.python scripts/bench_verify_distribution_consistency.pypasses against the committed baseline.🤖 Generated with Claude Code