hyperi-ci 2.7.2__tar.gz → 2.7.3__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.
Files changed (289) hide show
  1. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/workflows/ci.yml +20 -0
  2. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/workflows/go-ci.yml +24 -0
  3. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/workflows/python-ci.yml +24 -0
  4. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/workflows/rust-ci.yml +24 -0
  5. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/workflows/ts-ci.yml +24 -0
  6. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.hyperi-ci.yaml +4 -0
  7. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/PKG-INFO +14 -1
  8. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/README.md +13 -0
  9. hyperi_ci-2.7.3/VERSION +1 -0
  10. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/ARCHITECTURE.md +1 -1
  11. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/DESIGN.md +1 -0
  12. hyperi_ci-2.7.3/docs/quality-gate.md +142 -0
  13. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/cli.py +25 -4
  14. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/defaults.yaml +1 -4
  15. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/dispatch.py +8 -1
  16. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/golang/quality.py +10 -13
  17. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/python/quality.py +14 -16
  18. hyperi_ci-2.7.3/src/hyperi_ci/languages/quality_common.py +131 -0
  19. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/quality.py +10 -13
  20. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/quality.py +10 -11
  21. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/quality/commit_validation.py +1 -1
  22. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/quality/gitleaks.py +3 -0
  23. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/quality/predicted_bump.py +2 -1
  24. hyperi_ci-2.7.3/src/hyperi_ci/quality/semgrep.py +98 -0
  25. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/watch.py +45 -0
  26. hyperi_ci-2.7.3/tests/unit/test_quality_strict.py +134 -0
  27. hyperi_ci-2.7.3/tests/unit/test_semgrep.py +71 -0
  28. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_typescript_quality.py +7 -6
  29. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_watch.py +94 -0
  30. hyperi_ci-2.7.2/VERSION +0 -1
  31. hyperi_ci-2.7.2/src/hyperi_ci/languages/quality_common.py +0 -48
  32. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.gitattributes +0 -0
  33. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/actions/predict-version/action.yml +0 -0
  34. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/actions/setup-osv-scanner/action.yml +0 -0
  35. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/actions/setup-runtime/action.yml +0 -0
  36. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/actions/setup-semantic-release/action.yml +0 -0
  37. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/actions/setup-semantic-release/default.releaserc.json +0 -0
  38. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.github/workflows/_release-tail.yml +0 -0
  39. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.gitignore +0 -0
  40. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/.releaserc.yaml +0 -0
  41. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/AI-TRAINING-POLICY.md +0 -0
  42. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/CHANGELOG.md +0 -0
  43. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/COMMERCIAL.md +0 -0
  44. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/CONTRIBUTING.md +0 -0
  45. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/LICENSE +0 -0
  46. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/SECURITY.md +0 -0
  47. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/config/commit-types.yaml +0 -0
  48. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/config/org.yaml +0 -0
  49. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/config/runners.yaml +0 -0
  50. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/config/secrets-access.yaml +0 -0
  51. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/config/versions.yaml +0 -0
  52. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/ARC-RUNNERS.md +0 -0
  53. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/CI-LESSONS.md +0 -0
  54. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/FLOW.md +0 -0
  55. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/JFROG-MIGRATION.md +0 -0
  56. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/LESSONS.md +0 -0
  57. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/MIGRATION-GUIDE.md +0 -0
  58. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/PGO-WORKLOAD-GUIDE.md +0 -0
  59. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/README.md +0 -0
  60. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/dependencies/DEPS-PINNING.md +0 -0
  61. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/dependencies/WORKFLOW-PINNING.md +0 -0
  62. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/deployment/CONTRACT-IDENTITY.md +0 -0
  63. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/deployment/CONTRACT.md +0 -0
  64. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/deployment/TIERS.md +0 -0
  65. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/deployment-contract.md +0 -0
  66. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/languages/GO.md +0 -0
  67. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/languages/PYTHON.md +0 -0
  68. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/languages/RUST.md +0 -0
  69. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/languages/TYPESCRIPT.md +0 -0
  70. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/migration/CODEBERG-SECRETS-AND-CI.md +0 -0
  71. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/migration/JFROG.md +0 -0
  72. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/migration/ONBOARDING.md +0 -0
  73. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/migration/codeberg-secrets-and-ci.md +0 -0
  74. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/migration/codeberg.md +0 -0
  75. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/migration/deployment-contract-tier3.md +0 -0
  76. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/runtime/PGO-BOLT.md +0 -0
  77. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/runtime/RUNNERS.md +0 -0
  78. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/runtime/TESTENV.md +0 -0
  79. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/rust.md +0 -0
  80. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/docs/typescript.md +0 -0
  81. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/pyproject.toml +0 -0
  82. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/renovate.json +0 -0
  83. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/robots.txt +0 -0
  84. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/scripts/check-workflow-interfaces.py +0 -0
  85. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/scripts/pre-commit-versions.sh +0 -0
  86. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/scripts/recover-tags.py +0 -0
  87. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/scripts/setup-rust-dev.py +0 -0
  88. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/scripts/sync-secrets-access.py +0 -0
  89. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/scripts/update-versions.py +0 -0
  90. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/__init__.py +0 -0
  91. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/argocd/__init__.py +0 -0
  92. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/argocd/gitops_push.py +0 -0
  93. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/argocd/stage.py +0 -0
  94. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/common.py +0 -0
  95. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/native-deps/golang.yaml +0 -0
  96. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/native-deps/python.yaml +0 -0
  97. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/native-deps/rust.yaml +0 -0
  98. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/native-deps/typescript.yaml +0 -0
  99. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/org.yaml +0 -0
  100. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/toolchains/gcc.yaml +0 -0
  101. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config/toolchains/llvm.yaml +0 -0
  102. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/config.py +0 -0
  103. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/__init__.py +0 -0
  104. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/binary_stage.py +0 -0
  105. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/build.py +0 -0
  106. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/compose.py +0 -0
  107. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/detect.py +0 -0
  108. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/labels.py +0 -0
  109. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/manifest.py +0 -0
  110. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/registry.py +0 -0
  111. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/stage.py +0 -0
  112. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/container/templates.py +0 -0
  113. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/__init__.py +0 -0
  114. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/cli.py +0 -0
  115. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/contract.py +0 -0
  116. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/detect.py +0 -0
  117. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/__init__.py +0 -0
  118. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/anchors/__init__.py +0 -0
  119. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/anchors/argocd.py +0 -0
  120. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/anchors/dockerfile.py +0 -0
  121. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/anchors/helm.py +0 -0
  122. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/cli.py +0 -0
  123. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/errors.py +0 -0
  124. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/model.py +0 -0
  125. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/overlay/render.py +0 -0
  126. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/registry.py +0 -0
  127. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/scaffold.py +0 -0
  128. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/stage.py +0 -0
  129. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/topology/__init__.py +0 -0
  130. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/topology/resolve.py +0 -0
  131. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/deployment/topology/stitch.py +0 -0
  132. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/detect.py +0 -0
  133. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gh.py +0 -0
  134. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/.gitbook.yaml +0 -0
  135. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/.gitignore +0 -0
  136. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/CODEOWNERS +0 -0
  137. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/LICENSE +0 -0
  138. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/README.md +0 -0
  139. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/argocd/README.md +0 -0
  140. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/argocd/applicationsets/.gitkeep +0 -0
  141. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/argocd/appprojects/.gitkeep +0 -0
  142. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/argocd/bootstrap/.gitkeep +0 -0
  143. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/concepts/architecture.md +0 -0
  144. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/concepts/overview.md +0 -0
  145. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/how-to/add-app.md +0 -0
  146. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/how-to/add-environment.md +0 -0
  147. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/how-to/add-topology.md +0 -0
  148. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/index.md +0 -0
  149. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/operations/disaster-recovery.md +0 -0
  150. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/operations/rollback.md +0 -0
  151. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/quickstart.md +0 -0
  152. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/reference/sync-waves.md +0 -0
  153. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/docs/reference/topology-schema.md +0 -0
  154. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/mkdocs.yml +0 -0
  155. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/pull_request_template.md +0 -0
  156. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/terraform/README.md +0 -0
  157. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/terraform/aws/environments/.gitkeep +0 -0
  158. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/terraform/aws/modules/.gitkeep +0 -0
  159. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/terraform/rancher/clusters/.gitkeep +0 -0
  160. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/terraform/rancher/modules/.gitkeep +0 -0
  161. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/topologies/README.md +0 -0
  162. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/values/.gitkeep +0 -0
  163. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/workflows/docs.yaml +0 -0
  164. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/workflows/stitch-and-publish.yaml +0 -0
  165. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/gitops_templates/workflows/validate.yaml +0 -0
  166. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/helm/__init__.py +0 -0
  167. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/helm/stage.py +0 -0
  168. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/init.py +0 -0
  169. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/init_gitops.py +0 -0
  170. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/install_deps.py +0 -0
  171. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/__init__.py +0 -0
  172. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/_build_common.py +0 -0
  173. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/golang/__init__.py +0 -0
  174. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/golang/build.py +0 -0
  175. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/golang/publish.py +0 -0
  176. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/golang/test.py +0 -0
  177. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/python/__init__.py +0 -0
  178. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/python/build.py +0 -0
  179. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/python/publish.py +0 -0
  180. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/python/test.py +0 -0
  181. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/__init__.py +0 -0
  182. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/build.py +0 -0
  183. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/optimize.py +0 -0
  184. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/pgo.py +0 -0
  185. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/publish.py +0 -0
  186. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/rust/test.py +0 -0
  187. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/__init__.py +0 -0
  188. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/_common.py +0 -0
  189. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/build.py +0 -0
  190. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/install_deps.py +0 -0
  191. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/publish.py +0 -0
  192. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/languages/typescript/test.py +0 -0
  193. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/licenses.py +0 -0
  194. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/logs.py +0 -0
  195. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/migrate.py +0 -0
  196. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/native_deps.py +0 -0
  197. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/publish/__init__.py +0 -0
  198. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/publish/binaries.py +0 -0
  199. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/publish/dispatch.py +0 -0
  200. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/publish_binaries.py +0 -0
  201. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/push.py +0 -0
  202. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/quality/__init__.py +0 -0
  203. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/quality/ignores.py +0 -0
  204. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/quality/osv_scanner.py +0 -0
  205. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/release.py +0 -0
  206. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/stamp.py +0 -0
  207. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/trigger.py +0 -0
  208. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/src/hyperi_ci/upgrade.py +0 -0
  209. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/pgo-workload/README.md +0 -0
  210. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/pgo-workload/grpc-server.sh +0 -0
  211. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/pgo-workload/http-server.sh +0 -0
  212. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/pgo-workload/kafka-consumer.sh +0 -0
  213. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/pgo-workload/kafka-producer.sh +0 -0
  214. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/pgo-workload/multi-protocol.sh +0 -0
  215. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/testenv/README.md +0 -0
  216. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/testenv/clickhouse-low-mem.xml +0 -0
  217. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/testenv/clickhouse.compose.yaml +0 -0
  218. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/templates/testenv/redpanda.compose.yaml +0 -0
  219. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/__init__.py +0 -0
  220. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/argocd/__init__.py +0 -0
  221. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/argocd/test_gitops_push.py +0 -0
  222. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/argocd/test_stage.py +0 -0
  223. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/__init__.py +0 -0
  224. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/overlay/__init__.py +0 -0
  225. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/overlay/test_argocd_anchors.py +0 -0
  226. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/overlay/test_cli.py +0 -0
  227. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/overlay/test_dockerfile_anchors.py +0 -0
  228. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/overlay/test_helm_anchors.py +0 -0
  229. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/overlay/test_model.py +0 -0
  230. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/topology/__init__.py +0 -0
  231. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/topology/test_resolve.py +0 -0
  232. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/deployment/topology/test_stitch.py +0 -0
  233. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/helm/__init__.py +0 -0
  234. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/helm/test_stage.py +0 -0
  235. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/helm/test_stage_topology_mode.py +0 -0
  236. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/integration/__init__.py +0 -0
  237. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/integration/test_rust_build_optimize.py +0 -0
  238. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/__init__.py +0 -0
  239. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/__init__.py +0 -0
  240. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/test_contract.py +0 -0
  241. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/test_detect_tier.py +0 -0
  242. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/test_emit_artefacts_cli.py +0 -0
  243. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/test_registry_cascade.py +0 -0
  244. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/test_scaffold.py +0 -0
  245. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/deployment/test_stage.py +0 -0
  246. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_build_common.py +0 -0
  247. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_cli.py +0 -0
  248. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_cli_init_gitops.py +0 -0
  249. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_cli_stitch.py +0 -0
  250. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_commit_validation.py +0 -0
  251. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_common.py +0 -0
  252. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_config.py +0 -0
  253. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_binary_stage.py +0 -0
  254. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_build.py +0 -0
  255. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_compose.py +0 -0
  256. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_detect.py +0 -0
  257. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_labels.py +0 -0
  258. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_manifest.py +0 -0
  259. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_registry.py +0 -0
  260. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_stage.py +0 -0
  261. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_container_templates.py +0 -0
  262. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_detect.py +0 -0
  263. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_dispatch_alias.py +0 -0
  264. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_dispatch_status.py +0 -0
  265. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_gh.py +0 -0
  266. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_init.py +0 -0
  267. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_init_gitops.py +0 -0
  268. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_init_topology.py +0 -0
  269. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_licenses.py +0 -0
  270. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_migrate.py +0 -0
  271. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_native_deps.py +0 -0
  272. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_osv_scanner.py +0 -0
  273. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_predicted_bump.py +0 -0
  274. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_publish.py +0 -0
  275. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_publish_dispatch.py +0 -0
  276. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_push.py +0 -0
  277. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_quality_ignore_wiring.py +0 -0
  278. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_quality_ignores.py +0 -0
  279. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_recover_tags.py +0 -0
  280. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_release_version.py +0 -0
  281. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_rust_optimize.py +0 -0
  282. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_rust_pgo.py +0 -0
  283. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_rust_quality.py +0 -0
  284. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_stamp.py +0 -0
  285. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_update_versions.py +0 -0
  286. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_upgrade.py +0 -0
  287. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_workflow_consistency.py +0 -0
  288. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/tests/unit/test_workflow_interfaces.py +0 -0
  289. {hyperi_ci-2.7.2 → hyperi_ci-2.7.3}/uv.lock +0 -0
