Skip to content

fix: Windows gh extension install hang and upgrade retry failure in upgrade test (#73303392593)#28860

Merged
pelikhan merged 3 commits intomainfrom
copilot/investigate-gh-aw-installation-issue
Apr 28, 2026
Merged

fix: Windows gh extension install hang and upgrade retry failure in upgrade test (#73303392593)#28860
pelikhan merged 3 commits intomainfrom
copilot/investigate-gh-aw-installation-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 28, 2026

Problem

The Extension Upgrade Test workflow on windows-latest had two separate failures:

  1. gh extension install hang (~10 min): Consistently hit the job timeout with zero output. See job 73303392593.
  2. gh aw upgrade retry failure: After fixing the install hang, a second issue was revealed — the self-upgrade retry path failed with unable to retrieve latest version for extension "aw".

Root cause — install hang

The gh CLI executes the newly downloaded gh-aw.exe as part of installation. On Windows, Windows Defender Real-Time Protection intercepts the new executable before allowing it to run, blocking the process indefinitely. Evidence: the runner always reports Terminate orphan process: pid (NNNN) (gh-aw) at cleanup.

Root cause — upgrade retry failure

The rename+retry path in upgradeExtensionIfOutdated re-ran gh extension upgrade --force, which calls the /releases/latest GitHub API endpoint internally. This endpoint returns 404 for prerelease-only repos, causing LatestVersion() to return "" and the "unable to retrieve latest version" error.

Changes

pkg/cli/update_extension_check.go

  • Changed the retry path from gh extension upgrade --force to gh extension remove + gh extension install --pin EXACT_VERSION. The install --pin path uses fetchReleaseFromTag (not fetchLatestRelease) and works with any tag — stable or prerelease.
  • Extracted extensionRepo constant ("github/gh-aw") to avoid duplicating the string across remove, install, and upgrade invocations.

.github/workflows/upgrade-test.yml

  • Diagnose Windows environment (new step): logs gh version, Defender status, existing extension dir, and running gh* processes before the install.
  • Exclude gh CLI directory from Windows Defender (new step): adds Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\GitHub CLI" so Defender cannot block the newly downloaded binary.
  • timeout-minutes: 4 on the install step: fails fast with a clear error instead of silently consuming the 10-minute job budget.
  • GH_DEBUG=api on Windows: captures verbose HTTP/API trace to pinpoint exactly which call or subprocess invocation hangs if Defender is not the sole cause.
  • Capture orphan processes after install (new step, always runs): confirms whether gh-aw.exe is still alive after the step.
  • Added install-gh-aw.sh to the pull_request path triggers.

install-gh-aw.sh

  • Wraps gh extension install in a 90-second timeout on Windows so that, if the Defender-scan hang occurs in this script too, the existing direct-download fallback is triggered instead of hanging indefinitely.

How to validate

Trigger the workflow manually (workflow_dispatch) or open a PR that touches install-gh-aw.sh or .github/workflows/upgrade-test.yml. The Windows job should now complete successfully across both the install and upgrade steps.



✨ PR Review Safe Output Test - Run 25044466924

💥 [THE END] — Illustrated by Smoke Claude · ● 211K ·

- Add Windows Defender exclusion for gh CLI dir before extension install
- Add per-step timeout-minutes: 4 to fail fast instead of hitting job ceiling
- Add GH_DEBUG=api on Windows to trace which API/subprocess call stalls
- Capture before/after process list to confirm orphan gh-aw hypothesis
- Wrap gh extension install in 90s timeout in install-gh-aw.sh on Windows
  so the direct-download fallback kicks in instead of hanging indefinitely
- Add install-gh-aw.sh to the workflow trigger paths

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/413284b6-4038-4bce-91bd-a3603ae37c98

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
Copy link
Copy Markdown
Collaborator

…ease repos

The `gh extension upgrade --force` retry was failing with "unable to retrieve
latest version for extension 'aw'" because the gh CLI uses /releases/latest
internally, which returns 404 for prerelease-only repos.

Change the retry to use `gh extension remove` + `gh extension install --pin VERSION`
which calls fetchReleaseFromTag (not fetchLatestRelease) and works with any tag.
Also extract `extensionRepo` constant to avoid duplicating "github/gh-aw".

Agent-Logs-Url: https://github.com/github/gh-aw/sessions/fac75fb6-53df-4321-bf1a-374951416e41

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 28, 2026

@copilot review windows failure https://github.com/github/gh-aw/actions/runs/25036209433/job/73329021824#step:8:1

Analyzed the new run (25036209433). Two separate issues were found and fixed:

Issue 1 (install hang) — fixed in previous commit cab1ac2:
The gh extension install step now completes in <1s on Windows. The Defender exclusion confirmed the root cause: Windows Defender was intercepting the newly downloaded gh-aw.exe and blocking execution indefinitely. The orphan-process capture step shows no orphan processes, confirming this.

Issue 2 (upgrade retry failure) — fixed in commit 5467402:
The gh aw upgrade step was failing with unable to retrieve latest version for extension "aw". The retry path was using gh extension upgrade --force, which calls /releases/latest internally. This returns 404 for prerelease-only repos.

Fix: Changed the retry path in pkg/cli/update_extension_check.go to use gh extension remove github/gh-aw + gh extension install github/gh-aw --pin VERSION. The install --pin path uses fetchReleaseFromTag instead of fetchLatestRelease, which works for any tag (stable or prerelease).

The first attempt (buffered) still uses gh extension upgrade --force as before — it correctly gets "Access is denied" from trying to overwrite the running binary, which triggers the rename. The retry then cleanly removes and reinstalls at the exact version.

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 &#43; &#34;/&#34; &#43; .name ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet **/*.json --ignore-path ../../../.pretti/home/REDACTED/work/gh-aw/gh-aw/.github/workflows/archie.md ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh repo view owner/repo /hom�� --write scripts/**/*.js x_amd64/link .prettierignore --log-level=erroconfig (http block)
    • Triggering command: /usr/bin/gh gh repo view owner/repo -c echo &#34;��� JavaScript files formatted&#34; (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 (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_WithImports1691751628/001 config /usr/bin/git remote.origin.urgit (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 /tmp/TestHashConsistency_GoAndJavaScript2514049833/001/test-inlined-imports-enabled-with-env-temgit x_amd64/vet /usr/bin/unpigz */*.json&#39; &#39;!../.git --local x_amd64/vet /usr/bin/unpigz nt.m�� md d /usr/bin/git successfully&#34; --local 64/pkg/tool/linu--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 -unreachable=false /tmp/go-build3416517781/b138/vet.cfg ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v5 --jq [.object.sha, .object.type] | @tsv --show-toplevel x_amd64/link /usr/bin/git -unreachable=faltr /tmp/go-build341\n ache/go/1.25.8/x: git rev-�� --show-toplevel Bh/hKJC44cVKMHVnremote.origin.url /usr/bin/git -bool -buildtags /opt/hostedtoolc--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 ache/go/1.25.8/x64/pkg/tool/linux_amd64/link /usr/bin/git 2866039/b462/typgit -pack 2866039/b462/imp--show-toplevel git rev-�� --show-toplevel VWw7VJguVlRAx/jNQYSQDdMsvnnTZDbyx2/zg1-jwF1IRoPasY5xy3c/9ezsDU_VWw7VJguVlRAx /usr/bin/git s/test.md s/1/artifacts 2866039/b462/_pk--show-toplevel git (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 archie.md tname) 2866039/b422/vet.cfg -errorsas -ifaceassert -nilfunc bash --no�� g/cli -tests /usr/bin/git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv g/testutil/spec_test.go g/testutil/tempdir_test.go ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile l -test.run=^Test -test.short=true--show-toplevel ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile rev-�� 656248104 /home/REDACTED/work/gh-aw/gh-aw/pkg/cli/update_redirects.go 2866039/b455=&gt; ./../pkg/workflogit b/gh-aw/pkg/timerev-parse k/_temp/uv-pytho--show-toplevel git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv origin my-default 64/pkg/tool/linux_amd64/vet (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 /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linu--jq /usr/bin/git agent-performancgit /tmp/go-build341rev-parse /opt/hostedtoolcHEAD git rev-�� --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linu-buildtags /usr/bin/git -bool -buildtags /usr/local/.ghcu--show-toplevel 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 (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv th .prettierignore --log-level=error (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -silent &gt;/dev/null 2&gt;&amp;1 (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 -mDQ/m744uhZfAkobaTk3-mDQ 64/pkg/tool/linu-dwarf=false /usr/bin/infocmp /etc/php/8.3/cligit -d ache/go/1.25.8/x--show-toplevel 2866039/b471/importcfg -1 k/gh-aw/gh-aw/pkg/workflow/features_import_test.go k/gh-aw/gh-aw/pkg/workflow/import_schema_test.go /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet y_with_repos_arrgit g/cli/update_extrev-parse 64/pkg/tool/linu--show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (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 se 2866039/b113/vet.cfg /usr/bin/git &#39;**/*.ts&#39; &#39;**/*.git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv --git-dir 64/pkg/tool/linux_amd64/vet /usr/bin/gh s/^session\.gc_mgit (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 ry=1 /tmp/go-build3416517781/b363/vet.cfg 2866039/b420/_pkg_.a js/**/*.json&#39; --git (http block)
    • Triggering command: /usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -test.paniconexit0 -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 (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 ons-test626505786 remote ow-without-reaction.lock.yml (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 -880056248/base.md -880056248/new.md /usr/bin/git scripts synced git 1 1/x64/bin/bash /usr/bin/git remo�� -v ache/go/1.25.8/x64/pkg/tool/linuremote /usr/bin/git y_only_defaults_git 6517781/b051/vetrev-parse x_amd64/link 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 /tmp/TestGuardPolicyMinIntegrityOnlymin-integrittest-logs/run-3 remote /usr/bin/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 /tmp/TestGuardPolicyMinIntegrityOnlymin-integrittest-logs/run-5 rev-parse /opt/hostedtoolcache/node/24.14.1/x64/bin/node (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 &gt;=2026-04-21 (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 &gt;=2026-03-29 (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 &gt;=2026-01-28 (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 6517781/b046/vet.cfg 64/pkg/tool/linux_amd64/compile **/*.ts **/*.json --ignore-path 64/pkg/tool/linux_amd64/compile /opt�� g_.a format:pkg-json ache/go/1.25.8/x64/pkg/tool/linu-buildmode=exe tierignore (http block)
    • Triggering command: /usr/bin/gh gh run download 1 --dir test-logs/run-1 6517781/b067/vet.cfg 64/pkg/tool/linux_amd64/link (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 (http block)
    • Triggering command: /usr/bin/gh gh run download 12345 --dir test-logs/run-12345 --write 64/pkg/tool/linux_amd64/compile **/*.ts **/*.json --ignore-path 64/pkg/tool/linux_amd64/compile estl�� e-analyzer.md (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 ne_constants.go 64/pkg/tool/linux_amd64/compile (http block)
    • Triggering command: /usr/bin/gh gh run download 12346 --dir test-logs/run-12346 --write x_amd64/vet **/*.ts **/*.json --ignore-path x_amd64/vet -c echo &#34;��� JavaScript files formatted&#34; (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 6517781/b044/vet.cfg 64/pkg/tool/linux_amd64/link **/*.ts **/*.json --ignore-path 64/pkg/tool/linux_amd64/link /opt�� sole.test format:pkg-json ortcfg.link tierignore (http block)
    • Triggering command: /usr/bin/gh gh run download 2 --dir test-logs/run-2 6517781/b048/vet.cfg 64/pkg/tool/linux_amd64/compile (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 6517781/b050/vet.cfg 64/pkg/tool/linux_amd64/vet **/*.ts **/*.json --ignore-path 64/pkg/tool/linux_amd64/vet -c npx prettier --write &#39;../../../**/*.json&#39; &#39;!../.-c=4 (http block)
    • Triggering command: /usr/bin/gh gh run download 3 --dir test-logs/run-3 6517781/b055/vet.cfg 64/pkg/tool/linux_amd64/vet (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 6517781/b004/vet.cfg 64/pkg/tool/linux_amd64/link **/*.ts **/*.json --ignore-path 64/pkg/tool/linuTest User -c .test (http block)
    • Triggering command: /usr/bin/gh gh run download 4 --dir test-logs/run-4 6517781/b104/vet.cfg 64/pkg/tool/linux_amd64/compile (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 6517781/b037/vet.cfg 64/pkg/tool/linux_amd64/vet **/*.ts **/*.json --ignore-path 64/pkg/tool/linutest@example.com -c npx prettier --write &#39;../../../**/*.json&#39; &#39;!../.-test.timeout=10m0s (http block)
    • Triggering command: /usr/bin/gh gh run download 5 --dir test-logs/run-5 6517781/b054/vet.cfg 64/pkg/tool/linux_amd64/vet (http block)
  • https://api.github.com/repos/github/gh-aw/actions/workflows
    • Triggering command: /usr/bin/gh gh workflow list --json name,state,path (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 (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 -j DROP 64/pkg/tool/linu^remote\..*\.gh-resolved$ -c &#34;prettier&#34; --write &#39;scripts/**/*-test.timeout=10m0s (http block)
  • https://api.github.com/repos/github/gh-aw/contents/.github/workflows/shared/reporting.md
    • Triggering command: /tmp/go-build3312866039/b404/cli.test /tmp/go-build3312866039/b404/cli.test -test.testlogfile=/tmp/go-build3312866039/b404/testlog.txt -test.paniconexit0 -test.v=true -test.parallel=4 -test.timeout=10m0s -test.run=^Test -test.short=true hub.com/.extrahe/opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (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 /opt/hostedtoolcache/go/1.25.8/xother /usr/bin/git -unreachable=falgit /tmp/go-build341rev-parse 6517781/b364/vet--show-toplevel git rev-�� --show-toplevel /opt/hostedtoolcache/go/1.25.8/x64/pkg/tool/linu-goversion /usr/bin/git ithub/workflows (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 se 6517781/b264/vet.cfg k rror (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&#39; &#39;!../../../pkg/workflo-errorsas --local x_amd64/vet user.name (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&#39; &#39;!../.-c=4 --local x_amd64/vet user.name (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 */*.json&#39; &#39;!../../../pkg/workflo-errorsas --local x_amd64/vet user.email (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 with-tools.md --local x_amd64/vet user.email (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 (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 se 6517781/b270/vet.cfg ache/go/1.25.8/x64/pkg/tool/linu-nolocalimports rror (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 **/*.json --ignore-path ../../../.pretti--git-dir ache/go/1.25.8/x64/pkg/tool/linuremote.origin.url estl�� se 6517781/b270/vet.cfg ache/go/1.25.8/x64/pkg/tool/linu-nolocalimports rror (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 x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh workflow list --repo owner/repo --json name,path,state x_amd64/link .prettierignore --log-level=errorev-parse gn/gh-gpgsign-li--git-dir x_amd64/link -c t4239707663/.github/workflows (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 (http block)
  • https://api.github.com/repos/test/repo
    • Triggering command: /usr/bin/gh gh api /repos/test/repo --jq .default_branch se 6517781/b233/vet.cfg ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet (http block)

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

Copilot AI changed the title investigate: fix Windows gh extension install hang in upgrade test (#73303392593) fix: Windows gh extension install hang and upgrade retry failure in upgrade test (#73303392593) Apr 28, 2026
@github-actions github-actions Bot mentioned this pull request Apr 28, 2026
@pelikhan pelikhan marked this pull request as ready for review April 28, 2026 09:09
Copilot AI review requested due to automatic review settings April 28, 2026 09:09
@pelikhan pelikhan added the smoke label Apr 28, 2026
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 addresses two Windows-specific failures in the Extension Upgrade Test workflow: a hang during gh extension install (likely due to Defender scanning) and a retry-path failure during gh aw upgrade when /releases/latest returns 404 for prerelease-only repositories.

Changes:

  • Updates the self-upgrade retry path to remove and reinstall the extension pinned to an exact version instead of re-running gh extension upgrade --force.
  • Adds Windows-focused diagnostics, Defender exclusion, and a shorter install step timeout in the upgrade test workflow.
  • Wraps gh extension install with a bounded timeout in installation scripts to avoid long hangs and trigger fallback behavior.
Show a summary per file
File Description
pkg/cli/update_extension_check.go Changes the rename+retry logic to remove + reinstall pinned to the target version; centralizes the repo slug via a constant.
install-gh-aw.sh Adds a Windows-only bounded timeout around gh extension install to prevent indefinite hangs.
actions/setup-cli/install.sh Mirrors the same Windows timeout behavior used by the standalone installer script.
.github/workflows/upgrade-test.yml Adds Windows diagnostics, Defender exclusion, API debug logging, step timeout, and orphan-process capture.

Copilot's findings

Tip

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

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

Comment on lines +162 to +166
// Note: the backup file lives inside the extension directory, so if the
// remove step succeeds the backup is also gone; we clear backupPath to
// avoid a misleading restore attempt on subsequent failures.
removeCmd := exec.Command("gh", "extension", "remove", extensionRepo)
removeCmd.Stdout = os.Stderr
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The retry path removes the extension directory before reinstalling, which also deletes the renamed backup binary (the ..bak file) because it lives alongside the executable inside the extension dir. If the subsequent gh extension install --pin ... fails (e.g., network/API error), the user is left without a working gh-aw binary and there is nothing to restore. Consider keeping the backup outside the extension directory (e.g., temp dir) or deferring deletion of the original until the pinned reinstall has succeeded, so rollback is always possible.

Copilot uses AI. Check for mistakes.
Comment on lines +149 to +153
// Retry path: remove + reinstall at the exact target version.
//
// Using "gh extension upgrade --force" again would call fetchLatestRelease
// (/releases/latest) internally, which returns 404 for prerelease-only repos
// and causes "unable to retrieve latest version for extension" errors.
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The new remove+reinstall retry logic is significant behavior change (it changes how failures are handled and which gh subcommands run), but there are no tests exercising this path. Consider adding coverage for the rename+retry branch (including the remove/install sequence and rollback behavior) by abstracting gh command execution behind a stub-able helper or by adding an integration test that simulates failures.

Copilot uses AI. Check for mistakes.
# Fix strategy (this PR):
# A. Disable Windows Defender real-time scanning for the gh CLI data
# directory *before* the install so the scan cannot block execution.
# B. Add a per-step timeout of 3 min so failures are caught fast rather
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

Comment says the per-step timeout is "3 min", but the actual timeout-minutes configured on the install step is 4. Please align the comment with the configuration (or adjust the timeout) to avoid confusion when debugging workflow timeouts.

Suggested change
# B. Add a per-step timeout of 3 min so failures are caught fast rather
# B. Add a per-step timeout of 4 min so failures are caught fast rather

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed! The comment says 3 min but timeout-minutes is 4. A suggestion code block was already included - hope the author picks it up!

📰 BREAKING: Report filed by Smoke Copilot · ● 814.5K

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

⚠️ Smoke Crush failed. Crush encountered unexpected challenges...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

⚠️ Smoke Gemini failed. Gemini encountered unexpected challenges...

@github-actions
Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions github-actions Bot removed the smoke label Apr 28, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

🚀 Smoke OpenCode MISSION COMPLETE! OpenCode delivered. 🔥

@github-actions
Copy link
Copy Markdown
Contributor

Agent Container Tool Check

Tool Status Version
bash 5.2.21
sh available
git 2.53.0
jq 1.7
yq 4.52.5
curl 8.5.0
gh 2.89.0
node 22.22.2
python3 3.10.16 (PyPy 7.3.19)
go 1.24.13
java 10.0.201
dotnet NOT FOUND

Result: 11/12 tools available ⚠️

Overall Status: FAILdotnet (.NET runtime) is not available in this container.

🔧 Tool validation by Agent Container Smoke Test · ● 120K ·

@github-actions
Copy link
Copy Markdown
Contributor

Smoke test overall: FAIL
PRs: #28848 [jsweep] Clean add_labels.cjs; #28854 fix: grant pull-requests: write for issue_comment reactions (slash_command PR comment fix)
✅ GitHub MCP, Serena, Playwright, file write/read, build
❌ Web Fetch MCP unavailable
❌ Comment memory files unavailable

Warning

Firewall blocked 2 domains

The following domains were blocked by the firewall during workflow execution:

  • ab.chatgpt.com
  • chatgpt.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"
    - "chatgpt.com"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex ·

@github-actions
Copy link
Copy Markdown
Contributor

🛠️ Agentic Maintenance updated this pull request branch.

View workflow run

@github-actions
Copy link
Copy Markdown
Contributor

The smoke test agent was here! All systems nominal. May your NextCursor never be empty!

📰 BREAKING: Report filed by Smoke Copilot · ● 814.5K ·

@github-actions
Copy link
Copy Markdown
Contributor

Smoke test #25044466983 results for PR #28860 by @Copilot (assignees: @pelikhan @Copilot):

  • GitHub MCP: ✅
  • MCP Scripts GH CLI: ✅
  • Serena CLI: ✅
  • Playwright: ✅
  • File Writing + Bash: ✅
  • Discussion Interaction: ✅
  • Build gh-aw: ✅
  • Upload artifact: ✅
  • Discussion Creation: ✅
  • Haiku Printer dispatch: ✅
  • PR Review: ✅
  • Workflow Dispatch: ✅

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot · ● 814.5K ·

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.

Smoke test agent reviewed this PR. The Windows Defender fix and timeout approach look sound. Two minor inline notes added.

📰 BREAKING: Report filed by Smoke Copilot · ● 814.5K

updateExtensionCheckLog.Printf("Could not remove extension before reinstall (will attempt install anyway): %v", removeErr)
}

retryCmd := exec.Command("gh", "extension", "install", extensionRepo, "--pin", latestVersion)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

removeCmd.Stdout is set to os.Stderr here - intentional for interleaving remove output with error output, but worth a comment explaining why stdout goes to stderr.

Comment thread install-gh-aw.sh
install_result=${PIPESTATUS[0]}
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The SC2086 disable comment is needed here, but consider using an array instead: declare the timeout as an array (GH_INSTALL_CMD_TIMEOUT=() or GH_INSTALL_CMD_TIMEOUT=(timeout 90)) so it expands safely without shellcheck suppression.

@github-actions
Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link
Copy Markdown
Contributor

🧪 Smoke Test Results — Run 25044466924

Test Status
1 GitHub MCP
2 GH CLI Scripts
3 Serena MCP
4 Make Build
5 Playwright
6 Tavily Search
7 File Write
8 Bash
9 Discussion
10 AW MCP Status
11 Slack
12 Code Scanning
13 Update PR
14 Review Comments
15 Submit Review
16 Resolve Thread ⚠️
17 Add Reviewer
18 Push Branch
19 Close PR ⚠️

Overall: ⚠️ PARTIAL (1 ❌, 2 ⚠️)

💥 [THE END] — Illustrated by Smoke Claude · ● 211K ·

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.

💥 Automated smoke test review - all systems nominal! (Run 25044466924)

💥 [THE END] — Illustrated by Smoke Claude · ● 211K

// manifest in place the install command takes the "already installed" code
// path and does nothing; removing the extension clears that guard.
//
// Note: the backup file lives inside the extension directory, so if the
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Smoke Test Review Comment — The remove+reinstall retry logic correctly handles the prerelease-only repo limitation. Clearing backupPath after successful removal prevents misleading restore attempts on subsequent failures. Well done.

# C. Capture `GH_DEBUG=api` on Windows to trace exactly which API call
# or binary invocation causes the stall if Defender is not the cause.
# ──────────────────────────────────────────────────────────────────────────

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Smoke Test Review Comment — The Windows Defender exclusion step (Add-MpPreference -ExclusionPath) is targeted and appropriate. Logging the current exclusion list after adding helps verify the step succeeded. Good diagnostic approach.

@pelikhan pelikhan merged commit a31106c into main Apr 28, 2026
1 check passed
@pelikhan pelikhan deleted the copilot/investigate-gh-aw-installation-issue branch April 28, 2026 09:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants