From 0cef033a6a2c8df7d930be2e0986e6b35881e6d9 Mon Sep 17 00:00:00 2001 From: claude-ceo-assistant Date: Thu, 7 May 2026 15:26:22 -0700 Subject: [PATCH] ci(canary): route curl -w to tempfile to satisfy status-capture lint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two API probes used the unsafe shape rejected by lint-curl-status-capture.yml (per feedback_curl_status_capture_pollution): status=$(curl ... -w '%{http_code}' ... || echo "000") When curl exits non-zero (transport error, --fail-with-body 4xx/5xx), the `-w` already wrote a code; the `|| echo "000"` then APPENDS another "000", yielding "000000" or "409000" — passes shape checks while looking right. Switch to the canonical safe shape (set +e + tempfile + cat): set +e curl ... -w '%{http_code}' >code_file 2>/dev/null set -e status=$(cat code_file 2>/dev/null || true) [ -z "$status" ] && status="000" Inline comment in both probe steps explains the lint constraint so the next editor doesn't re-introduce the bad pattern. Refs: #72, lint failure on PR #77 (1/22 red → 22/22 expected green) --- .github/workflows/auto-sync-canary.yml | 28 ++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/auto-sync-canary.yml b/.github/workflows/auto-sync-canary.yml index 9f55aa19..0c0573db 100644 --- a/.github/workflows/auto-sync-canary.yml +++ b/.github/workflows/auto-sync-canary.yml @@ -211,15 +211,23 @@ jobs: run: | set -euo pipefail response_file="$(mktemp)" + code_file="$(mktemp)" # `--max-time 30`: full call ceiling. `--connect-timeout 10`: - # DNS + TCP. `-w "%{http_code}"` to a separate var (not - # response body — see feedback_curl_status_capture_pollution). - status=$(curl -sS -o "$response_file" \ + # DNS + TCP. `-w "%{http_code}"` routed to a tempfile so curl's + # exit code can't pollute the captured status — see + # feedback_curl_status_capture_pollution + the + # `lint-curl-status-capture.yml` gate that rejects the unsafe + # `$(curl ... || echo "000")` shape. + set +e + curl -sS -o "$response_file" \ --max-time 30 --connect-timeout 10 \ -w "%{http_code}" \ -H "Authorization: token ${AUTO_SYNC_TOKEN}" \ -H "Accept: application/json" \ - "https://${GITEA_HOST}/api/v1/user" || echo "000") + "https://${GITEA_HOST}/api/v1/user" >"$code_file" 2>/dev/null + set -e + status=$(cat "$code_file" 2>/dev/null || true) + [ -z "$status" ] && status="000" if [ "$status" != "200" ]; then echo "::error::Token rotation suspected: GET /api/v1/user returned HTTP $status (expected 200)." >&2 @@ -247,12 +255,20 @@ jobs: run: | set -euo pipefail response_file="$(mktemp)" - status=$(curl -sS -o "$response_file" \ + code_file="$(mktemp)" + # See first probe step for the rationale on the tempfile-routed + # `-w "%{http_code}"` pattern — the unsafe `|| echo "000"` shape + # is rejected by lint-curl-status-capture.yml. + set +e + curl -sS -o "$response_file" \ --max-time 30 --connect-timeout 10 \ -w "%{http_code}" \ -H "Authorization: token ${AUTO_SYNC_TOKEN}" \ -H "Accept: application/json" \ - "https://${GITEA_HOST}/api/v1/repos/${REPO_PATH}" || echo "000") + "https://${GITEA_HOST}/api/v1/repos/${REPO_PATH}" >"$code_file" 2>/dev/null + set -e + status=$(cat "$code_file" 2>/dev/null || true) + [ -z "$status" ] && status="000" if [ "$status" != "200" ]; then echo "::error::Token lacks read:repository scope on ${REPO_PATH}: HTTP $status." >&2