@@ -47,11 +47,23 @@ concurrency:
47
47
  group: ${{ github.workflow }}-${{ inputs.tag || github.ref }}
48
48
  cancel-in-progress: true
49
49
 
50
+ # Least-privilege GITHUB_TOKEN default for every job (CodeQL
51
+ # actions/missing-workflow-permissions). Two jobs elevate: release-tail
52
+ # (passes write down to _release-tail.yml -- semantic-release commit/tag +
53
+ # GHCR) and plan (semantic-release push-access verify on a publish predict).
54
+ # commit-check / quality / test / build are read-only.
55
+ permissions:
56
+ contents: read
57
+
50
58
  jobs:
51
59
  plan:
52
60
  name: Plan
53
61
  if: github.event.pull_request.head.repo.fork != true
54
62
  runs-on: ubuntu-latest
63
+ # predict-version runs semantic-release, whose git plugin verifies push
64
+ # access (a `git push --dry-run`) on a publish predict -- needs write.
65
+ permissions:
66
+ contents: write
55
67
  outputs:
56
68
  run-checks: ${{ steps.predict.outputs.run-checks }}
57
69
  run-build: ${{ steps.predict.outputs.run-build }}
@@ -218,6 +230,14 @@ jobs:
218
230
  release-tail:
219
231
  name: Release tail
