fix(docs-noob-tester): replace STATUS=$(curl) with until curl to survive set -e#28624
fix(docs-noob-tester): replace STATUS=$(curl) with until curl to survive set -e#28624
Conversation
The previous STATUS=$(curl ...) command substitution was exiting with code 7 (CURLE_COULDNT_CONNECT) on the very first attempt because GitHub Actions runs bash steps with 'set -e', causing the entire step to fail immediately rather than retrying. Replace with 'until curl -sf ...' which puts curl in a test/condition position that is immune to 'set -e'. Also adds: - Server process liveness check (detects crash vs timeout) - Explicit timeout failure with log dump for easier debugging" Agent-Logs-Url: https://github.com/github/gh-aw/sessions/3942cff2-1b61-441a-b1a4-1f302e24e20f Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Updates the docs-noob-tester workflow’s “wait for server readiness” logic to reliably retry under set -e, while improving failure diagnostics when the docs server crashes or never becomes ready.
Changes:
- Replaced
STATUS=$(curl ...)polling with anuntil curl -sf ...; do ...; doneloop so connection failures don’t terminate the step underset -e. - Added server crash detection via PID liveness checks and improved timeout diagnostics by dumping
/tmp/preview.log. - Regenerated the compiled workflow lock file.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/docs-noob-tester.md |
Updates the readiness wait loop and adds crash/timeout diagnostics for the docs server. |
.github/workflows/docs-noob-tester.lock.yml |
Regenerates the compiled workflow to include the updated readiness logic. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 3
| echo "Waiting for server... ($i/45) (status: $STATUS)" && sleep 3 | ||
| MAX_WAIT=135 # 45 attempts × 3s = 135s max wait | ||
| WAITED=0 | ||
| until curl -sf http://localhost:4321/gh-aw/ > /dev/null 2>&1; do |
There was a problem hiding this comment.
curl -sf in the until condition has no connect/overall timeout, so a stalled connect/read can block the loop longer than the intended 3s cadence and make the effective wait exceed (or behave inconsistently with) MAX_WAIT. Consider adding --connect-timeout/--max-time (or similar) so each probe is bounded and the MAX_WAIT semantics stay reliable.
| until curl -sf http://localhost:4321/gh-aw/ > /dev/null 2>&1; do | |
| until curl -sf --connect-timeout 1 --max-time 2 http://localhost:4321/gh-aw/ > /dev/null 2>&1; do |
| if [ -f /tmp/server.pid ] && ! kill -0 "$(cat /tmp/server.pid)" 2>/dev/null; then | ||
| echo "::error::Documentation server process died before becoming ready. Server log:" | ||
| cat /tmp/preview.log | ||
| exit 1 |
There was a problem hiding this comment.
The crash-detection check uses kill -0 "$(cat /tmp/server.pid)" which is vulnerable to races/invalid contents (e.g., empty/partial PID file) and reintroduces a command substitution in a set -e script. Safer is to read the PID with shell redirection (read -r pid < /tmp/server.pid) and validate it’s a non-empty numeric PID before calling kill -0.
| if [ -f /tmp/server.pid ] && ! kill -0 "$(cat /tmp/server.pid)" 2>/dev/null; then | |
| echo "::error::Documentation server process died before becoming ready. Server log:" | |
| cat /tmp/preview.log | |
| exit 1 | |
| if [ -f /tmp/server.pid ]; then | |
| read -r pid < /tmp/server.pid || pid= | |
| case "$pid" in | |
| ''|*[!0-9]*) | |
| echo "::error::Documentation server PID file is invalid before readiness check. Server log:" | |
| cat /tmp/preview.log | |
| exit 1 | |
| ;; | |
| esac | |
| if ! kill -0 "$pid" 2>/dev/null; then | |
| echo "::error::Documentation server process died before becoming ready. Server log:" | |
| cat /tmp/preview.log | |
| exit 1 | |
| fi |
| [ "$STATUS" = "200" ] && echo "Server ready at http://localhost:4321/gh-aw/!" && break | ||
| echo "Waiting for server... ($i/45) (status: $STATUS)" && sleep 3 | ||
| MAX_WAIT=135 # 45 attempts × 3s = 135s max wait | ||
| WAITED=0 |
There was a problem hiding this comment.
This workflow imports shared/docs-server-lifecycle.md, but that shared document’s “Waiting for Server Readiness” section still shows the old STATUS=$(curl ...) pattern (shared/docs-server-lifecycle.md:54-58). Consider updating the shared instructions (or noting the newer pattern here) to avoid the prompt/documentation drifting from the actual pre-agent step behavior.
| WAITED=0 | |
| WAITED=0 | |
| # Note: shared/docs-server-lifecycle.md may still show the older | |
| # STATUS=$(curl ...) example, but this workflow intentionally uses | |
| # the newer direct until-curl pattern plus PID/timeout checks so the | |
| # documented behavior here matches the actual pre-agent step. |
GitHub Actions runs bash steps with
set -e. The command substitutionSTATUS=$(curl ...)propagates curl's exit code 7 (CURLE_COULDNT_CONNECT) directly to bash, which terminates the step on the very first connection attempt—the retry loop never retried.Changes
docs-noob-tester.md— Wait for server readiness step: ReplaceSTATUS=$(curl ...)withuntil curl -sf ...— bash exempts loop conditions fromset -e, so a failed curl causes the loop body to run instead of killing the step.kill -0 $(cat /tmp/server.pid)inside the loop to distinguish server crash from slow startup./tmp/preview.logto surface the actual startup error.docs-noob-tester.lock.yml: recompiled.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/usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw(http block)https://api.github.com/repos/actions/checkout/git/ref/tags/v6/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --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)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/checkout/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/actions/github-script/git/ref/tags/v9/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linu--jq(http block)/usr/bin/gh gh api /repos/actions/github-script/git/ref/tags/v9 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/actions/setup-go/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-go/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linu--jq(http block)https://api.github.com/repos/actions/setup-node/git/ref/tags/v4/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v4 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet env -json .cfg 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/pkg/tool/linux_amd64/vet(http block)https://api.github.com/repos/actions/setup-node/git/ref/tags/v6/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --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)/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet(http block)/usr/bin/gh gh api /repos/actions/setup-node/git/ref/tags/v6 --jq [.object.sha, .object.type] | @tsv -json GO111MODULE x_amd64/vet GOINSECURE GOMOD GOMODCACHE x_amd64/vet env -json GO111MODULE 64/pkg/tool/linux_amd64/vet GOINSECURE GOMOD GOMODCACHE 64/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: