Skip to content

Improve test quality: pkg/cli/health_command_test.go#28622

Merged
pelikhan merged 3 commits intomainfrom
copilot/improve-test-quality-health-command
Apr 26, 2026
Merged

Improve test quality: pkg/cli/health_command_test.go#28622
pelikhan merged 3 commits intomainfrom
copilot/improve-test-quality-health-command

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 26, 2026

TestHealthConfigValidation was reimplementing the validation logic inline rather than exercising RunHealth, and TestHealthCommand used assert.NotNil on flag objects before dereferencing them (risking panics on nil). Coverage of edge-case days values and the JSON output path of displayDetailedHealth was also missing.

Changes

  • TestHealthConfigValidation — calls RunHealth directly; invalid days (e.g. 0, -1, 91, 365) exercise the real validation path and assert on the returned error message
  • TestRunHealthInvalidDays — new table-driven test covering six invalid days values, verifying both the specific value in the error and the hint "Must be 7, 30, or 90"
  • TestHealthCommandassert.NotNilrequire.NotNil for the command and all flag lookups so the test halts on nil rather than panicking
  • TestDisplayDetailedHealthJSON — new test for displayDetailedHealth with nil and empty runs + JSONOutput: true; captures stdout and asserts the output is valid JSON with correct WorkflowName and zero counts
// Before: inline re-implementation of validation logic
if tt.config.Days != 7 && tt.config.Days != 30 && tt.config.Days != 90 {
    assert.True(t, tt.shouldErr, "Should error for invalid days value")
}