220
232
  needs: [plan, build]
233
+ # Elevated + passed to _release-tail.yml: its tag-and-publish job commits +
234
+ # tags (contents), pushes GHCR (packages) and runs the semantic-release GH
235
+ # plugin (issues + pull-requests). Capped by the caller's grant.
236
+ permissions:
237
+ contents: write
238
+ packages: write
239
+ issues: write
240
+ pull-requests: write
221
241
  # Local ref (dogfood): a change to the shared release tail is exercised
222
242
  # on hyperi-ci's own CI before any consumer pins it. The tail's own
223
243
  # tag-and-publish job is gated on will-publish == 'true', so a non-publish
@@ -106,6 +106,18 @@ concurrency:
106
106
  env:
107
107
  HYPERCI_PUBLISH_TARGET: ${{ inputs.publish-target }}
108
108
  HYPERCI_INSTALL: uvx --no-cache --refresh hyperi-ci
109
+ # Rare edge-case escape hatch: set the HYPERCI_QUALITY_SKIP repo/org
110
+ # variable (e.g. "semgrep") to force-skip a quality tool whose false
111
+ # positive is halting CI, until the real fix lands. Empty when unset.
112
+ HYPERCI_QUALITY_SKIP: ${{ vars.HYPERCI_QUALITY_SKIP }}
113
+
114
+ # Least-privilege GITHUB_TOKEN default for every job (CodeQL
115
+ # actions/missing-workflow-permissions). Two jobs elevate: release-tail
116
+ # (passes write down to _release-tail.yml -- semantic-release commit/tag +
117
+ # GHCR) and plan (semantic-release push-access verify on a publish predict).
118
+ # commit-check / quality / test / build are read-only.
119
+ permissions:
120
+ contents: read
109
121
 
110
122
  jobs:
111
123
  # ---------------------------------------------------------------------------
@@ -116,6 +128,10 @@ jobs:
116
128
  name: Plan
117
129
  if: github.event.pull_request.head.repo.fork != true
118
130
  runs-on: ubuntu-latest
131
+ # predict-version runs semantic-release, whose git plugin verifies push
132
+ # access (a `git push --dry-run`) on a publish predict -- needs write.
133
+ permissions:
134
+ contents: write
119
135
  outputs:
120
136
  run-checks: ${{ steps.predict.outputs.run-checks }}
121
137
  run-build: ${{ steps.predict.outputs.run-build }}
@@ -370,6 +386,14 @@ jobs:
370
386
  release-tail:
371
387
  name: Release tail
372
388
  needs: [plan, build]
