mirror of
https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli.git
synced 2026-09-29 16:57:48 +08:00
fix: align scoped coverage and test timeout
This commit is contained in:
@@ -438,7 +438,7 @@ jobs:
|
||||
needs: lint
|
||||
if: ${{ needs.lint.outputs.changelog_only != 'true' && needs.lint.outputs.docs_only != 'true' && needs.lint.outputs.full_suite != 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -1160,14 +1160,20 @@ jobs:
|
||||
- name: Enforce coverage gate
|
||||
if: needs.lint.outputs.changelog_only != 'true' && needs.lint.outputs.docs_only != 'true'
|
||||
env:
|
||||
FULL_SUITE: ${{ needs.lint.outputs.full_suite }}
|
||||
COVERAGE_TARGET: "100"
|
||||
COVERAGE_ENFORCE_OVERALL: "false"
|
||||
COVERAGE_OVERALL_TOLERANCE: "0"
|
||||
run: |
|
||||
policy_profile=coverage-policy.txt
|
||||
if [ "$FULL_SUITE" != true ]; then
|
||||
policy_profile=
|
||||
fi
|
||||
additional_profile=
|
||||
if [ -f coverage-shortcut.txt ]; then
|
||||
additional_profile=coverage-shortcut.txt
|
||||
fi
|
||||
COVERAGE_DIFF_PROFILE="$policy_profile" \
|
||||
COVERAGE_ADDITIONAL_DIFF_PROFILE="$additional_profile" \
|
||||
make coverage-gate BASE_REF="$COVERAGE_BASE_REF"
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ BASE_REF=""
|
||||
OVERALL_PROFILE="coverage.txt"
|
||||
ADDITIONAL_DIFF_PROFILE="${COVERAGE_ADDITIONAL_DIFF_PROFILE:-${COVERAGE_ADDITIONAL_PROFILE:-}}"
|
||||
BASELINE_PROFILE="coverage-base.txt"
|
||||
DIFF_PROFILE="coverage-policy.txt"
|
||||
DIFF_PROFILE="${COVERAGE_DIFF_PROFILE-coverage-policy.txt}"
|
||||
TARGET="${COVERAGE_TARGET:-100}"
|
||||
OVERALL_TOLERANCE="${COVERAGE_OVERALL_TOLERANCE:-0}"
|
||||
ENFORCE_OVERALL="${COVERAGE_ENFORCE_OVERALL:-false}"
|
||||
@@ -77,13 +77,15 @@ go build -o "$CHECKER" ./scripts/policy/coverage-gate
|
||||
|
||||
module="$(go list -m -f '{{.Path}}')"
|
||||
set -- "$CHECKER" \
|
||||
--diff-profile "$DIFF_PROFILE" \
|
||||
--base-ref "$BASE_REF" \
|
||||
--module "$module" \
|
||||
--overall-tolerance "$OVERALL_TOLERANCE" \
|
||||
--target "$TARGET" \
|
||||
--enforce-overall-target="$ENFORCE_OVERALL"
|
||||
|
||||
if [ -n "$DIFF_PROFILE" ]; then
|
||||
set -- "$@" --diff-profile "$DIFF_PROFILE"
|
||||
fi
|
||||
if [ "$CHANGED_ONLY" = "true" ]; then
|
||||
set -- "$@" --changed-only
|
||||
else
|
||||
|
||||
@@ -514,6 +514,35 @@ func TestChangelogPRFastPathWorkflowContract(t *testing.T) {
|
||||
t.Error("Code Admission must not suppress required contexts with paths-ignore")
|
||||
}
|
||||
|
||||
focusedStart := strings.Index(admission, "\n test-focused:\n")
|
||||
focusedEnd := strings.Index(admission, "\n test-race:\n")
|
||||
if focusedStart < 0 || focusedEnd <= focusedStart {
|
||||
t.Fatal("Code Admission workflow missing focused test job boundaries")
|
||||
}
|
||||
focusedJob := admission[focusedStart:focusedEnd]
|
||||
if !strings.Contains(focusedJob, "timeout-minutes: 20") {
|
||||
t.Error("focused test job must allow the scoped race suite up to 20 minutes")
|
||||
}
|
||||
|
||||
coverageStart := strings.Index(admission, "\n coverage:\n")
|
||||
coverageEnd := strings.Index(admission, "\n policy:\n")
|
||||
if coverageStart < 0 || coverageEnd <= coverageStart {
|
||||
t.Fatal("Code Admission workflow missing coverage job boundaries")
|
||||
}
|
||||
coverageJob := admission[coverageStart:coverageEnd]
|
||||
for _, want := range []string{
|
||||
`FULL_SUITE: ${{ needs.lint.outputs.full_suite }}`,
|
||||
"policy_profile=coverage-policy.txt\n" +
|
||||
` if [ "$FULL_SUITE" != true ]; then` + "\n" +
|
||||
" policy_profile=\n" +
|
||||
" fi",
|
||||
`COVERAGE_DIFF_PROFILE="$policy_profile"`,
|
||||
} {
|
||||
if !strings.Contains(coverageJob, want) {
|
||||
t.Errorf("Code Admission workflow missing scoped coverage contract %q", want)
|
||||
}
|
||||
}
|
||||
|
||||
notification := readWorkflow(".github/workflows/notify-wukong.yml")
|
||||
if !strings.Contains(notification, "- CI") {
|
||||
t.Error("Wukong notification must follow the renamed CI workflow")
|
||||
@@ -529,6 +558,12 @@ func TestChangelogPRFastPathWorkflowContract(t *testing.T) {
|
||||
if !strings.Contains(coverageGate, `OVERALL_TOLERANCE="${COVERAGE_OVERALL_TOLERANCE:-0}"`) {
|
||||
t.Error("coverage gate must reject any reported overall regression")
|
||||
}
|
||||
if !strings.Contains(coverageGate, `DIFF_PROFILE="${COVERAGE_DIFF_PROFILE-coverage-policy.txt}"`) {
|
||||
t.Error("coverage gate must allow scoped CI to explicitly omit the supporting policy profile")
|
||||
}
|
||||
if !strings.Contains(coverageGate, `if [ -n "$DIFF_PROFILE" ]; then`) {
|
||||
t.Error("coverage gate must add the supporting policy profile only when configured")
|
||||
}
|
||||
if !strings.Contains(coverageGate, `--baseline-profile "$BASELINE_PROFILE"`) {
|
||||
t.Error("coverage gate must evaluate the merge-base profile with the candidate checker")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package scripts_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCoverageGatePolicyProfileCanBeExplicitlyOmitted(t *testing.T) {
|
||||
root, err := filepath.Abs(filepath.Join("..", ".."))
|
||||
if err != nil {
|
||||
t.Fatalf("Abs(repo root) error = %v", err)
|
||||
}
|
||||
|
||||
binDir := t.TempDir()
|
||||
fakeGoPath := filepath.Join(binDir, "go")
|
||||
const fakeGo = `#!/bin/sh
|
||||
set -eu
|
||||
case "$1" in
|
||||
build)
|
||||
shift
|
||||
output=
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-o)
|
||||
output="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
cat > "$output" <<'EOF'
|
||||
#!/bin/sh
|
||||
printf '%s\n' "$@" > "$COVERAGE_ARGS_LOG"
|
||||
EOF
|
||||
chmod +x "$output"
|
||||
;;
|
||||
list)
|
||||
printf '%s\n' "example.com/coverage-fixture"
|
||||
;;
|
||||
*)
|
||||
printf 'unexpected fake go command: %s\n' "$1" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
`
|
||||
if err := os.WriteFile(fakeGoPath, []byte(fakeGo), 0o755); err != nil {
|
||||
t.Fatalf("WriteFile(fake go) error = %v", err)
|
||||
}
|
||||
|
||||
baseEnv := make([]string, 0, len(os.Environ())+2)
|
||||
for _, value := range os.Environ() {
|
||||
if strings.HasPrefix(value, "PATH=") ||
|
||||
strings.HasPrefix(value, "COVERAGE_DIFF_PROFILE=") ||
|
||||
strings.HasPrefix(value, "COVERAGE_ARGS_LOG=") {
|
||||
continue
|
||||
}
|
||||
baseEnv = append(baseEnv, value)
|
||||
}
|
||||
baseEnv = append(baseEnv, "PATH="+binDir+":"+os.Getenv("PATH"))
|
||||
|
||||
runGate := func(t *testing.T, diffProfile *string) []string {
|
||||
t.Helper()
|
||||
|
||||
argsLog := filepath.Join(t.TempDir(), "args.log")
|
||||
cmd := exec.Command(
|
||||
"sh",
|
||||
"./scripts/policy/check-coverage-gate.sh",
|
||||
"--base-ref",
|
||||
"HEAD",
|
||||
)
|
||||
cmd.Dir = root
|
||||
cmd.Env = append(append([]string{}, baseEnv...), "COVERAGE_ARGS_LOG="+argsLog)
|
||||
if diffProfile != nil {
|
||||
cmd.Env = append(cmd.Env, "COVERAGE_DIFF_PROFILE="+*diffProfile)
|
||||
}
|
||||
output, runErr := cmd.CombinedOutput()
|
||||
if runErr != nil {
|
||||
t.Fatalf("coverage gate error = %v\noutput:\n%s", runErr, output)
|
||||
}
|
||||
data, readErr := os.ReadFile(argsLog)
|
||||
if readErr != nil {
|
||||
t.Fatalf("ReadFile(args log) error = %v", readErr)
|
||||
}
|
||||
return strings.Fields(string(data))
|
||||
}
|
||||
|
||||
assertDiffProfiles := func(t *testing.T, args []string, want ...string) {
|
||||
t.Helper()
|
||||
|
||||
var got []string
|
||||
for i := 0; i+1 < len(args); i++ {
|
||||
if args[i] == "--diff-profile" {
|
||||
got = append(got, args[i+1])
|
||||
i++
|
||||
}
|
||||
}
|
||||
if strings.Join(got, "\n") != strings.Join(want, "\n") {
|
||||
t.Fatalf("diff profiles = %q, want %q; args = %q", got, want, args)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("unset keeps strict policy profile", func(t *testing.T) {
|
||||
assertDiffProfiles(
|
||||
t,
|
||||
runGate(t, nil),
|
||||
"coverage-policy.txt",
|
||||
"coverage.txt",
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("explicit empty omits only policy profile", func(t *testing.T) {
|
||||
empty := ""
|
||||
assertDiffProfiles(t, runGate(t, &empty), "coverage.txt")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user