// After: call the real function and check the actual error
err := RunHealth(tt.config)
require.Error(t, err, "RunHealth should return a validation error for: %s", tt.name)
assert.Contains(t, err.Error(), tt.errContains, "Error message should describe the validation failure")

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh gh repo view --json owner,name --jq .owner.login + "/" + .name ache/go/1.25.8/x64/pkg/tool/linux_amd64/asm GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/xTest User env 2122522566/001 _wTXDDAYc ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE 7476736/b029/ GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh repo view owner/repo 3399�� -json Q8gElMZ6A x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env t1652612488 GO111MODULE .yml GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x^remote\..*\.gh-resolved$ (http block)
    • Triggering command: /usr/bin/gh gh repo view owner/repo env 1343549843 aNsjT_hWR x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env ortcfg GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x12345 (http block)
  • https://api.github.com/orgs/test-owner/actions/secrets
    • Triggering command: /usr/bin/gh gh api /orgs/test-owner/actions/secrets --jq .secrets[].name -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/ai-inference/git/ref/tags/v1
    • Triggering command: /usr/bin/gh gh api /repos/actions/ai-inference/git/ref/tags/v1 --jq [.object.sha, .object.type] | @tsv /tmp/TestCollectWorkflowFiles_WithImports3953790611/001 rev-parse /usr/bin/git -h gh-aw.wasm |git EFuVqG1PQ x_amd64/link git rev-�� --show-toplevel x_amd64/link /usr/bin/git ortcfg GO111MODULE ache/go/1.25.8/xinstall git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v3
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v3 --jq [.object.sha, .object.type] | @tsv GOMODCACHE go /tmp/go-build733999326/b466/typeutil.test -json GO111MODULE x_amd64/compile /tmp/go-build733999326/b466/typeutil.test ent.�� .md md /usr/bin/git -test.timeout=10git -test.run=^Test -test.short=true--show-toplevel git (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v5
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv 3612-33430/test-3306591191/.gith--detach GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE ntio/asm/cpu GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile 7476�� 999326/b392/_pkg_.a pkg/mod/github.com/segmentio/asm@v1.1.3/internal/unsafebytes/uns-c=4 ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile /usr/bin/git ons/secrets om/modelcontextp\n ache/go/1.25.8/x: git rev-�� --show-toplevel rtcfg /usr/bin/git 581425908/.githugit g/repoutil/repourev-parse ache/go/1.25.8/x--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel m2xpu7MOJIw7R/iLX4908EimRzvG1AHIFr/vLW-tx2f42dcm-MlvCPy/t6M8s7Cm2xpu7MOJIw7R /usr/bin/git ry=1 (http block)
  • https://api.github.com/repos/actions/checkout/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv '/tmp/TestParseDefaultBranchFromLsRemoteWithRealGitmaster_branch4029908751/001' '/tmp/TestParseDefaultBranchFromLsRemoteWithRealGitmaster_branch4029908751/001' 1/x64/bin/node -p math/rand/v2 -lang=go1.25 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile t-ha�� ithub/workflows/agentic-observability-kit.md 999326/b424/_testmain.go /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile -p vendor/golang.orrev-parse -lang=go1.25 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv /tmp/go-build733999326/b395/_pkg_.a 999326/b438/_testmain.go /usr/bin/git -p main -lang=go1.25 git init�� 2975139352 -dwarf=false /usr/bin/git go1.25.8 -c=4 -nolocalimports git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv . l /usr/bin/git -json GO111MODULE 64/bin/go git -C /tmp/TestGuardPolicyTrustedUsersExpressionCompilv1.0.0 (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v8
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v8 --jq [.object.sha, .object.type] | @tsv --show-toplevel ache/go/1.25.8/x64/pkg/tool/linuTest User /usr/bin/git vaScript30611375bash b24G/6nfC8zN5c6k/tmp/gh-aw-test-runs/20260426-183629-36124/test-patch-priority-12590�� 999326/b419=> git rev-�� --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile /usr/bin/git '/tmp/TestParseDgit '/tmp/TestParseDrev-parse 1/x64/bin/node git (http block)
  • https://api.github.com/repos/actions/github-script/git/ref/tags/v9
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv optimization)..."; \ BEFORE=$(wc -c < gh-aw.wasm); \ wasm-opt -Oz --enable-bulk-memory gh-aw.wasm -o gh-aw.opt.wasm && \ mv gh-aw.opt.wasm gh-aw.wasm; \ AFTER=$(wc -c < g -c=4 -nolocalimports -importcfg /tmp/go-build2587476736/b231/importcfg -pack /home/REDACTED/go/pkg/mod/github.com/modelcontextprotocol/go-sdk@v1.5.0/internal/xcontext/xcontext.go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv go1.25.8 -c=4 -nolocalimports -importcfg /tmp/go-build2587476736/b254/importcfg -pack /home/REDACTED/work/gh-aw/gh-aw/pkg/fileutil/fileutil.go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/actions/setup-go/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --show-toplevel 64/pkg/tool/linux_amd64/compile /usr/bin/gh g_.a GO111MODULE 64/pkg/tool/linu--show-toplevel gh run download 3 /usr/bin/git test-logs/run-3 yVIFwLdjv /opt/hostedtoolc--show-toplevel git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv /tmp/TestGuardPolicyTrustedUsersRequiresMinIntegrity3218222359/001 config ache/node/24.14.1/x64/bin/node remote.origin.urgit GO111MODULE 64/bin/go git t-25�� k/gh-aw/gh-aw/.github/workflows/architecture-guardian.md rev-parse /usr/bin/git -json /unsafebytes/unsrev-parse x_amd64/compile git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv GOMODCACHE 64/pkg/tool/linuremote /usr/bin/gh g_.a GO111MODULE 64/pkg/tool/linu--show-toplevel gh run download 4 /usr/bin/git test-logs/run-4 8kq6Gg-gh x_amd64/link git (http block)
  • https://api.github.com/repos/actions/setup-node/git/ref/tags/v6
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv mplied -trimpath 999326/b419/vet.cfg -p set -lang=go1.25 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/compile -o /tmp/go-build2587476736/b222/_pkg_.a -trimpath /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/link 001' 001' -lang=go1.25 /opt/hostedtoolcache/go/1.25.8/x-test.v=true (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv 3612-33430/test-2529214262 -importcfg /usr/bin/git -s -w -buildmode=exe git conf�� 2975139352 Test User /usr/bin/git -json GO111MODULE 64/bin/go git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv run --auto /usr/bin/git --detach GO111MODULE 64/bin/go git -C /tmp/TestGuardPolicyTrustedUsersRequiresMinIntegrity3218222359/001 rev-parse clusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle -json GO111MODULE 64/bin/go git (http block)
  • https://api.github.com/repos/actions/upload-artifact/git/ref/tags/v4
    • Triggering command: /usr/bin/gh gh api /repos/actions/upload-artifact/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv /tmp/gh-aw-test-runs/20260426-183612-33430/test-2244722346/.github/workflows rev-parse /usr/bin/git -json GO111MODULE 64/bin/go git -C /tmp/gh-aw-test-runs/20260426-183612-33430/test-1257917169/.github/workflows rev-parse 0"}} -json GO111MODULE x_amd64/compile infocmp (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv user.email ings.cjs n-dir/git f3d33968..full-mgo ings.cjs 86_64/node forks.js bran�� -M st/suppress-warnings.cjs (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv . tions/setup/js/nmain $name) { hasDiscussionsEnabled } } /tmp/bare-incremgit gin/full-mode-brcheckout ache/uv/0.11.7/x-b git init�� -q (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq [.object.sha, .object.type] | @tsv . tions/setup/js/node_modules/vite--stdout ndor/bin/git /tmp/bare-increm/opt/hostedtoolcache/node/24.14.1/x64/bin/node . bin/git git init�� -q st/suppress-warn--conditions ache/node/24.14.development -m ode_modules/viteapi ache/node/24.14.graphql st/dist/workers/-f (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .default_branch user.email test@example.com r: $owner, name: $name) { hasDiscussionsEnabled } } 1/x64/lib/node_mgit 6ae797ea49ca08d8-C c1 1/x64/bin/node ve HEAD tions/setup/js/node_modules/viteowner=github r: $owner, name: $name) { hasDiscussionsEnabled } } --count k/gh-aw/gh-aw/ac-C ode-gyp-bin/git tions/setup/js/nshow (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .default_branch heckout/git/ref/remote.origin.url -m bject.type] | @tsv it git ed } } go run k/gh-aw/gh-aw/.github/workflows git lock.yml l ings.cjs 29f0d4cba46926b6/home/REDACTED/work/gh-aw/gh-aw /opt/hostedtoolcshow (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v0.1.2
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v0.1.2 --jq [.object.sha, .object.type] | @tsv -2253421647/base.md -2253421647/new.md /usr/bin/git -json GO111MODULE 64/pkg/tool/linu--show-toplevel /usr/bin/git remo�� -v 64/pkg/tool/linux_amd64/compile /usr/bin/git 3293877992/.githgit GO111MODULE x_amd64/vet git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv k/gh-aw/gh-aw/.github/workflows/agent-persona-extest-logs/run-3 rev-parse /usr/bin/git -json GO111MODULE 64/bin/go git rev-�� --show-toplevel go om/owner/repo.git -json GO111MODULE x_amd64/compile git (http block)
  • https://api.github.com/repos/github/gh-aw-actions/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw-actions/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv k/gh-aw/gh-aw/.github/workflows/agent-performanctest-logs/run-4 remote 999326/b465/vet.cfg -json GO111MODULE 64/bin/go /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linuconfig -o /tmp/go-build733999326/b450/styles.test -importcfg /usr/bin/git -s -w -buildmode=exe git (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --limit 100 --created >=2026-04-19 (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --limit 100 --created >=2026-03-27 (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --limit 100 --created >=2026-01-26 /tmp/go-build2013035312/b001/importcfg -pack /tmp/go-build2013035312/b001/_testmain.go (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/1/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/1/artifacts --jq .artifacts[].name Cy4PJHJpH 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile ns-l�� _.a 0kiaYELPw ache/go/1.25.8/x64/pkg/tool/linux_amd64/asm GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 QyquJZDcH 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 36/001/test-frontmatter-with-nested-objects.md Y9sJvruy0 ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12345/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12345/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE s.o 64/src/runtime/iuser.name 64/pkg/tool/linuTest User env 3014314512 3Js0Ri3Dw ache/go/1.25.8/x64/pkg/tool/linu-nilfunc GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu-tests (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet ortc�� 1343549843 1T9iaPhBz x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/12346/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/12346/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE _wasm.o 64/src/runtime/asm_wasm.s 64/pkg/tool/linux_amd64/vet env -json diXaaNED5 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linutest@example.com (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 nLaxVxxol 64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/compile env 1343549843 aNsjT_hWR x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/2/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/2/artifacts --jq .artifacts[].name KmEF_rn9z 64/pkg/tool/linux_amd64/link GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/link env 36/001/test-frontmatter-with-env-s 7zDW0_L0m rtcfg.link GOINSECURE GOMOD GOMODCACHE -4GmfpWzsnidAKUU7I/p67f43WHEJUTsremote.origin.url (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile ortc�� -json pKmvAbdZx x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/3/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/3/artifacts --jq .artifacts[].name UHEwN-QbQ 64/pkg/tool/linux_amd64/compile GOINSECURE go-sdk/internal/rev-parse GOMODCACHE 64/pkg/tool/linux_amd64/compile env _.a GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuorigin (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 yVIFwLdjv /opt/hostedtoolcache/go/1.25.8/x64/bin/go GOINSECURE /bidi GOMODCACHE go env ortcfg JmzP4TwGo ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu/tmp/file-tracker-test4046565621/test2.lock.yml (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/4/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/4/artifacts --jq .artifacts[].name DW6KATJ4J 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env ortcfg FSSLThW2J ache/go/1.25.8/x64/pkg/tool/linux_amd64/asm GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/xTest User (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 8kq6Gg-gh x_amd64/link GOINSECURE a20poly1305 GOMODCACHE x_amd64/link env ortcfg R30X4Bcts ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE N_/MhA652aEkSuR8NKQxPfr/feDwSjXStImIOC-NY5wN (http block)
  • https://api.github.com/repos/github/gh-aw/actions/runs/5/artifacts
    • Triggering command: /usr/bin/gh gh api --paginate repos/{owner}/{repo}/actions/runs/5/artifacts --jq .artifacts[].name GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE .o 64/src/internal/--show-toplevel 64/pkg/tool/linux_amd64/vet env report.md jPRjWWcxh x_amd64/link GOINSECURE GOMOD GOMODCACHE x_amd64/link (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 rrG8ct2Bi ache/go/1.25.8/x64/pkg/tool/linux_amd64/cgo GOINSECURE rm GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/cgo env ortcfg BIoY6_isA ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 100 GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run list --json databaseId,number,url,status,conclusion,workflowName,createdAt,startedAt,updatedAt,event,headBranch,headSha,displayTitle --workflow nonexistent-workflow-12345 --limit 6 GOMOD abis 64/pkg/tool/linux_amd64/vet env XMdlm1J_w ortcfg ache/go/1.25.8/x64/pkg/tool/linux_amd64/asm GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/asm (http block)
  • https://api.github.com/repos/github/gh-aw/contents/.github/workflows/shared/reporting.md
    • Triggering command: /tmp/go-build733999326/b404/cli.test /tmp/go-build733999326/b404/cli.test -test.testlogfile=/tmp/go-build733999326/b404/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true -nolocalimports -importcfg /tmp/go-build2587476736/b202/importcfg -pack env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v0.47.4
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v0.47.4 --jq [.object.sha, .object.type] | @tsv --show-toplevel ache/go/1.25.8/x64/pkg/tool/linuupstream /usr/bin/git OnlyCompiledOutpgit gNV_/-ERQMY_tDmUrev-parse 64/pkg/tool/linu--show-toplevel git rev-�� --show-toplevel 64/pkg/tool/linux_amd64/link /usr/bin/git ngutil.test GOPROXY 1/x64/bin/node git (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.0.0 --jq [.object.sha, .object.type] | @tsv 3612-33430/test-source-field-variant-2971461342/.github/workflows GO111MODULE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE record GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuremote ortc�� 7476736/b144/_pkg_.a rg/x/text@v0.36.0/internal/language/compact/compact.go ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE ntio/asm/base64 GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linuorigin (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v1.2.3
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v1.2.3 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/asm GOINSECURE GOMOD GOMODCACHE x_amd64/asm 0299�� -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v2.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v2.0.0 --jq [.object.sha, .object.type] | @tsv iant-2971461342/.github/workflows GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json age/compact/compact.go x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
  • https://api.github.com/repos/github/gh-aw/git/ref/tags/v3.0.0
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw/git/ref/tags/v3.0.0 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile env -json GO111MODULE x_amd64/compile GOINSECURE GOMOD GOMODCACHE x_amd64/compile (http block)
  • https://api.github.com/repos/nonexistent/action/git/ref/tags/v999.999.999
    • Triggering command: /usr/bin/gh gh api /repos/nonexistent/action/git/ref/tags/v999.999.999 --jq [.object.sha, .object.type] | @tsv 36/001/test-inlined-imports-enabled-with-env-template-expressions-in-body.md GO111MODULE tartedAt,updatedAt,event,headBranch,headSha,displayTitle GOINSECURE /atomic GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu-buildtags sRem�� 7476736/b160/_pkg_.a rg/x/text@v0.36.0/language/cover-ifaceassert ache/go/1.25.8/x64/pkg/tool/linu-nilfunc GOINSECURE light 7476736/b021/symview ache/go/1.25.8/x12345 (http block)
  • https://api.github.com/repos/nonexistent/repo/actions/runs/12345
    • Triggering command: /usr/bin/gh gh run view 12345 --repo nonexistent/repo --json status,conclusion GOINSECURE util GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu-buildtags env /ref/tags/v9 GO111MODULE sv GOINSECURE /gc GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linu--jq (http block)
  • https://api.github.com/repos/owner/repo/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path --repo owner/repo 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh gh workflow list --repo owner/repo --json name,path,state rtcfg.link GOINSECURE GOMOD GOMODCACHE b4L7Ikj7IChhS-MVF4/opxEl9d6gxDxhremote.origin.url ortc�� -json om/goccy/go-yaml@v1.19.2/context.go _.a GOINSECURE 7476736/b011/ GOMODCACHE ache/go/1.25.8/x^remote\..*\.gh-resolved$ (http block)
  • https://api.github.com/repos/test-owner/test-repo/actions/secrets
    • Triggering command: /usr/bin/gh gh api /repos/test-owner/test-repo/actions/secrets --jq .secrets[].name -c=4 -nolocalimports -importcfg /tmp/go-build733999326/b434/importcfg -pack /home/REDACTED/work/gh-aw/gh-aw/pkg/repoutil/repoutil.go /home/REDACTED/work/gh-aw/gh-aw/pkg/repoutil/repoutil_test.go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/test/repo
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch 36/001/test-frontmatter-with-nested-objects.md Y9sJvruy0 ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile env DefaultBranchFromLsRemoteWithRealGitmaster_branch4029908751/001' DefaultBranchFromLsRemoteWithRealGitmaster_branch4029908751/001' ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile GOINSECURE GOMOD GOMODCACHE ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile (http block)
  • invalid.example.invalid
    • Triggering command: /usr/lib/git-core/git-remote-https /usr/lib/git-core/git-remote-https origin https://invalid.example.invalid/nonexistent-repo.git e/git init�� e/git-receive-pa-b git ode_modules/.bin/git =receive test@example.com--git-dir=/tmp/bare-incremental-GdHOxk /git (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

- Refactor TestHealthConfigValidation to call RunHealth for validation path
- Add edge-case days values (0, -1, 91, 365) to TestHealthConfigValidation
- Use require.NotNil for command/flag objects in TestHealthCommand
- Add TestRunHealthInvalidDays table-driven test
- Add TestDisplayDetailedHealthJSON for nil-runs + JSON output path
- Fix io.ReadAll usage to properly handle read errors"

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/6427f696-4261-41e1-a561-761885b30c1a

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
Copilot AI changed the title [WIP] Improve test quality for health_command_test.go Improve test quality: pkg/cli/health_command_test.go Apr 26, 2026
Copilot AI requested a review from gh-aw-bot April 26, 2026 18:43
@pelikhan pelikhan marked this pull request as ready for review April 26, 2026 20:38
Copilot AI review requested due to automatic review settings April 26, 2026 20:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the quality and coverage of unit tests for the health CLI command, focusing on exercising real validation paths, safer test assertions, and JSON output behavior.

Changes:

  • Refactors TestHealthConfigValidation to call RunHealth and assert on returned validation errors for invalid Days values.
  • Adds TestRunHealthInvalidDays as a table-driven test verifying invalid Days values and the “Must be 7, 30, or 90” hint.
  • Updates TestHealthCommand to use require.NotNil for command/flag lookups and adds TestDisplayDetailedHealthJSON to validate JSON output for nil/empty runs.
Show a summary per file
File Description
pkg/cli/health_command_test.go Refines validation testing to use RunHealth, hardens flag assertions with require, and adds JSON output coverage for detailed health output.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 1/1 changed files
  • Comments generated: 3

Comment on lines +85 to +97
func TestRunHealthInvalidDays(t *testing.T) {
tests := []struct {
name string
days int
errContains string
}{
{name: "zero", days: 0, errContains: "invalid days value: 0"},
{name: "negative", days: -1, errContains: "invalid days value: -1"},
{name: "too large 91", days: 91, errContains: "invalid days value: 91"},
{name: "too large 365", days: 365, errContains: "invalid days value: 365"},
{name: "not a valid option 15", days: 15, errContains: "invalid days value: 15"},
{name: "not a valid option 8", days: 8, errContains: "invalid days value: 8"},
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is substantial overlap between the invalid-days cases in TestHealthConfigValidation and the new TestRunHealthInvalidDays (both exercise the same RunHealth validation and assert similar substrings). Consolidating these into a single table-driven test would reduce duplication and extra RunHealth invocations while keeping the same coverage.

Copilot uses AI. Check for mistakes.
Comment on lines +165 to +170
os.Stdout = w

runErr := displayDetailedHealth(tt.runs, config)

w.Close()
os.Stdout = oldStdout
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestDisplayDetailedHealthJSON mutates the global os.Stdout and only restores it on the normal path. If the test fails/panics between setting os.Stdout and restoring it, subsequent tests in the package can be affected. Use t.Cleanup/defer to restore os.Stdout and close both pipe ends to keep the test isolated.

Suggested change
os.Stdout = w
runErr := displayDetailedHealth(tt.runs, config)
w.Close()
os.Stdout = oldStdout
t.Cleanup(func() {
os.Stdout = oldStdout
if w != nil {
_ = w.Close()
}
if r != nil {
_ = r.Close()
}
})
os.Stdout = w
runErr := displayDetailedHealth(tt.runs, config)
require.NoError(t, w.Close(), "Closing captured stdout writer should not fail")
w = nil

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +79
err := RunHealth(tt.config)
if tt.wantDaysErr {
require.Error(t, err, "RunHealth should return a validation error for: %s", tt.name)
assert.Contains(t, err.Error(), tt.errContains, "Error message should describe the validation failure")
} else {
assert.False(t, tt.shouldErr, "Should not error for valid days value")
// Valid days values pass days validation; any error comes from GitHub API access
if err != nil {
assert.NotContains(t, err.Error(), "invalid days value", "Valid days should not produce a days validation error")
}
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TestHealthConfigValidation calls RunHealth for valid days values. In RunHealth the days check passes and it proceeds to resolve workflow names and fetch runs via fetchWorkflowRuns (health_command.go:136+), which can invoke gh / network and make this unit test slow/flaky or fail in CI environments without auth/network. Consider avoiding the fetch path for these cases (e.g., set a guaranteed-invalid WorkflowName so RunHealth exits after name resolution, or drop the “valid days” cases and keep validation coverage in TestRunHealthInvalidDays).

See below for a potential fix:

			config := tt.config
			if !tt.wantDaysErr {
				// Keep valid-days cases on the validation/name-resolution path and
				// avoid fetching workflow runs via gh/network.
				config.WorkflowName = "__definitely_invalid_workflow_name_for_validation_test__"
			}

			err := RunHealth(config)
			if tt.wantDaysErr {
				require.Error(t, err, "RunHealth should return a validation error for: %s", tt.name)
				assert.Contains(t, err.Error(), tt.errContains, "Error message should describe the validation failure")
			} else if err != nil {
				assert.NotContains(t, err.Error(), "invalid days value", "Valid days should not produce a days validation error")

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 92/100

Excellent test quality

Metric Value
New/modified tests analyzed 4
✅ Design tests (behavioral contracts) 4 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 3 (75%)
Duplicate test clusters 0
Test inflation detected No
🚨 Coding-guideline violations None

Test Classification Details

Test File Classification Notes
TestHealthConfigValidation pkg/cli/health_command_test.go ✅ Design Now calls RunHealth() directly; verifies error message content for invalid day values
TestRunHealthInvalidDays pkg/cli/health_command_test.go ✅ Design Covers zero, negative, boundary, and non-option values; checks both error message and "Must be 7, 30, or 90" hint
TestHealthCommand pkg/cli/health_command_test.go ✅ Design Verifies observable command API: name, flags, defaults, and help text contract
TestDisplayDetailedHealthJSON pkg/cli/health_command_test.go ✅ Design Captures stdout, parses JSON, asserts on WorkflowHealth fields; covers nil and empty-slice edge cases

Highlights

  • Previous TestHealthConfigValidation only tested the raw days integer condition without calling RunHealth() — it was essentially testing a hand-written if block in the test itself. The new version calls the real function and asserts on error message content, which would catch regressions in the validation logic.
  • TestRunHealthInvalidDays adds systematic boundary coverage (0, −1, 15, 8, 91, 365) and checks that the error message surfaces the allowed values, enforcing the user-facing contract.
  • TestDisplayDetailedHealthJSON captures stdout and round-trips through json.Unmarshal to verify JSON structural correctness — a solid behavioral assertion on the JSON output contract.
  • All assertions include descriptive messages. ✅
  • Build tag //go:build !integration is present on line 1. ✅
  • No mock libraries used. ✅

Language Support

Tests analyzed:

  • 🐹 Go (*_test.go): 4 tests — unit (//go:build !integration)

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%). All tests verify observable behavior.


📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

References:

🧪 Test quality analysis by Test Quality Sentinel · ● 440.2K ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Test Quality Sentinel: 92/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%). All 4 tests verify observable behavioral contracts with proper error coverage and assertion messages.

Add draft Architecture Decision Record documenting the decision to test
validation logic via real RunHealth function invocation rather than
inline re-implementation in health_command_test.go.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Commit pushed: 88f5a82

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions
Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic directories (pkg/) with 141 new lines but does not have a linked Architecture Decision Record (ADR).

AI has analyzed the PR diff and generated a draft ADR to help you get started:

📄 Draft ADR: docs/adr/28622-test-validation-via-real-function-invocation.md

What to do next

  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI couldn't infer, refine the decision rationale, and list real alternatives you considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-28622: Test Validation via Real Function Invocation

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

Why ADRs Matter

"AI made me procrastinate on key design decisions. Because refactoring was cheap, I could always say 'I'll deal with this later.' Deferring decisions corroded my ability to think clearly."

ADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you.


📋 Michael Nygard ADR Format Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number (e.g., 28622-test-validation-via-real-function-invocation.md for PR #28622).

🔒 This PR cannot merge until an ADR is linked in the PR body.

References: §24966509091

Note

🔒 Integrity filter blocked 1 item

The following item was blocked because it doesn't meet the GitHub integrity level.

To allow these resources, lower min-integrity in your GitHub frontmatter:

tools:
  github:
    min-integrity: approved  # merged | approved | unapproved | none

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · ● 174.2K ·

@pelikhan pelikhan merged commit c5f36dd into main Apr 26, 2026
@pelikhan pelikhan deleted the copilot/improve-test-quality-health-command branch April 26, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[testify-expert] Improve Test Quality: pkg/cli/health_command_test.go

4 participants