389
+ # Elevated + passed to _release-tail.yml: its tag-and-publish job commits +
390
+ # tags (contents), pushes GHCR (packages) and runs the semantic-release GH
391
+ # plugin (issues + pull-requests). Capped by the caller's grant.
392
+ permissions:
393
+ contents: write
394
+ packages: write
395
+ issues: write
396
+ pull-requests: write
373
397
  uses: hyperi-io/hyperi-ci/.github/workflows/_release-tail.yml@main
374
398
  with:
375
399
  language: golang
@@ -110,6 +110,18 @@ concurrency:
110
110
  env:
111
111
  HYPERCI_PUBLISH_TARGET: ${{ inputs.publish-target }}
112
112
  HYPERCI_INSTALL: uvx --no-cache --refresh hyperi-ci
113
+ # Rare edge-case escape hatch: set the HYPERCI_QUALITY_SKIP repo/org
114
+ # variable (e.g. "semgrep") to force-skip a quality tool whose false
115
+ # positive is halting CI, until the real fix lands. Empty when unset.
116
+ HYPERCI_QUALITY_SKIP: ${{ vars.HYPERCI_QUALITY_SKIP }}
117
+
118
+ # Least-privilege GITHUB_TOKEN default for every job (CodeQL
119
+ # actions/missing-workflow-permissions). Two jobs elevate: release-tail
120
+ # (passes write down to _release-tail.yml -- semantic-release commit/tag +
121
+ # GHCR) and plan (semantic-release push-access verify on a publish predict).
122
+ # commit-check / quality / test / build are read-only.
123
+ permissions:
124
+ contents: read
113
125
 
114
126
  jobs:
115
127
  # ---------------------------------------------------------------------------
@@ -121,6 +133,10 @@ jobs:
121
133
  name: Plan
122
134
  if: github.event.pull_request.head.repo.fork != true
123
135
  runs-on: ubuntu-latest
136
+ # predict-version runs semantic-release, whose git plugin verifies push
137
+ # access (a `git push --dry-run`) on a publish predict -- needs write.
138
+ permissions:
139
+ contents: write
124
140
  outputs:
125
141
  run-checks: ${{ steps.predict.outputs.run-checks }}
126
142
  run-build: ${{ steps.predict.outputs.run-build }}
@@ -367,6 +383,14 @@ jobs:
367
383
  release-tail:
368
384
  name: Release tail
369
385
  needs: [plan, build]
386
+ # Elevated + passed to _release-tail.yml: its tag-and-publish job commits +
387
+ # tags (contents), pushes GHCR (packages) and runs the semantic-release GH
388
+ # plugin (issues + pull-requests). Capped by the caller's grant.
389
+ permissions:
390
+ contents: write
391
+ packages: write
392
+ issues: write
393
+ pull-requests: write
370
394
  uses: hyperi-io/hyperi-ci/.github/workflows/_release-tail.yml@main
371
395
  with:
372
396
  language: python
@@ -118,6 +118,18 @@ env:
118
118
  # publish), or `publish-target: both`, or a from-head dispatch (issue #35 —
119
119
  # a from-head release is GA, not a dev pre-release).
120
120
  HYPERCI_CHANNEL: ${{ (inputs.tag != '' || inputs.publish-target == 'both' || inputs.from-head == 'true') && 'release' || '' }}
121
+ # Rare edge-case escape hatch: set the HYPERCI_QUALITY_SKIP repo/org
122
+ # variable (e.g. "semgrep") to force-skip a quality tool whose false
123
+ # positive is halting CI, until the real fix lands. Empty when unset.
124
+ HYPERCI_QUALITY_SKIP: ${{ vars.HYPERCI_QUALITY_SKIP }}
125
+
126
+ # Least-privilege GITHUB_TOKEN default for every job (CodeQL
127
+ # actions/missing-workflow-permissions). Two jobs elevate: release-tail
128
+ # (passes write down to _release-tail.yml -- semantic-release commit/tag +
129
+ # GHCR) and plan (semantic-release push-access verify on a publish predict).
130
+ # commit-check / quality / test / build are read-only.
131
+ permissions:
132
+ contents: read
121
133
 
122
134
  jobs:
123
135
  # ---------------------------------------------------------------------------
@@ -136,6 +148,10 @@ jobs:
136
148
  name: Plan
137
149
  if: github.event.pull_request.head.repo.fork != true
138
150
  runs-on: ubuntu-latest
151
+ # predict-version runs semantic-release, whose git plugin verifies push
152
+ # access (a `git push --dry-run`) on a publish predict -- needs write.
153
+ permissions:
154
+ contents: write
139
155
  outputs:
140
156
  run-checks: ${{ steps.predict.outputs.run-checks }}
141
157
  run-build: ${{ steps.predict.outputs.run-build }}
@@ -424,6 +440,14 @@ jobs:
424
440
  release-tail:
425
441
  name: Release tail
426
442
  needs: [plan, build]
443
+ # Elevated + passed to _release-tail.yml: its tag-and-publish job commits +
444
+ # tags (contents), pushes GHCR (packages) and runs the semantic-release GH
445
+ # plugin (issues + pull-requests). Capped by the caller's grant.
446
+ permissions:
447
+ contents: write
448
+ packages: write
449
+ issues: write
450
+ pull-requests: write
427
451
  uses: hyperi-io/hyperi-ci/.github/workflows/_release-tail.yml@main
428
452
  with:
429
453
  language: rust
@@ -108,6 +108,18 @@ concurrency:
108
108
  env:
109
109
  HYPERCI_PUBLISH_TARGET: ${{ inputs.publish-target }}
110
110
  HYPERCI_INSTALL: uvx --no-cache --refresh hyperi-ci
111
+ # Rare edge-case escape hatch: set the HYPERCI_QUALITY_SKIP repo/org
112
+ # variable (e.g. "semgrep") to force-skip a quality tool whose false
113
+ # positive is halting CI, until the real fix lands. Empty when unset.
114
+ HYPERCI_QUALITY_SKIP: ${{ vars.HYPERCI_QUALITY_SKIP }}
115
+
116
+ # Least-privilege GITHUB_TOKEN default for every job (CodeQL
117
+ # actions/missing-workflow-permissions). Two jobs elevate: release-tail
118
+ # (passes write down to _release-tail.yml -- semantic-release commit/tag +
119
+ # GHCR) and plan (semantic-release push-access verify on a publish predict).
120
+ # commit-check / quality / test / build are read-only.
121
+ permissions:
122
+ contents: read
111
123
 
