chore(go): enforce package coverage gates
This commit is contained in:
@@ -59,13 +59,68 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
go test -covermode=atomic -coverprofile=coverage.out ./...
|
go test -covermode=atomic -coverprofile=coverage.out ./... | tee go-test-coverage.log
|
||||||
go tool cover -html=coverage.out -o coverage.html
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
|
||||||
total="$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/, "", $3); print $3}')"
|
total="$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/, "", $3); print $3}')"
|
||||||
printf '{\n "total": "%s"\n}\n' "$total" > coverage-summary.json
|
printf '{\n "total": "%s"\n}\n' "$total" > coverage-summary.json
|
||||||
printf 'total=%s\n' "$total" >> "$GITHUB_OUTPUT"
|
printf 'total=%s\n' "$total" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
awk '
|
||||||
|
/^ok[[:space:]]/ && /coverage: [0-9.]+% of statements/ {
|
||||||
|
pkg = $2
|
||||||
|
cov = $0
|
||||||
|
sub(/^.*coverage: /, "", cov)
|
||||||
|
sub(/% of statements.*$/, "", cov)
|
||||||
|
status = "target"
|
||||||
|
if (cov + 0 < 50) {
|
||||||
|
status = "fail"
|
||||||
|
fail = 1
|
||||||
|
} else if (cov + 0 < 65) {
|
||||||
|
status = "high-risk"
|
||||||
|
} else if (cov + 0 < 80) {
|
||||||
|
status = "warning"
|
||||||
|
}
|
||||||
|
printf "%s %.1f %s\n", pkg, cov + 0, status
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (fail) {
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' go-test-coverage.log > coverage-packages.raw
|
||||||
|
package_gate_status=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
{
|
||||||
|
echo '| Package | Coverage | Status |'
|
||||||
|
echo '| --- | ---: | --- |'
|
||||||
|
} > coverage-packages.md
|
||||||
|
|
||||||
|
while read -r pkg cov status; do
|
||||||
|
case "$status" in
|
||||||
|
fail)
|
||||||
|
pretty='FAIL (<50%)'
|
||||||
|
;;
|
||||||
|
high-risk)
|
||||||
|
pretty='High risk (50%-64.99%)'
|
||||||
|
;;
|
||||||
|
warning)
|
||||||
|
pretty='Warning (65%-79.99%)'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
pretty='Target (>=80%)'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
printf '| `%s` | %.1f%% | %s |\n' "$pkg" "$cov" "$pretty" >> coverage-packages.md
|
||||||
|
done < coverage-packages.raw
|
||||||
|
|
||||||
|
if [[ "$package_gate_status" -ne 0 ]]; then
|
||||||
|
echo "Per-package coverage gate failed: one or more packages are below 50%." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Run security analysis
|
- name: Run security analysis
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -172,6 +227,9 @@ jobs:
|
|||||||
echo '- Total: `${{ steps.coverage.outputs.total }}%`'
|
echo '- Total: `${{ steps.coverage.outputs.total }}%`'
|
||||||
echo '- Report: ${{ steps.upload.outputs.report_url }}'
|
echo '- Report: ${{ steps.upload.outputs.report_url }}'
|
||||||
echo '- Badge: ${{ steps.upload.outputs.badge_url }}'
|
echo '- Badge: ${{ steps.upload.outputs.badge_url }}'
|
||||||
|
echo
|
||||||
|
echo '### Package Coverage'
|
||||||
|
cat coverage-packages.md
|
||||||
} >> "$GITHUB_STEP_SUMMARY"
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
- name: Run behavior suite
|
- name: Run behavior suite
|
||||||
|
|||||||
@@ -51,13 +51,68 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
go test -covermode=atomic -coverprofile=coverage.out ./...
|
go test -covermode=atomic -coverprofile=coverage.out ./... | tee go-test-coverage.log
|
||||||
go tool cover -html=coverage.out -o coverage.html
|
go tool cover -html=coverage.out -o coverage.html
|
||||||
|
|
||||||
total="$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/, "", $3); print $3}')"
|
total="$(go tool cover -func=coverage.out | awk '/^total:/ {sub(/%/, "", $3); print $3}')"
|
||||||
printf '{\n "total": "%s"\n}\n' "$total" > coverage-summary.json
|
printf '{\n "total": "%s"\n}\n' "$total" > coverage-summary.json
|
||||||
printf 'total=%s\n' "$total" >> "$GITHUB_OUTPUT"
|
printf 'total=%s\n' "$total" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
set +e
|
||||||
|
awk '
|
||||||
|
/^ok[[:space:]]/ && /coverage: [0-9.]+% of statements/ {
|
||||||
|
pkg = $2
|
||||||
|
cov = $0
|
||||||
|
sub(/^.*coverage: /, "", cov)
|
||||||
|
sub(/% of statements.*$/, "", cov)
|
||||||
|
status = "target"
|
||||||
|
if (cov + 0 < 50) {
|
||||||
|
status = "fail"
|
||||||
|
fail = 1
|
||||||
|
} else if (cov + 0 < 65) {
|
||||||
|
status = "high-risk"
|
||||||
|
} else if (cov + 0 < 80) {
|
||||||
|
status = "warning"
|
||||||
|
}
|
||||||
|
printf "%s %.1f %s\n", pkg, cov + 0, status
|
||||||
|
}
|
||||||
|
END {
|
||||||
|
if (fail) {
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' go-test-coverage.log > coverage-packages.raw
|
||||||
|
package_gate_status=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
{
|
||||||
|
echo '| Package | Coverage | Status |'
|
||||||
|
echo '| --- | ---: | --- |'
|
||||||
|
} > coverage-packages.md
|
||||||
|
|
||||||
|
while read -r pkg cov status; do
|
||||||
|
case "$status" in
|
||||||
|
fail)
|
||||||
|
pretty='FAIL (<50%)'
|
||||||
|
;;
|
||||||
|
high-risk)
|
||||||
|
pretty='High risk (50%-64.99%)'
|
||||||
|
;;
|
||||||
|
warning)
|
||||||
|
pretty='Warning (65%-79.99%)'
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
pretty='Target (>=80%)'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
printf '| `%s` | %.1f%% | %s |\n' "$pkg" "$cov" "$pretty" >> coverage-packages.md
|
||||||
|
done < coverage-packages.raw
|
||||||
|
|
||||||
|
if [[ "$package_gate_status" -ne 0 ]]; then
|
||||||
|
echo "Per-package coverage gate failed: one or more packages are below 50%." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Run security analysis
|
- name: Run security analysis
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -128,6 +183,9 @@ jobs:
|
|||||||
echo '- Total: `${{ steps.coverage.outputs.total }}%`'
|
echo '- Total: `${{ steps.coverage.outputs.total }}%`'
|
||||||
echo '- Report: ${{ steps.upload.outputs.report_url }}'
|
echo '- Report: ${{ steps.upload.outputs.report_url }}'
|
||||||
echo '- Badge: ${{ steps.upload.outputs.badge_url }}'
|
echo '- Badge: ${{ steps.upload.outputs.badge_url }}'
|
||||||
|
echo
|
||||||
|
echo '### Package Coverage'
|
||||||
|
cat coverage-packages.md
|
||||||
} >> "$GITHUB_STEP_SUMMARY"
|
} >> "$GITHUB_STEP_SUMMARY"
|
||||||
|
|
||||||
- name: Run behavior suite on main pushes
|
- name: Run behavior suite on main pushes
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.hrafn.xyz/aether/gosick/internal/homesick/cli"
|
"git.hrafn.xyz/aether/gosick/internal/homesick/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
exitCode := cli.Run(os.Args[1:], os.Stdout, os.Stderr)
|
exitCode := run(os.Args[1:], os.Stdout, os.Stderr)
|
||||||
os.Exit(exitCode)
|
os.Exit(exitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func run(args []string, stdout io.Writer, stderr io.Writer) int {
|
||||||
|
return cli.Run(args, stdout, stderr)
|
||||||
|
}
|
||||||
|
|||||||
53
cmd/homesick/main_test.go
Normal file
53
cmd/homesick/main_test.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.hrafn.xyz/aether/gosick/internal/homesick/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRunVersionCommand(t *testing.T) {
|
||||||
|
stdout := &bytes.Buffer{}
|
||||||
|
stderr := &bytes.Buffer{}
|
||||||
|
|
||||||
|
exitCode := run([]string{"version"}, stdout, stderr)
|
||||||
|
if exitCode != 0 {
|
||||||
|
t.Fatalf("run(version) exit code = %d, want 0", exitCode)
|
||||||
|
}
|
||||||
|
if got := stdout.String(); got != version.String+"\n" {
|
||||||
|
t.Fatalf("stdout = %q, want %q", got, version.String+"\n")
|
||||||
|
}
|
||||||
|
if got := stderr.String(); got != "" {
|
||||||
|
t.Fatalf("stderr = %q, want empty", got)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMainVersionCommand(t *testing.T) {
|
||||||
|
if os.Getenv("GO_WANT_HELPER_PROCESS") == "1" {
|
||||||
|
os.Args = []string{"gosick", "version"}
|
||||||
|
main()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(os.Args[0], "-test.run=TestMainVersionCommand")
|
||||||
|
cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
|
||||||
|
|
||||||
|
stdout := &bytes.Buffer{}
|
||||||
|
stderr := &bytes.Buffer{}
|
||||||
|
cmd.Stdout = stdout
|
||||||
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
t.Fatalf("helper process failed: %v, stderr: %s", err, stderr.String())
|
||||||
|
}
|
||||||
|
if got := stdout.String(); got != version.String+"\n" {
|
||||||
|
t.Fatalf("stdout = %q, want %q", got, version.String+"\n")
|
||||||
|
}
|
||||||
|
if got := stderr.String(); got != "" {
|
||||||
|
t.Fatalf("stderr = %q, want empty", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user