name: vociferate/coverage-gate description: > Enforce per-package code coverage thresholds against Go coverage profiles. Supports JSON policy files with per-package overrides and global minimums. inputs: profile: description: Path to Go coverage profile file (output from `go test -coverprofile=...`). required: false default: coverage.out policy: description: Path to JSON file defining coverage thresholds and per-package overrides. required: false default: docs/coverage-thresholds.json src-root: description: Source root directory for package discovery (passed to `go list ./...`). required: false default: . summary-file: description: Optional file path to append markdown summary of coverage results. required: false default: '' outputs: passed: description: 'Boolean: true if all packages meet threshold, false if any failed.' value: ${{ steps.gate.outputs.passed }} total-coverage: description: Repository-wide statement coverage percentage. value: ${{ steps.gate.outputs.total_coverage }} packages-checked: description: Number of packages evaluated against policy. value: ${{ steps.gate.outputs.packages_checked }} packages-failed: description: Number of packages below threshold. value: ${{ steps.gate.outputs.packages_failed }} runs: using: composite steps: - id: gate shell: bash working-directory: ${{ github.action_path }} env: PROFILE: ${{ inputs.profile }} POLICY: ${{ inputs.policy }} SRC_ROOT: ${{ inputs.src-root }} SUMMARY_FILE: ${{ inputs.summary-file }} run: | set -euo pipefail # Run coverage gate and capture output EXIT_CODE=0 OUTPUT=$(go run . \ --profile "$PROFILE" \ --policy "$POLICY" \ --src-root "$SRC_ROOT" \ ) || EXIT_CODE=$? echo "$OUTPUT" # Parse summary from output (tool prints JSON stats on last line) SUMMARY_LINE=$(echo "$OUTPUT" | tail -1) # Determine pass/fail if [[ $EXIT_CODE -eq 0 ]]; then echo "passed=true" >> "$GITHUB_OUTPUT" else echo "passed=false" >> "$GITHUB_OUTPUT" fi # Extract metrics (tool outputs: packages_checked, packages_failed, total_coverage on summary line) if echo "$SUMMARY_LINE" | jq . &>/dev/null; then echo "total_coverage=$(echo "$SUMMARY_LINE" | jq -r '.total_coverage')" >> "$GITHUB_OUTPUT" echo "packages_checked=$(echo "$SUMMARY_LINE" | jq -r '.packages_checked')" >> "$GITHUB_OUTPUT" echo "packages_failed=$(echo "$SUMMARY_LINE" | jq -r '.packages_failed')" >> "$GITHUB_OUTPUT" # Append to summary file if provided if [[ -n "$SUMMARY_FILE" ]]; then { echo "## Coverage Gate Results" echo echo "- **Passed:** $([ "$EXIT_CODE" -eq 0 ] && echo '✓ Yes' || echo '✗ No')" echo "- **Total Coverage:** $(echo "$SUMMARY_LINE" | jq -r '.total_coverage')%" echo "- **Packages Checked:** $(echo "$SUMMARY_LINE" | jq -r '.packages_checked')" echo "- **Packages Failed:** $(echo "$SUMMARY_LINE" | jq -r '.packages_failed')" } >> "$SUMMARY_FILE" fi fi exit $EXIT_CODE