112
124
  jobs:
113
125
  # ---------------------------------------------------------------------------
@@ -118,6 +130,10 @@ jobs:
118
130
  name: Plan
119
131
  if: github.event.pull_request.head.repo.fork != true
120
132
  runs-on: ubuntu-latest
133
+ # predict-version runs semantic-release, whose git plugin verifies push
134
+ # access (a `git push --dry-run`) on a publish predict -- needs write.
135
+ permissions:
136
+ contents: write
121
137
  outputs:
122
138
  run-checks: ${{ steps.predict.outputs.run-checks }}
123
139
  run-build: ${{ steps.predict.outputs.run-build }}
@@ -378,6 +394,14 @@ jobs:
378
394
  release-tail:
379
395
  name: Release tail
380
396
  needs: [plan, build]
397
+ # Elevated + passed to _release-tail.yml: its tag-and-publish job commits +
398
+ # tags (contents), pushes GHCR (packages) and runs the semantic-release GH
399
+ # plugin (issues + pull-requests). Capped by the caller's grant.
400
+ permissions:
401
+ contents: write
402
+ packages: write
403
+ issues: write
404
+ pull-requests: write
381
405
  uses: hyperi-io/hyperi-ci/.github/workflows/_release-tail.yml@main
382
406
  with:
383
407
  language: typescript
@@ -33,3 +33,7 @@ quality:
33
33
  - python.lang.compatibility.python36.python36-compatibility-importlib2
34
34
  - python.lang.compatibility.python37.python37-compatibility-importlib2
35
35
  reason: "importlib.resources is stdlib; repo requires-python >= 3.12, no py<3.9 support"
36
+ - tool: semgrep
37
+ ids:
38
+ - yaml.github-actions.security.github-actions-mutable-action-tag.github-actions-mutable-action-tag
39
+ reason: "gitops_templates/ ships floating @vN action refs as a readable starting point; downstream repos pin via their own Renovate. This repo's own workflows are SHA-pinned (versions.yaml + pre-commit hook) so the rule is redundant here. Rule-scoped, not a path exclude, so other semgrep rules still cover the templates."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hyperi-ci
3
- Version: 2.7.2
3
+ Version: 2.7.3
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
@@ -79,6 +79,17 @@ only — those code paths have been removed.
79
79
  - Semantic-release config that just works
80
80
  - A commit hook that catches bad messages before they hit CI
81
81
 
82
+ ## Preventative, Not Detective
83
+
84
+ hyperi-ci is the preventative layer: gitleaks blocks a secret before
85
+ the push, commit validation blocks a bad message before it lands,
86
+ quality gates block a broken build before it merges. GitHub's native
87
+ security features (secret scanning alerts, CodeQL code scanning,
88
+ Dependabot) are the detective layer - they find what already landed,
89
+ or what arrived from upstream in repos hyperi-ci never runs on
90
+ (external forks, mirrors). Run both: hyperi-ci stops you making the
91
+ mess, the GitHub side catches the mess you inherited.
92
+
82
93
  ## Install
83
94
 
84
95
  ```bash
@@ -104,6 +115,7 @@ This creates `.hyperi-ci.yaml`, `Makefile`, `.github/workflows/ci.yml`,
104
115
  hyperi-ci check # Quality + test
105
116
  hyperi-ci check --quick # Quality only (fast)
106
117
  hyperi-ci check --full # Quality + test + build
118
+ hyperi-ci check --strict # Also fail on warn-tier findings (zero warnings)
107
119
 
108
120
  # 3. Commit (hook validates your message format)
109
121
  git commit -m "fix: resolve timeout in auth handler"
@@ -274,6 +286,7 @@ No code changes, no workflow changes.
274
286
  | `hyperi-ci check` | Pre-push validation (quality + test) |
275
287
  | `hyperi-ci check --quick` | Quality only |
276
288
  | `hyperi-ci check --full` | Quality + test + build |
289
+ | `hyperi-ci check --strict` | Also fail on warn-tier findings - see [docs/quality-gate.md](docs/quality-gate.md) |
277
290
  | `hyperi-ci push` | Push (validate-only — no tag, no publish) |
278
291
  | `hyperi-ci push --publish` | Stamp `Publish: true` trailer, push, single-run publish |
279
292
  | `hyperi-ci push --bump-patch` | Force +0.0.1 release even with no-bump commits |
@@ -46,6 +46,17 @@ only — those code paths have been removed.
46
46
  - Semantic-release config that just works
47
47
  - A commit hook that catches bad messages before they hit CI
48
48
 
49
+ ## Preventative, Not Detective
50
+
51
+ hyperi-ci is the preventative layer: gitleaks blocks a secret before
52
+ the push, commit validation blocks a bad message before it lands,
53
+ quality gates block a broken build before it merges. GitHub's native
54
+ security features (secret scanning alerts, CodeQL code scanning,
55
+ Dependabot) are the detective layer - they find what already landed,
56
+ or what arrived from upstream in repos hyperi-ci never runs on
57
+ (external forks, mirrors). Run both: hyperi-ci stops you making the
58
+ mess, the GitHub side catches the mess you inherited.
59
+
49
60
  ## Install
50
61
 
51
62
  ```bash
@@ -71,6 +82,7 @@ This creates `.hyperi-ci.yaml`, `Makefile`, `.github/workflows/ci.yml`,
71
82
  hyperi-ci check # Quality + test
72
83
  hyperi-ci check --quick # Quality only (fast)
73
84
  hyperi-ci check --full # Quality + test + build
85
+ hyperi-ci check --strict # Also fail on warn-tier findings (zero warnings)
74
86
 
75
87
  # 3. Commit (hook validates your message format)
76
88
  git commit -m "fix: resolve timeout in auth handler"
