hyperi-ci 2.7.1__tar.gz → 2.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/workflows/_release-tail.yml +10 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/workflows/ci.yml +27 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/workflows/go-ci.yml +30 -6
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/workflows/python-ci.yml +30 -6
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/workflows/rust-ci.yml +30 -6
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/workflows/ts-ci.yml +30 -6
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/PKG-INFO +1 -1
- hyperi_ci-2.7.2/VERSION +1 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/ARCHITECTURE.md +18 -7
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/LESSONS.md +4 -2
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/cli.py +17 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/dispatch.py +19 -9
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/quality/commit_validation.py +44 -6
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_commit_validation.py +94 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_quality_ignores.py +11 -2
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_workflow_consistency.py +60 -10
- hyperi_ci-2.7.1/VERSION +0 -1
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.gitattributes +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/actions/predict-version/action.yml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/actions/setup-osv-scanner/action.yml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/actions/setup-runtime/action.yml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/actions/setup-semantic-release/action.yml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.github/actions/setup-semantic-release/default.releaserc.json +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.gitignore +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.hyperi-ci.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/.releaserc.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/AI-TRAINING-POLICY.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/CHANGELOG.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/COMMERCIAL.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/CONTRIBUTING.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/LICENSE +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/SECURITY.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/config/commit-types.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/config/org.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/config/runners.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/config/secrets-access.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/config/versions.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/ARC-RUNNERS.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/CI-LESSONS.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/DESIGN.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/FLOW.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/JFROG-MIGRATION.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/MIGRATION-GUIDE.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/PGO-WORKLOAD-GUIDE.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/dependencies/DEPS-PINNING.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/dependencies/WORKFLOW-PINNING.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/deployment/CONTRACT-IDENTITY.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/deployment/CONTRACT.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/deployment/TIERS.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/deployment-contract.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/languages/GO.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/languages/PYTHON.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/languages/RUST.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/languages/TYPESCRIPT.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/migration/CODEBERG-SECRETS-AND-CI.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/migration/JFROG.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/migration/ONBOARDING.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/migration/codeberg-secrets-and-ci.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/migration/codeberg.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/migration/deployment-contract-tier3.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/runtime/PGO-BOLT.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/runtime/RUNNERS.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/runtime/TESTENV.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/rust.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/docs/typescript.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/pyproject.toml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/renovate.json +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/robots.txt +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/scripts/check-workflow-interfaces.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/scripts/pre-commit-versions.sh +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/scripts/recover-tags.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/scripts/setup-rust-dev.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/scripts/sync-secrets-access.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/scripts/update-versions.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/argocd/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/argocd/gitops_push.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/argocd/stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/common.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/defaults.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/native-deps/golang.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/native-deps/python.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/native-deps/rust.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/native-deps/typescript.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/org.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/toolchains/gcc.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config/toolchains/llvm.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/config.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/binary_stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/build.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/compose.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/detect.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/labels.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/manifest.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/registry.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/container/templates.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/cli.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/contract.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/detect.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/anchors/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/anchors/argocd.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/anchors/dockerfile.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/anchors/helm.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/cli.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/errors.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/model.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/overlay/render.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/registry.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/scaffold.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/topology/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/topology/resolve.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/deployment/topology/stitch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/detect.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gh.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/.gitbook.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/.gitignore +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/CODEOWNERS +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/LICENSE +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/argocd/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/argocd/applicationsets/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/argocd/appprojects/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/argocd/bootstrap/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/concepts/architecture.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/concepts/overview.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/how-to/add-app.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/how-to/add-environment.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/how-to/add-topology.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/index.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/operations/disaster-recovery.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/operations/rollback.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/quickstart.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/reference/sync-waves.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/docs/reference/topology-schema.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/mkdocs.yml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/pull_request_template.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/terraform/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/terraform/aws/environments/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/terraform/aws/modules/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/terraform/rancher/clusters/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/terraform/rancher/modules/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/topologies/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/values/.gitkeep +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/workflows/docs.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/workflows/stitch-and-publish.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/gitops_templates/workflows/validate.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/helm/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/helm/stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/init.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/init_gitops.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/install_deps.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/_build_common.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/golang/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/golang/build.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/golang/publish.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/golang/quality.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/golang/test.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/python/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/python/build.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/python/publish.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/python/quality.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/python/test.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/quality_common.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/build.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/optimize.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/pgo.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/publish.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/quality.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/rust/test.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/_common.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/build.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/install_deps.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/publish.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/quality.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/languages/typescript/test.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/licenses.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/logs.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/migrate.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/native_deps.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/publish/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/publish/binaries.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/publish/dispatch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/publish_binaries.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/push.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/quality/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/quality/gitleaks.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/quality/ignores.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/quality/osv_scanner.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/quality/predicted_bump.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/release.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/stamp.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/trigger.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/upgrade.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/src/hyperi_ci/watch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/pgo-workload/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/pgo-workload/grpc-server.sh +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/pgo-workload/http-server.sh +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/pgo-workload/kafka-consumer.sh +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/pgo-workload/kafka-producer.sh +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/pgo-workload/multi-protocol.sh +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/testenv/README.md +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/testenv/clickhouse-low-mem.xml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/testenv/clickhouse.compose.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/templates/testenv/redpanda.compose.yaml +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/argocd/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/argocd/test_gitops_push.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/argocd/test_stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/overlay/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/overlay/test_argocd_anchors.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/overlay/test_cli.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/overlay/test_dockerfile_anchors.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/overlay/test_helm_anchors.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/overlay/test_model.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/topology/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/topology/test_resolve.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/deployment/topology/test_stitch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/helm/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/helm/test_stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/helm/test_stage_topology_mode.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/integration/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/integration/test_rust_build_optimize.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/__init__.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/test_contract.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/test_detect_tier.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/test_emit_artefacts_cli.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/test_registry_cascade.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/test_scaffold.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/deployment/test_stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_build_common.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_cli.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_cli_init_gitops.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_cli_stitch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_common.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_config.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_binary_stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_build.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_compose.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_detect.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_labels.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_manifest.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_registry.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_stage.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_container_templates.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_detect.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_dispatch_alias.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_dispatch_status.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_gh.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_init.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_init_gitops.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_init_topology.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_licenses.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_migrate.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_native_deps.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_osv_scanner.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_predicted_bump.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_publish.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_publish_dispatch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_push.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_quality_ignore_wiring.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_recover_tags.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_release_version.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_rust_optimize.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_rust_pgo.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_rust_quality.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_stamp.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_typescript_quality.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_update_versions.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_upgrade.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_watch.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/tests/unit/test_workflow_interfaces.py +0 -0
- {hyperi_ci-2.7.1 → hyperi_ci-2.7.2}/uv.lock +0 -0
|
@@ -70,6 +70,10 @@ on:
|
|
|
70
70
|
type: string
|
|
71
71
|
default: "stable"
|
|
72
72
|
description: "Rust toolchain (only used when language=rust)"
|
|
73
|
+
submodules:
|
|
74
|
+
type: string
|
|
75
|
+
default: ""
|
|
76
|
+
description: "Space-separated submodule paths to init before the container build (e.g. 'schemas'), so a Dockerfile can bake submodule content. Empty (default) inits nothing."
|
|
73
77
|
|
|
74
78
|
env:
|
|
75
79
|
HYPERCI_INSTALL: uvx --no-cache --refresh hyperi-ci
|
|
@@ -108,6 +112,12 @@ jobs:
|
|
|
108
112
|
with:
|
|
109
113
|
ref: ${{ inputs.tag || github.ref }}
|
|
110
114
|
|
|
115
|
+
- name: Init submodules
|
|
116
|
+
if: ${{ inputs.submodules != '' }}
|
|
117
|
+
env:
|
|
118
|
+
SUBMODULES: ${{ inputs.submodules }}
|
|
119
|
+
run: git submodule update --init --depth 1 $SUBMODULES
|
|
120
|
+
|
|
111
121
|
- name: Install uv
|
|
112
122
|
# Needed to run the resolve step below. Cheap, no Docker Hub —
|
|
113
123
|
# so a library never pays the Buildx/Docker-Hub cost (issue #33).
|
|
@@ -70,6 +70,33 @@ jobs:
|
|
|
70
70
|
from-head: ${{ inputs.from-head }}
|
|
71
71
|
bump: ${{ inputs.bump }}
|
|
72
72
|
|
|
73
|
+
commit-check:
|
|
74
|
+
name: Commit messages
|
|
75
|
+
# Landing gate for conventional-commit messages -- dogfoods the same job
|
|
76
|
+
# the reusable <lang>-ci.yml workflows now ship. Deliberately NOT gated on
|
|
77
|
+
# plan.outputs.run-checks: it must validate what actually reaches main on
|
|
78
|
+
# EVERY merge, not only publish-worthy pushes. Fatal on push to main (what
|
|
79
|
+
# lands); advisory on pull_request. Runs the LOCAL branch code (uv run) so
|
|
80
|
+
# this repo's own PRs exercise the change. See CLAUDE.md CI gate doctrine.
|
|
81
|
+
if: >-
|
|
82
|
+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
|
83
|
+
github.event_name == 'pull_request'
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
87
|
+
with:
|
|
88
|
+
fetch-depth: 0
|
|
89
|
+
- name: Install uv
|
|
90
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
91
|
+
with:
|
|
92
|
+
enable-cache: true
|
|
93
|
+
- name: Set up Python
|
|
94
|
+
run: uv python install 3.12
|
|
95
|
+
- name: Install dependencies
|
|
96
|
+
run: uv sync --no-sources
|
|
97
|
+
- name: Validate commit messages
|
|
98
|
+
run: uv run --no-sources hyperi-ci check-commits
|
|
99
|
+
|
|
73
100
|
quality:
|
|
74
101
|
name: Quality
|
|
75
102
|
runs-on: ubuntu-latest
|
|
@@ -155,6 +155,30 @@ jobs:
|
|
|
155
155
|
fi
|
|
156
156
|
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
|
|
157
157
|
|
|
158
|
+
commit-check:
|
|
159
|
+
name: Commit messages
|
|
160
|
+
# Landing gate for conventional-commit messages. Deliberately NOT gated
|
|
161
|
+
# on plan.outputs.run-checks: a cheap git-log + regex check must validate
|
|
162
|
+
# what actually reaches main on EVERY merge, not only publish-worthy
|
|
163
|
+
# pushes (all the quality job covers). Fatal on push to main (what lands);
|
|
164
|
+
# advisory on pull_request (branch commits may be squashed away -- see
|
|
165
|
+
# commit_validation.run). Feature-branch pushes skip it, so the fast
|
|
166
|
+
# chore-skip path is untouched. See CLAUDE.md CI gate doctrine.
|
|
167
|
+
if: >-
|
|
168
|
+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
|
169
|
+
github.event_name == 'pull_request'
|
|
170
|
+
runs-on: ubuntu-latest
|
|
171
|
+
steps:
|
|
172
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
173
|
+
with:
|
|
174
|
+
fetch-depth: 0
|
|
175
|
+
- name: Install uv
|
|
176
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
177
|
+
with:
|
|
178
|
+
enable-cache: false
|
|
179
|
+
- name: Validate commit messages
|
|
180
|
+
run: ${{ env.HYPERCI_INSTALL }} check-commits
|
|
181
|
+
|
|
158
182
|
quality:
|
|
159
183
|
name: Quality
|
|
160
184
|
needs: [plan]
|
|
@@ -200,12 +224,11 @@ jobs:
|
|
|
200
224
|
- name: Install native dependencies
|
|
201
225
|
run: ${{ env.HYPERCI_INSTALL }} install-native-deps golang
|
|
202
226
|
|
|
203
|
-
- name: Deepen history for
|
|
204
|
-
#
|
|
205
|
-
#
|
|
206
|
-
#
|
|
207
|
-
#
|
|
208
|
-
# and warns loudly -- it never silently passes having checked nothing.
|
|
227
|
+
- name: Deepen history for secret scan
|
|
228
|
+
# gitleaks scans the branch git log for committed secrets; a depth-1
|
|
229
|
+
# checkout would only see HEAD. Deepen so the scan covers the pushed
|
|
230
|
+
# range. Conventional-commit validation moved to the commit-check job
|
|
231
|
+
# (its own fetch-depth: 0 checkout). Harmless on an already-full clone.
|
|
209
232
|
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
|
|
210
233
|
run: git fetch --deepen=200 origin
|
|
211
234
|
|
|
@@ -356,4 +379,5 @@ jobs:
|
|
|
356
379
|
from-head: ${{ inputs.from-head }}
|
|
357
380
|
bump: ${{ inputs.bump }}
|
|
358
381
|
publish-target: ${{ inputs.publish-target }}
|
|
382
|
+
submodules: ${{ inputs.submodules }}
|
|
359
383
|
secrets: inherit
|
|
@@ -140,6 +140,30 @@ jobs:
|
|
|
140
140
|
from-head: ${{ inputs.from-head }}
|
|
141
141
|
bump: ${{ inputs.bump }}
|
|
142
142
|
|
|
143
|
+
commit-check:
|
|
144
|
+
name: Commit messages
|
|
145
|
+
# Landing gate for conventional-commit messages. Deliberately NOT gated
|
|
146
|
+
# on plan.outputs.run-checks: a cheap git-log + regex check must validate
|
|
147
|
+
# what actually reaches main on EVERY merge, not only publish-worthy
|
|
148
|
+
# pushes (all the quality job covers). Fatal on push to main (what lands);
|
|
149
|
+
# advisory on pull_request (branch commits may be squashed away -- see
|
|
150
|
+
# commit_validation.run). Feature-branch pushes skip it, so the fast
|
|
151
|
+
# chore-skip path is untouched. See CLAUDE.md CI gate doctrine.
|
|
152
|
+
if: >-
|
|
153
|
+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
|
154
|
+
github.event_name == 'pull_request'
|
|
155
|
+
runs-on: ubuntu-latest
|
|
156
|
+
steps:
|
|
157
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
158
|
+
with:
|
|
159
|
+
fetch-depth: 0
|
|
160
|
+
- name: Install uv
|
|
161
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
162
|
+
with:
|
|
163
|
+
enable-cache: false
|
|
164
|
+
- name: Validate commit messages
|
|
165
|
+
run: ${{ env.HYPERCI_INSTALL }} check-commits
|
|
166
|
+
|
|
143
167
|
quality:
|
|
144
168
|
name: Quality
|
|
145
169
|
needs: [plan]
|
|
@@ -174,12 +198,11 @@ jobs:
|
|
|
174
198
|
- name: Install dependencies
|
|
175
199
|
run: uv sync --frozen --all-extras
|
|
176
200
|
|
|
177
|
-
- name: Deepen history for
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
#
|
|
181
|
-
#
|
|
182
|
-
# and warns loudly -- it never silently passes having checked nothing.
|
|
201
|
+
- name: Deepen history for secret scan
|
|
202
|
+
# gitleaks scans the branch git log for committed secrets; a depth-1
|
|
203
|
+
# checkout would only see HEAD. Deepen so the scan covers the pushed
|
|
204
|
+
# range. Conventional-commit validation moved to the commit-check job
|
|
205
|
+
# (its own fetch-depth: 0 checkout). Harmless on an already-full clone.
|
|
183
206
|
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
|
|
184
207
|
run: git fetch --deepen=200 origin
|
|
185
208
|
|
|
@@ -354,4 +377,5 @@ jobs:
|
|
|
354
377
|
bump: ${{ inputs.bump }}
|
|
355
378
|
publish-target: ${{ inputs.publish-target }}
|
|
356
379
|
python-version: ${{ inputs.python-version }}
|
|
380
|
+
submodules: ${{ inputs.submodules }}
|
|
357
381
|
secrets: inherit
|
|
@@ -173,6 +173,30 @@ jobs:
|
|
|
173
173
|
fi
|
|
174
174
|
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
|
|
175
175
|
|
|
176
|
+
commit-check:
|
|
177
|
+
name: Commit messages
|
|
178
|
+
# Landing gate for conventional-commit messages. Deliberately NOT gated
|
|
179
|
+
# on plan.outputs.run-checks: a cheap git-log + regex check must validate
|
|
180
|
+
# what actually reaches main on EVERY merge, not only publish-worthy
|
|
181
|
+
# pushes (all the quality job covers). Fatal on push to main (what lands);
|
|
182
|
+
# advisory on pull_request (branch commits may be squashed away -- see
|
|
183
|
+
# commit_validation.run). Feature-branch pushes skip it, so the fast
|
|
184
|
+
# chore-skip path is untouched. See CLAUDE.md CI gate doctrine.
|
|
185
|
+
if: >-
|
|
186
|
+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
|
187
|
+
github.event_name == 'pull_request'
|
|
188
|
+
runs-on: ubuntu-latest
|
|
189
|
+
steps:
|
|
190
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
191
|
+
with:
|
|
192
|
+
fetch-depth: 0
|
|
193
|
+
- name: Install uv
|
|
194
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
195
|
+
with:
|
|
196
|
+
enable-cache: false
|
|
197
|
+
- name: Validate commit messages
|
|
198
|
+
run: ${{ env.HYPERCI_INSTALL }} check-commits
|
|
199
|
+
|
|
176
200
|
quality:
|
|
177
201
|
name: Quality
|
|
178
202
|
needs: [plan]
|
|
@@ -226,12 +250,11 @@ jobs:
|
|
|
226
250
|
- name: Setup osv-scanner
|
|
227
251
|
uses: hyperi-io/hyperi-ci/.github/actions/setup-osv-scanner@main
|
|
228
252
|
|
|
229
|
-
- name: Deepen history for
|
|
230
|
-
#
|
|
231
|
-
#
|
|
232
|
-
#
|
|
233
|
-
#
|
|
234
|
-
# and warns loudly -- it never silently passes having checked nothing.
|
|
253
|
+
- name: Deepen history for secret scan
|
|
254
|
+
# gitleaks scans the branch git log for committed secrets; a depth-1
|
|
255
|
+
# checkout would only see HEAD. Deepen so the scan covers the pushed
|
|
256
|
+
# range. Conventional-commit validation moved to the commit-check job
|
|
257
|
+
# (its own fetch-depth: 0 checkout). Harmless on an already-full clone.
|
|
235
258
|
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
|
|
236
259
|
run: git fetch --deepen=200 origin
|
|
237
260
|
|
|
@@ -411,4 +434,5 @@ jobs:
|
|
|
411
434
|
bump: ${{ inputs.bump }}
|
|
412
435
|
publish-target: ${{ inputs.publish-target }}
|
|
413
436
|
rust-toolchain: ${{ inputs.rust-toolchain }}
|
|
437
|
+
submodules: ${{ inputs.submodules }}
|
|
414
438
|
secrets: inherit
|
|
@@ -137,6 +137,30 @@ jobs:
|
|
|
137
137
|
from-head: ${{ inputs.from-head }}
|
|
138
138
|
bump: ${{ inputs.bump }}
|
|
139
139
|
|
|
140
|
+
commit-check:
|
|
141
|
+
name: Commit messages
|
|
142
|
+
# Landing gate for conventional-commit messages. Deliberately NOT gated
|
|
143
|
+
# on plan.outputs.run-checks: a cheap git-log + regex check must validate
|
|
144
|
+
# what actually reaches main on EVERY merge, not only publish-worthy
|
|
145
|
+
# pushes (all the quality job covers). Fatal on push to main (what lands);
|
|
146
|
+
# advisory on pull_request (branch commits may be squashed away -- see
|
|
147
|
+
# commit_validation.run). Feature-branch pushes skip it, so the fast
|
|
148
|
+
# chore-skip path is untouched. See CLAUDE.md CI gate doctrine.
|
|
149
|
+
if: >-
|
|
150
|
+
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
|
|
151
|
+
github.event_name == 'pull_request'
|
|
152
|
+
runs-on: ubuntu-latest
|
|
153
|
+
steps:
|
|
154
|
+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
155
|
+
with:
|
|
156
|
+
fetch-depth: 0
|
|
157
|
+
- name: Install uv
|
|
158
|
+
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
159
|
+
with:
|
|
160
|
+
enable-cache: false
|
|
161
|
+
- name: Validate commit messages
|
|
162
|
+
run: ${{ env.HYPERCI_INSTALL }} check-commits
|
|
163
|
+
|
|
140
164
|
quality:
|
|
141
165
|
name: Quality
|
|
142
166
|
needs: [plan]
|
|
@@ -197,12 +221,11 @@ jobs:
|
|
|
197
221
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
198
222
|
"$HOME/.local/bin/osv-scanner" --version
|
|
199
223
|
|
|
200
|
-
- name: Deepen history for
|
|
201
|
-
#
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
#
|
|
205
|
-
# and warns loudly -- it never silently passes having checked nothing.
|
|
224
|
+
- name: Deepen history for secret scan
|
|
225
|
+
# gitleaks scans the branch git log for committed secrets; a depth-1
|
|
226
|
+
# checkout would only see HEAD. Deepen so the scan covers the pushed
|
|
227
|
+
# range. Conventional-commit validation moved to the commit-check job
|
|
228
|
+
# (its own fetch-depth: 0 checkout). Harmless on an already-full clone.
|
|
206
229
|
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
|
|
207
230
|
run: git fetch --deepen=200 origin
|
|
208
231
|
|
|
@@ -364,4 +387,5 @@ jobs:
|
|
|
364
387
|
from-head: ${{ inputs.from-head }}
|
|
365
388
|
bump: ${{ inputs.bump }}
|
|
366
389
|
publish-target: ${{ inputs.publish-target }}
|
|
390
|
+
submodules: ${{ inputs.submodules }}
|
|
367
391
|
secrets: inherit
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hyperi-ci
|
|
3
|
-
Version: 2.7.
|
|
3
|
+
Version: 2.7.2
|
|
4
4
|
Summary: HyperI CI/CD CLI tool — multi-language build, test, and publish automation
|
|
5
5
|
Project-URL: Homepage, https://github.com/hyperi-io/hyperi-ci
|
|
6
6
|
Project-URL: Repository, https://github.com/hyperi-io/hyperi-ci
|
hyperi_ci-2.7.2/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.7.2
|
|
@@ -82,11 +82,21 @@ the single place language divergence is allowed.
|
|
|
82
82
|
| Job | needs | if | Purpose |
|
|
83
83
|
|---|---|---|---|
|
|
84
84
|
| `plan` | — | always | Decide if this run is publish-worthy; emit gate outputs |
|
|
85
|
+
| `commit-check` | — | push-to-main OR `pull_request` | Conventional-commit **landing gate** — fatal on push to main (validates what lands), advisory on PRs. NOT `run-checks`-gated (see below) |
|
|
85
86
|
| `quality` | `[plan]` | `run-checks` | Lint / typecheck / security scan |
|
|
86
87
|
| `test` | `[plan]` | `run-checks` | Unit + integration tests |
|
|
87
88
|
| `build` | `[plan, quality, test]` | `run-build` | Compile binaries / wheels / packages, stamp version, upload `dist/` |
|
|
88
89
|
| `release-tail` | `[plan, build]` | own gates | Container + tag-and-publish, via shared `_release-tail.yml` |
|
|
89
90
|
|
|
91
|
+
`commit-check` is deliberately **independent of `plan` / `run-checks`**: that
|
|
92
|
+
gate skips the quality job on ordinary (non-publish) merges to main, so a bad
|
|
93
|
+
conventional-commit message could otherwise land unvalidated. It is a cheap
|
|
94
|
+
git-log + regex check (no compile/publish), fatal on the push that actually
|
|
95
|
+
reaches main and advisory on PRs (branch commits may be squashed away — only
|
|
96
|
+
the squash subject lands). Feature-branch pushes skip it, preserving the
|
|
97
|
+
chore-skip fast path. Logic: `hyperi_ci.quality.commit_validation.run`; the
|
|
98
|
+
local `hyperi-ci check` runs the same validation over `origin/main..HEAD`.
|
|
99
|
+
|
|
90
100
|
### Gate outputs (computed in `plan`)
|
|
91
101
|
|
|
92
102
|
| Output | True when | Effect |
|
|
@@ -115,13 +125,14 @@ flowchart LR
|
|
|
115
125
|
|
|
116
126
|
### What runs when
|
|
117
127
|
|
|
118
|
-
| Push type | plan | quality | test | build | container | tag+publish |
|
|
119
|
-
|
|
120
|
-
| `chore:` / `docs:` to main | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
|
|
121
|
-
| `feat:`/`fix:` to main, no `Publish:` trailer | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
|
|
122
|
-
| `feat:`/`fix:` to main + `Publish: true` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
123
|
-
| Pull request | ✓ | ✓ | ✓ | ✗ | ✗ | ✗ |
|
|
124
|
-
| `workflow_dispatch` (retroactive publish) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
128
|
+
| Push type | plan | commit-check | quality | test | build | container | tag+publish |
|
|
129
|
+
|---|---|---|---|---|---|---|---|
|
|
130
|
+
| `chore:` / `docs:` to main | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
|
|
131
|
+
| `feat:`/`fix:` to main, no `Publish:` trailer | ✓ | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ |
|
|
132
|
+
| `feat:`/`fix:` to main + `Publish: true` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
133
|
+
| Pull request | ✓ | ✓ advisory | ✓ | ✓ | ✗ | ✗ | ✗ |
|
|
134
|
+
| `workflow_dispatch` (retroactive publish) | ✓ | ✗ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
|
135
|
+
| push to a feature branch | ✓ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
|
|
125
136
|
|
|
126
137
|
Tag-on-publish doctrine: a commit landing on main produces no tag and no
|
|
127
138
|
artefacts. The operator opts in with `hyperi-ci push --publish` (adds the
|
|
@@ -299,10 +299,12 @@ build to ensure fresh artifacts, also via `hyperi-ci run build`.
|
|
|
299
299
|
- Detection: directory-based > marker-based > conftest-based
|
|
300
300
|
- Coverage: separate `.coverage.<tier>` files, combine at end
|
|
301
301
|
- No test directory: exit 0 (graceful skip)
|
|
302
|
-
- Submodule-dependent tests:
|
|
302
|
+
- Submodule-dependent tests or container builds:
|
|
303
303
|
- Public submodule: declare `submodules: schemas` in `.hyperi-ci.yaml`;
|
|
304
304
|
`hyperi-ci init` renders it as the reusable-workflow `submodules` input
|
|
305
|
-
in `ci.yml
|
|
305
|
+
in `ci.yml`. The test job checks it out so the tests run, and the
|
|
306
|
+
container build checks it out so a Dockerfile can bake submodule
|
|
307
|
+
content into the image.
|
|
306
308
|
- Private submodule (e.g. `dfe-schemas` while private): GITHUB_TOKEN can't
|
|
307
309
|
clone it, so mark dependent tests with
|
|
308
310
|
`@pytest.mark.skipif(not schemas_dir.exists(), reason="submodule not checked out")`
|
|
@@ -674,6 +674,23 @@ def check_commit_cmd(
|
|
|
674
674
|
raise typer.Exit(1)
|
|
675
675
|
|
|
676
676
|
|
|
677
|
+
@app.command(name="check-commits")
|
|
678
|
+
def check_commits_cmd() -> None:
|
|
679
|
+
"""Validate the conventional-commit messages in the CI push/PR range.
|
|
680
|
+
|
|
681
|
+
Landing-gate counterpart to `check-commit` (single message, local
|
|
682
|
+
commit-msg hook). Resolves the range from the CI event -- push
|
|
683
|
+
before..after (what lands on main) or PR base..HEAD -- validates each
|
|
684
|
+
commit, and is FATAL on push but ADVISORY on pull_request (branch
|
|
685
|
+
commits may be squashed away). CI-only; a no-op locally. Driven by the
|
|
686
|
+
dedicated `commit-check` workflow job, NOT the run-checks-gated quality
|
|
687
|
+
job -- so a merge to main is validated even when it is not a publish.
|
|
688
|
+
"""
|
|
689
|
+
from hyperi_ci.quality.commit_validation import run
|
|
690
|
+
|
|
691
|
+
raise typer.Exit(run())
|
|
692
|
+
|
|
693
|
+
|
|
677
694
|
def _publish_impl(
|
|
678
695
|
tag: str | None,
|
|
679
696
|
list_tags: bool,
|
|
@@ -169,22 +169,30 @@ def stage_setup(language: str, config: CIConfig) -> int:
|
|
|
169
169
|
return rc
|
|
170
170
|
|
|
171
171
|
|
|
172
|
-
def stage_quality(language: str, config: CIConfig) -> int:
|
|
172
|
+
def stage_quality(language: str, config: CIConfig, *, local: bool = False) -> int:
|
|
173
173
|
"""Quality checks — gitleaks + language-specific checks."""
|
|
174
174
|
if not config.get("quality.enabled", True):
|
|
175
175
|
info("Quality checks disabled in configuration")
|
|
176
176
|
return 0
|
|
177
177
|
|
|
178
|
-
# Cross-language checks first
|
|
178
|
+
# Cross-language checks first.
|
|
179
179
|
with group("Gitleaks secret scanning"):
|
|
180
180
|
rc = gitleaks.run(config)
|
|
181
181
|
if rc != 0:
|
|
182
182
|
return rc
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
# Commit-message validation. In CI this is the dedicated `commit-check`
|
|
185
|
+
# workflow job -- it runs on every merge to main (not just the
|
|
186
|
+
# publish-worthy pushes the run-checks-gated quality job covers) and is
|
|
187
|
+
# advisory on PRs. There is no such job for a LOCAL `hyperi-ci check`,
|
|
188
|
+
# so run it here over the unpushed range (origin/main..HEAD) as a
|
|
189
|
+
# pre-push backstop -- catch a bad message before the push, not after.
|
|
190
|
+
# See hyperi_ci.quality.commit_validation.run + CLAUDE.md CI gate doctrine.
|
|
191
|
+
if local:
|
|
192
|
+
with group("Commit message validation"):
|
|
193
|
+
rc = commit_validation.run(config, local=True)
|
|
194
|
+
if rc != 0:
|
|
195
|
+
return rc
|
|
188
196
|
|
|
189
197
|
extra_env: dict[str, str] = {}
|
|
190
198
|
if language == "rust":
|
|
@@ -440,9 +448,11 @@ def run_stage(
|
|
|
440
448
|
info(f"Project status: {status}{_STATUS_CLARIFIER.get(status, '')}")
|
|
441
449
|
|
|
442
450
|
handler = _STAGE_HANDLERS[stage]
|
|
443
|
-
if stage
|
|
444
|
-
#
|
|
445
|
-
#
|
|
451
|
+
if stage in ("build", "quality"):
|
|
452
|
+
# build + quality take `local` (build skips cross-targets; quality
|
|
453
|
+
# runs the commit-message backstop only for a local `hyperi-ci
|
|
454
|
+
# check`). _STAGE_HANDLERS is typed to the common (no-local)
|
|
455
|
+
# signature, so cast for this branch.
|
|
446
456
|
rc = cast("Any", handler)(language, config, local=local)
|
|
447
457
|
else:
|
|
448
458
|
rc = handler(language, config)
|
|
@@ -498,12 +498,35 @@ def _get_commits_to_validate() -> tuple[list[tuple[str, str]], bool]:
|
|
|
498
498
|
return [], False
|
|
499
499
|
|
|
500
500
|
|
|
501
|
-
def run(
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
501
|
+
def run(
|
|
502
|
+
config: CIConfig | None = None,
|
|
503
|
+
extra_env: dict[str, str] | None = None,
|
|
504
|
+
*,
|
|
505
|
+
local: bool = False,
|
|
506
|
+
) -> int:
|
|
507
|
+
"""Validate commit messages in the CI push/PR range (or the local range).
|
|
508
|
+
|
|
509
|
+
``config`` is unused (kept for call-site symmetry) so the CLI
|
|
510
|
+
``check-commits`` command can call ``run()`` bare.
|
|
511
|
+
|
|
512
|
+
Behaviour by event:
|
|
513
|
+
|
|
514
|
+
- ``push`` (what lands on main) -> FATAL: a failing commit returns 1.
|
|
515
|
+
This is the real landing gate -- the run-checks gate skips the
|
|
516
|
+
quality job on non-publish main pushes, so this dedicated check is
|
|
517
|
+
where merge-to-main enforcement lives.
|
|
518
|
+
- ``pull_request`` -> ADVISORY: failures are warned, returns 0. The
|
|
519
|
+
branch commits validated on a PR may be discarded by a squash-merge
|
|
520
|
+
(only the squash subject lands) and are never re-validated on the
|
|
521
|
+
merge push, so a PR gets feedback rather than a hard red.
|
|
522
|
+
|
|
523
|
+
``local=True`` runs the same check outside CI (``hyperi-ci check``
|
|
524
|
+
pre-push backstop): with no CI event the range falls back to
|
|
525
|
+
``origin/main..HEAD`` (the unpushed commits) and is FATAL, so a bad
|
|
526
|
+
message is caught before the push, not after. Without ``local`` the
|
|
527
|
+
check is a no-op outside CI (the commit-msg hook covers authoring).
|
|
505
528
|
"""
|
|
506
|
-
if not is_ci():
|
|
529
|
+
if not local and not is_ci():
|
|
507
530
|
info("Skipping commit message validation (not in CI)")
|
|
508
531
|
return 0
|
|
509
532
|
|
|
@@ -543,10 +566,25 @@ def run(config: CIConfig, extra_env: dict[str, str] | None = None) -> int:
|
|
|
543
566
|
failures.append((commit_hash, full_msg, result))
|
|
544
567
|
|
|
545
568
|
if failures:
|
|
569
|
+
# Advisory on a PR, fatal on push. See the run() docstring: PR
|
|
570
|
+
# branch commits may be squashed away and are never re-validated
|
|
571
|
+
# on the merge-to-main push, so a PR gets feedback -- not a hard
|
|
572
|
+
# red -- while the push that lands on main stays enforced.
|
|
573
|
+
advisory = os.environ.get("GITHUB_EVENT_NAME", "") == "pull_request"
|
|
574
|
+
emit = warn if advisory else error
|
|
546
575
|
for commit_hash, full_msg, result in failures:
|
|
547
576
|
short_hash = commit_hash[:8]
|
|
548
577
|
rejection = format_rejection(result, full_msg)
|
|
549
|
-
|
|
578
|
+
emit(f"[{short_hash}] {rejection}")
|
|
579
|
+
|
|
580
|
+
if advisory:
|
|
581
|
+
warn(
|
|
582
|
+
f"{len(failures)} commit(s) would fail validation on merge to "
|
|
583
|
+
"main. Advisory on a PR -- only the commit(s) that LAND on main "
|
|
584
|
+
"are enforced. If you squash-merge, make the squash subject a "
|
|
585
|
+
"valid conventional commit (that single line is what lands)."
|
|
586
|
+
)
|
|
587
|
+
return 0
|
|
550
588
|
|
|
551
589
|
error(
|
|
552
590
|
f"{len(failures)} commit(s) failed validation. "
|
|
@@ -649,12 +649,17 @@ class TestRunDegraded:
|
|
|
649
649
|
payload = _write_push_event(tmp_path, "0" * 40, "HEAD")
|
|
650
650
|
monkeypatch.setenv("GITHUB_EVENT_PATH", str(payload))
|
|
651
651
|
monkeypatch.setattr(cv, "is_ci", lambda: True)
|
|
652
|
+
# Capture the (legitimate) degraded warning so it doesn't leak into
|
|
653
|
+
# CI logs from the test run itself.
|
|
654
|
+
warns: list[str] = []
|
|
655
|
+
monkeypatch.setattr(cv, "warn", lambda m: warns.append(m))
|
|
652
656
|
|
|
653
657
|
from hyperi_ci.config import CIConfig
|
|
654
658
|
|
|
655
659
|
rc = cv.run(CIConfig())
|
|
656
660
|
# Degraded, but HEAD is invalid -> must FAIL, not silent-pass.
|
|
657
661
|
assert rc == 1
|
|
662
|
+
assert any("DEGRADED" in w for w in warns) # warns loudly, never silent
|
|
658
663
|
|
|
659
664
|
def test_degraded_head_valid_passes(
|
|
660
665
|
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
@@ -666,6 +671,7 @@ class TestRunDegraded:
|
|
|
666
671
|
payload = _write_push_event(tmp_path, "0" * 40, "HEAD")
|
|
667
672
|
monkeypatch.setenv("GITHUB_EVENT_PATH", str(payload))
|
|
668
673
|
monkeypatch.setattr(cv, "is_ci", lambda: True)
|
|
674
|
+
monkeypatch.setattr(cv, "warn", lambda _m: None) # capture degraded warning
|
|
669
675
|
|
|
670
676
|
from hyperi_ci.config import CIConfig
|
|
671
677
|
|
|
@@ -673,6 +679,94 @@ class TestRunDegraded:
|
|
|
673
679
|
assert rc == 0
|
|
674
680
|
|
|
675
681
|
|
|
682
|
+
def _write_pr_event(tmp_path: Path, base_sha: str) -> Path:
|
|
683
|
+
payload = tmp_path / "event.json"
|
|
684
|
+
payload.write_text(json.dumps({"pull_request": {"base": {"sha": base_sha}}}))
|
|
685
|
+
return payload
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
class TestRunAdvisoryOnPR:
|
|
689
|
+
"""On a pull_request a failing commit is ADVISORY (warn, exit 0): branch
|
|
690
|
+
commits may be squashed away and are never re-validated on the merge-to-
|
|
691
|
+
main push. The push path stays FATAL (see TestRunDegraded)."""
|
|
692
|
+
|
|
693
|
+
def test_pr_failure_is_advisory(
|
|
694
|
+
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
695
|
+
) -> None:
|
|
696
|
+
repo = _repo(tmp_path)
|
|
697
|
+
base = _commit(repo, "fix: base")
|
|
698
|
+
# GitHub branch-normalised squashy subject -> no valid prefix.
|
|
699
|
+
_git(repo, "commit", "--allow-empty", "-q", "-m", "Feat/bad squashy subject")
|
|
700
|
+
monkeypatch.chdir(repo)
|
|
701
|
+
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
|
|
702
|
+
monkeypatch.setenv("GITHUB_EVENT_PATH", str(_write_pr_event(tmp_path, base)))
|
|
703
|
+
monkeypatch.setattr(cv, "is_ci", lambda: True)
|
|
704
|
+
warns: list[str] = []
|
|
705
|
+
errors: list[str] = []
|
|
706
|
+
monkeypatch.setattr(cv, "warn", lambda m: warns.append(m))
|
|
707
|
+
monkeypatch.setattr(cv, "error", lambda m: errors.append(m))
|
|
708
|
+
|
|
709
|
+
from hyperi_ci.config import CIConfig
|
|
710
|
+
|
|
711
|
+
rc = cv.run(CIConfig())
|
|
712
|
+
# Advisory: a bad commit must NOT hard-fail a PR...
|
|
713
|
+
assert rc == 0
|
|
714
|
+
# ...but the problem is still surfaced, via warn (not error).
|
|
715
|
+
assert any("would fail validation on merge to main" in w for w in warns)
|
|
716
|
+
assert errors == []
|
|
717
|
+
|
|
718
|
+
def test_pr_all_valid_passes(
|
|
719
|
+
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
720
|
+
) -> None:
|
|
721
|
+
repo = _repo(tmp_path)
|
|
722
|
+
base = _commit(repo, "fix: base")
|
|
723
|
+
_commit(repo, "fix: good change")
|
|
724
|
+
monkeypatch.chdir(repo)
|
|
725
|
+
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
|
|
726
|
+
monkeypatch.setenv("GITHUB_EVENT_PATH", str(_write_pr_event(tmp_path, base)))
|
|
727
|
+
monkeypatch.setattr(cv, "is_ci", lambda: True)
|
|
728
|
+
|
|
729
|
+
from hyperi_ci.config import CIConfig
|
|
730
|
+
|
|
731
|
+
rc = cv.run(CIConfig())
|
|
732
|
+
assert rc == 0
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
class TestRunLocal:
|
|
736
|
+
"""`local=True` (hyperi-ci check pre-push) validates the unpushed range
|
|
737
|
+
outside CI and is FATAL -- catch a bad message before the push. Without
|
|
738
|
+
it, run() is a no-op outside CI."""
|
|
739
|
+
|
|
740
|
+
def test_local_validates_range_and_is_fatal(
|
|
741
|
+
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
742
|
+
) -> None:
|
|
743
|
+
repo = _repo(tmp_path)
|
|
744
|
+
# Simulate origin/main at the base, one unpushed bad commit on top.
|
|
745
|
+
_commit(repo, "fix: base")
|
|
746
|
+
_git(repo, "branch", "origin/main") # local ref standing in for origin
|
|
747
|
+
_git(repo, "commit", "--allow-empty", "-q", "-m", "Broken No Prefix")
|
|
748
|
+
monkeypatch.chdir(repo)
|
|
749
|
+
monkeypatch.delenv("GITHUB_EVENT_NAME", raising=False)
|
|
750
|
+
monkeypatch.setattr(cv, "is_ci", lambda: False)
|
|
751
|
+
monkeypatch.setattr(cv, "warn", lambda _m: None)
|
|
752
|
+
monkeypatch.setattr(cv, "error", lambda _m: None)
|
|
753
|
+
|
|
754
|
+
rc = cv.run(local=True)
|
|
755
|
+
assert rc == 1 # not in CI, but local=True -> fatal on the bad commit
|
|
756
|
+
|
|
757
|
+
def test_not_local_and_not_ci_is_noop(
|
|
758
|
+
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
759
|
+
) -> None:
|
|
760
|
+
repo = _repo(tmp_path)
|
|
761
|
+
_git(repo, "commit", "--allow-empty", "-q", "-m", "Broken No Prefix")
|
|
762
|
+
monkeypatch.chdir(repo)
|
|
763
|
+
monkeypatch.delenv("GITHUB_EVENT_NAME", raising=False)
|
|
764
|
+
monkeypatch.setattr(cv, "is_ci", lambda: False)
|
|
765
|
+
|
|
766
|
+
rc = cv.run() # no local, not CI -> skip entirely
|
|
767
|
+
assert rc == 0
|
|
768
|
+
|
|
769
|
+
|
|
676
770
|
def test_is_zero_sha() -> None:
|
|
677
771
|
assert cv._is_zero_sha("0" * 40) is True
|
|
678
772
|
assert cv._is_zero_sha("0" * 7) is True
|
|
@@ -195,7 +195,11 @@ class TestExpires:
|
|
|
195
195
|
assert len(entries) == 1
|
|
196
196
|
assert entries[0].expires == date.today() + timedelta(days=30)
|
|
197
197
|
|
|
198
|
-
def test_past_expiry_is_dropped(self) -> None:
|
|
198
|
+
def test_past_expiry_is_dropped(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
199
|
+
# Capture the lapse warning so it doesn't leak into CI logs as a false
|
|
200
|
+
# "quality.ignore lapsed" annotation (the drop is asserted; that the
|
|
201
|
+
# warning fires is covered by test_lapsed_entry_is_logged).
|
|
202
|
+
monkeypatch.setattr("hyperi_ci.quality.ignores.warn", lambda _m: None)
|
|
199
203
|
past = (date.today() - timedelta(days=1)).isoformat()
|
|
200
204
|
raw = {
|
|
201
205
|
"quality": {
|
|
@@ -252,7 +256,12 @@ class TestExpires:
|
|
|
252
256
|
}
|
|
253
257
|
)
|
|
254
258
|
|
|
255
|
-
def test_batch_with_expiry_drops_whole_stanza_when_past(
|
|
259
|
+
def test_batch_with_expiry_drops_whole_stanza_when_past(
|
|
260
|
+
self, monkeypatch: pytest.MonkeyPatch
|
|
261
|
+
) -> None:
|
|
262
|
+
# Capture the lapse warning (see test_past_expiry_is_dropped) so it
|
|
263
|
+
# doesn't surface as a false CI annotation.
|
|
264
|
+
monkeypatch.setattr("hyperi_ci.quality.ignores.warn", lambda _m: None)
|
|
256
265
|
past = (date.today() - timedelta(days=5)).isoformat()
|
|
257
266
|
raw = {
|
|
258
267
|
"quality": {
|