@@ -241,6 +253,7 @@ No code changes, no workflow changes.
241
253
  | `hyperi-ci check` | Pre-push validation (quality + test) |
242
254
  | `hyperi-ci check --quick` | Quality only |
243
255
  | `hyperi-ci check --full` | Quality + test + build |
256
+ | `hyperi-ci check --strict` | Also fail on warn-tier findings - see [docs/quality-gate.md](docs/quality-gate.md) |
244
257
  | `hyperi-ci push` | Push (validate-only — no tag, no publish) |
245
258
  | `hyperi-ci push --publish` | Stamp `Publish: true` trailer, push, single-run publish |
246
259
  | `hyperi-ci push --bump-patch` | Force +0.0.1 release even with no-bump commits |
@@ -0,0 +1 @@
1
+ 2.7.3
@@ -188,7 +188,7 @@ Third-party pinning policy: [dependencies/DEPS-PINNING.md](dependencies/DEPS-PIN
188
188
 
189
189
  ```
190
190
  hyperi-ci run <stage> quality | test | build | publish
191
- hyperi-ci check [--quick|--full] pre-push: quality(+test)(+native build)
191
+ hyperi-ci check [--quick|--full|--strict] pre-push: quality(+test)(+build); --strict fails on warn-tier findings
192
192
  hyperi-ci push [--publish] commit + push, opt-in Publish: true trailer
193
193
  hyperi-ci release <tag> dispatch a GA/optimised release run
194
194
  hyperi-ci publish run the publish stage
@@ -182,6 +182,7 @@ hyperi-ci run <stage> Run CI stage (setup, quality, test, build, publish)
182
182
  hyperi-ci check Pre-push validation (quality + test)
183
183
  hyperi-ci check --full Pre-push with build (native target only)
184
184
  hyperi-ci check --quick Quality checks only
185
+ hyperi-ci check --strict Also fail on warn-tier findings (zero-warnings gate)
185
186
  hyperi-ci init Generate project scaffolding
186
187
  hyperi-ci detect Show detected language
187
188
  hyperi-ci config Show merged configuration
@@ -0,0 +1,142 @@
1
+ # Project: HyperI CI
2
+ # File: docs/quality-gate.md
3
+ # Purpose: Reference for the quality stage - tools, modes, --strict, skip hatch
4
+ #
5
+ # License: BUSL-1.1 -- HYPERI PTY LIMITED
6
+ # Copyright: (c) 2026 HYPERI PTY LIMITED
7
+
8
+ # Quality gate
9
+
10
+ The quality stage runs a fixed set of tools and decides, per tool, whether a
11
+ finding is fatal. Two cross-language scanners (gitleaks, semgrep) run once at
12
+ the dispatch level; the rest run in the per-language handler. Each tool's
13
+ **effective mode** is resolved from config, an optional strict upgrade, and a
14
+ force-skip escape hatch, in that precedence.
15
+
16
+ Same code runs locally (`hyperi-ci check`) and in CI (`hyperi-ci run quality`).
17
+ The only difference is the local-vs-CI handling of a missing tool (below).
18
+
19
+ ## Effective mode - how a tool's fate is decided
20
+
21
+ Bottom line: **skip beats strict beats configured mode.** A force-skip disables
22
+ the tool; otherwise strict upgrades a `warn` tool to `blocking`; otherwise the
23
+ configured mode stands.
24
+
25
+ ```mermaid
26
+ flowchart TB
27
+ T["a quality tool"] --> SK{"tool in<br/>HYPERCI_QUALITY_SKIP?"}
28
+ SK -->|yes| D["disabled<br/>(loud CI warning)"]:::skip
29
+ SK -->|no| M["configured mode<br/>quality.&lt;tool&gt; or quality.&lt;lang&gt;.&lt;tool&gt;"]
30
+ M --> ST{"--strict AND<br/>mode is warn?"}
31
+ ST -->|yes| B["blocking"]:::block
32
+ ST -->|no| K["keep configured mode<br/>(blocking / warn / disabled)"]
33
+ classDef skip fill:#D55E00,color:#fff
34
+ classDef block fill:#0072B2,color:#fff
35
+ ```
36
+
37
+ Resolution lives in `src/hyperi_ci/languages/quality_common.py`
38
+ (`resolve_tool_mode`, `apply_strict`, `is_skipped`) and is shared by the
39
+ per-language handlers and the dispatch-level semgrep module, so the precedence
40
+ is identical everywhere.
41
+
42
+ ## Modes
43
+
44
+ | Mode | Finding behaviour |
45
+ |---|---|
46
+ | `blocking` | A finding fails the stage (non-zero exit) |
47
+ | `warn` | A finding prints but does not fail |
48
+ | `disabled` | The tool does not run |
49
+
50
+ Set per project in `.hyperi-ci.yaml` under `quality.<lang>.<tool>` (or
51
+ `quality.<tool>` for the cross-language `gitleaks` / `semgrep`); defaults live in
52
+ `src/hyperi_ci/config/defaults.yaml`.
53
+
54
+ ## Tools
55
+
56
+ | Tool | Scope | Where |
57
+ |---|---|---|
58
+ | gitleaks | cross-language secret scan | dispatch (`quality/gitleaks.py`) |
59
+ | semgrep | cross-language SAST (`--config auto`) | dispatch (`quality/semgrep.py`) |
60
+ | ruff (lint, format, docstrings) | Python | `languages/python/quality.py` |
61
+ | ty | Python types | Python handler |
62
+ | pip-audit, bandit, vulture | Python | Python handler |
63
+ | clippy, rustfmt, cargo-audit/deny, osv-scanner | Rust | `languages/rust/quality.py` |
64
+ | eslint, prettier, tsc, npm audit, osv-scanner | TypeScript | `languages/typescript/quality.py` |
65
+ | gofmt, govet, golangci-lint, gosec, govulncheck | Go | `languages/golang/quality.py` |
66
+
67
+ semgrep and gitleaks moved to the dispatch level because their rulesets are
68
+ language-agnostic - running them once avoids the drift where only one handler
69
+ passed shared excludes.
70
+
71
+ ## --strict - a zero-warnings pre-push gate
72
+
73
+ `hyperi-ci check --strict` treats every `warn`-tier finding as `blocking`, so a
74
+ developer sees - and fixes or explicitly ignores - everything CI would surface
75
+ BEFORE the push, not after. It sets `HYPERCI_QUALITY_STRICT=1`, which
76
+ `apply_strict` reads.
77
+
78
+ `disabled` tools stay off (strict enforces warnings, it does not resurrect a
79
+ tool a project turned off). A tool that is not installed locally (and has no
80
+ `uv` fallback) is still warn-skipped even under `--strict` - strict enforces
81
+ what runs, not what your machine has; CI, where the tools are present, is the
82
+ backstop.
83
+
84
+ ```bash
85
+ hyperi-ci check --strict --quick # strict quality only, no tests
86
+ # -> non-zero if any tool has findings; fix or ignore each, then re-run
87
+ ```
88
+
89
+ ## HYPERCI_QUALITY_SKIP - the rare escape hatch
90
+
91
+ > **Note:** This is an EMERGENCY override, not the normal path. The reviewed,
92
+ > auditable way to silence a tool is the config (`quality.<tool>: disabled` or
93
+ > the `quality.ignore` list).
94
+
95
+ When a tool's false positive halts CI - a semgrep rule misfiring on a
96
+ dependency, an audit advisory with no fix yet - set `HYPERCI_QUALITY_SKIP` to
97
+ the tool name (comma-separated for several) to force it to `disabled` for the
98
+ blocked runs WITHOUT a config commit, then remove it once the real fix lands.
99
+
100
+ A force-skip is logged LOUDLY: a `warn()` line plus, in CI, a real GitHub
101
+ `::warning::` annotation that lands in the run summary (it does not hide inside
102
+ a collapsed log group) - so skipping a security scanner like gitleaks cannot
103
+ pass unnoticed.
104
+
105
+ In CI, set the `HYPERCI_QUALITY_SKIP` repo or org Actions variable; the four
106
+ reusable language workflows pass it through (empty variable = no-op). Only a
107
+ repo admin / org owner can set it.
108
+
109
+ ```bash
110
+ # local one-off: skip semgrep for this run
111
+ HYPERCI_QUALITY_SKIP=semgrep hyperi-ci run quality
112
+ ```
113
+
114
+ ## Suppressing a specific rule (the reviewed path)
115
+
116
+ To silence one noisy rule permanently, use `quality.ignore` in `.hyperi-ci.yaml`
117
+ - it is committed, diffable, and carries a `reason`:
118
+
119
+ ```yaml
120
+ quality:
121
+ ignore:
122
+ - tool: semgrep
123
+ ids:
124
+ - <full.rule.id>
125
+ reason: "why this rule is noise here"
126
+ ```
127
+
128
+ This is rule-scoped (not a path exclude), so the rest of the tool's coverage
129
+ stays active. `for_tool` in `src/hyperi_ci/quality/ignores.py` feeds these to
130
+ the tool's native ignore flag.
131
+
132
+ ## Missing tool - local vs CI
133
+
134
+ A tool that is not installed and has no `uv`/`uvx` fallback:
135
+
136
+ - **In CI** (`CI` env set): a `blocking` tool FAILS - every tool must be
137
+ present, and a silent skip would mask a coverage gap.
138
+ - **Locally**: it warn-skips and carries on, so `hyperi-ci check` still runs
139
+ whatever IS installed and tells you what it skipped.
140
+
141
+ This matches the gitleaks stage's existing behaviour (`is_ci()` in
142
+ `src/hyperi_ci/common.py`).
@@ -8,7 +8,7 @@
8
8
 
9
9
  Usage:
10
10
  hyperi-ci run <stage> Run a CI stage (setup, quality, test, build, publish)
11
- hyperi-ci check Pre-push checks (quality + test; --full adds build)
11
+ hyperi-ci check Pre-push checks (quality + test; --full adds build, --strict fails on warnings)
12
12
  hyperi-ci push Push with pre-checks (replaces bare git push)
13
13
  hyperi-ci init Initialise project (config, Makefile, workflow)
14
14
  hyperi-ci detect Detect project language
@@ -41,6 +41,7 @@ rely on muscle memory. In particular:
41
41
  from __future__ import annotations
42
42
 
43
43
  import json
44
+ import os
44
45
  import sys
45
46
  from pathlib import Path
46
47
  from typing import Annotated
@@ -117,10 +118,32 @@ def check(
117
118
  bool,
118
119
  typer.Option("--quick", help="Quality checks only (skip tests)"),
119
120
  ] = False,
121
+ strict: Annotated[
122
+ bool,
123
+ typer.Option(
124
+ "--strict",
125
+ help=(
126
+ "Fail on warn-tier quality findings (ty, semgrep, "
127
+ "docstrings, ...) too -- a zero-warnings pre-push gate that "
128
+ "surfaces everything CI would show, before the push."
129
+ ),
130
+ ),
131
+ ] = False,
120
132
  ) -> None:
121
- """Run local pre-push checks (quality + test by default)."""
133
+ """Run local pre-push checks (quality + test by default).
134
+
135
+ With ``--strict``, warn-tier quality findings (which CI tolerates but
136
+ still prints) are treated as failures, so nothing is carried into a
137
+ push unseen. Fix each, or flag it to ignore if it genuinely should be.
138
+ A tool that is not installed locally (and has no uv fallback) is still
139
+ warn-skipped even under ``--strict`` -- strict enforces what runs, not
140
+ what your machine has; CI, where the tools are present, is the backstop.
141
+ """
122
142
  dir_path = Path(project_dir) if project_dir else None
123
143
 
144
+ if strict:
145
+ os.environ["HYPERCI_QUALITY_STRICT"] = "1"
146
+
124
147
  stages = ["quality"]
125
148
  if not quick:
126
149
  stages.append("test")
@@ -239,8 +262,6 @@ def push(
239
262
  With ``--no-ci``: amends the last commit with ``[skip ci]`` and
240
263
  pushes (skips CI altogether).
241
264
  """
242
- import os
243
-
244
265
  from hyperi_ci.push import push as do_push
245
266
 
246
267
  if bump_patch and bump_minor:
@@ -69,6 +69,7 @@ quality:
69
69
  enabled: true
70
70
  exclude_paths: []
71
71
  gitleaks: blocking
72
+ semgrep: warn # Semgrep SAST (cross-language) - runs once at dispatch, like gitleaks
72
73
 
73
74
  # Directories treated as test code (relaxed rules applied)
74
75
  # Override per project in .hyperi-ci.yaml
@@ -79,7 +80,6 @@ quality:
79
80
  ruff: blocking
80
81
  ty: warn # Astral's type checker (OSS, Rust-based, replaces pyright/mypy)
81
82
  pyright: disabled # Superseded by ty
82
- semgrep: warn # Semgrep SAST — auto-config rules for Python
83
83
  bandit: disabled # Superseded by ruff S rules
84
84
  bandit_exclude_tests: true # Legacy — only used if bandit re-enabled
85
85
  pip_audit: blocking
@@ -114,7 +114,6 @@ quality:
114
114
  audit: blocking
115
115
  audit_level: moderate
116
116
  osv_scanner: warn # malicious-package (MAL-*) scan; npm audit is CVE-only
117
- semgrep: warn # Semgrep SAST — auto-config rules for TypeScript
118
117
  test_ignore:
119
118
  - "@typescript-eslint/no-explicit-any"
120
119
  - "@typescript-eslint/no-non-null-assertion"
@@ -126,7 +125,6 @@ quality:
126
125
  golangci_lint: blocking
127
126
  gosec: blocking
128
127
  govulncheck: warn
129
- semgrep: warn # Semgrep SAST — auto-config rules for Go
130
128
  test_ignore:
131
129
  - errcheck
132
130
  - gosec
@@ -138,7 +136,6 @@ quality:
138
136
  osv_scanner: warn # malicious-package (MAL-*) scan; OSV feed not in RustSec
139
137
  deny: warn
140
138
  features: all
141
- semgrep: warn # Semgrep SAST — auto-config rules for Rust
142
139
  # Feature-matrix check: catches feature-gating bugs where a module behind
143
140
  # feature X uses a crate only declared by feature Y. Without this check,
144
141
  # transitive deps from other features mask the bug until a downstream
@@ -31,7 +31,7 @@ from hyperi_ci.common import (
31
31
  )
32
32
  from hyperi_ci.config import VALID_PROJECT_STATUSES, CIConfig, load_config
33
33
  from hyperi_ci.detect import detect_language
34
- from hyperi_ci.quality import commit_validation, gitleaks
34
+ from hyperi_ci.quality import commit_validation, gitleaks, semgrep
35
35
 
36
36
 
37
37
  class StageRunFn(Protocol):
@@ -181,6 +181,13 @@ def stage_quality(language: str, config: CIConfig, *, local: bool = False) -> in
181
181
  if rc != 0:
182
182
  return rc
183
183
 
184
+ # Semgrep SAST is cross-language too (python / go / ts / rust / yaml /
185
+ # ...), so it runs here once rather than inside every language handler.
186
+ with group("Semgrep SAST scanning"):
187
+ rc = semgrep.run(config, language=language)
188
+ if rc != 0:
189
+ return rc
190
+
184
191
  # Commit-message validation. In CI this is the dedicated `commit-check`
185
192
  # workflow job -- it runs on every merge to main (not just the
186
193
  # publish-worthy pushes the run-checks-gated quality job covers) and is
@@ -11,16 +11,16 @@ from __future__ import annotations
11
11
  import shutil
12
12
  import subprocess
13
13
 
14
- from hyperi_ci.common import error, info, success, warn
14
+ from hyperi_ci.common import error, info, is_ci, success, warn
15
15
  from hyperi_ci.config import CIConfig
16
- from hyperi_ci.languages.quality_common import get_test_ignore
16
+ from hyperi_ci.languages.quality_common import get_test_ignore, resolve_tool_mode
17
17
  from hyperi_ci.quality.ignores import for_tool, load_ignores
18
18
 
19
19
  _DEFAULT_GO_TEST_IGNORE = ["errcheck", "gosec"]
20
20
 
21
21
 
22
22
  def _get_tool_mode(tool: str, config: CIConfig) -> str:
23
- return str(config.get(f"quality.golang.{tool}", "blocking"))
23
+ return resolve_tool_mode(tool, config, "golang")
24
24
 
25
25
 
26
26
  def _resolve_tool_cmd(cmd: list[str], use_uvx: bool = False) -> list[str]:
@@ -44,10 +44,15 @@ def _run_tool(
44
44
 
45
45
  resolved = _resolve_tool_cmd(cmd, use_uvx=use_uvx)
46
46
  if resolved == cmd and not shutil.which(cmd[0]):
47
- if mode == "blocking":
47
+ # A missing tool fails the gate only in CI, where every tool MUST
48
+ # be present -- a silent skip would mask a coverage gap. Locally it
49
+ # is an environment gap, not a quality finding: warn and carry on
50
+ # so `hyperi-ci check` still runs whatever IS installed (matches
51
+ # the gitleaks stage's local-vs-CI handling).
52
+ if mode == "blocking" and is_ci():
48
53
  error(f" {tool_name}: not installed (required)")
49
54
  return False
50
- warn(f" {tool_name}: not installed (skipping)")
55
+ warn(f" {tool_name}: not installed (skipping locally)")
51
56
  return True
52
57
 
53
58
  result = subprocess.run(resolved, capture_output=True, text=True)
@@ -131,12 +136,4 @@ def run(config: CIConfig, extra_env: dict[str, str] | None = None) -> int:
131
136
  if not _run_tool("govulncheck", ["govulncheck", "./..."], mode):
132
137
  had_failure = True
133
138
 
134
- # Semgrep SAST scanning
135
- mode = _get_tool_mode("semgrep", config)
136
- semgrep_cmd = ["semgrep", "scan", "--config", "auto", "--error", "--quiet"]
137
- for entry in for_tool(ignores, "semgrep"):
138
- semgrep_cmd.extend(["--exclude-rule", entry.id])
139
- if not _run_tool("semgrep", semgrep_cmd, mode, use_uvx=True):
140
- had_failure = True
141
-
142
139
  return 1 if had_failure else 0