[WIP] Fix the failing GitHub Actions workflow agent#1418
Conversation
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/6efe3da1-78c0-44c2-b7ce-06b070ab91b8
There was a problem hiding this comment.
Pull request overview
Fixes a CI failure in the agent container startup by preventing Claude Code config files from being clobbered when adding apiKeyHelper, preserving existing Claude Code state.
Changes:
- Update
write_api_key_helperto mergeapiKeyHelperinto existing JSON usingnode, rather than overwriting the entire file. - Add a fallback path that overwrites the config if the Node-based merge cannot run.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let obj = {}; | ||
| try { obj = JSON.parse(fs.readFileSync(file, 'utf8')); } catch(e) {} | ||
| obj.apiKeyHelper = helper; | ||
| fs.writeFileSync(file, JSON.stringify(obj) + '\n'); | ||
| " 2>/dev/null; then | ||
| chmod 666 "$config_file" | ||
| echo "[entrypoint] ✓ Merged apiKeyHelper into $label" | ||
| else | ||
| # Fallback if node is unavailable or the file is not valid JSON | ||
| echo "{\"apiKeyHelper\":\"$CLAUDE_CODE_API_KEY_HELPER\"}" > "$config_file" | ||
| chmod 666 "$config_file" | ||
| echo "[entrypoint] ✓ Wrote apiKeyHelper to $label (overwrite fallback)" | ||
| fi |
There was a problem hiding this comment.
The node -e merge currently treats invalid JSON as success because JSON.parse(...) errors are swallowed. That means the else branch (commented as "file is not valid JSON") will never run for parse failures, and the log will say "Merged" even though the file was effectively overwritten with only apiKeyHelper. Consider making parse failures cause a non-zero exit (so the fallback path is taken and/or a clearer log is emitted), or update the comment/logging to reflect the actual behavior.
| # Fallback if node is unavailable or the file is not valid JSON | ||
| echo "{\"apiKeyHelper\":\"$CLAUDE_CODE_API_KEY_HELPER\"}" > "$config_file" | ||
| chmod 666 "$config_file" | ||
| echo "[entrypoint] ✓ Wrote apiKeyHelper to $label (overwrite fallback)" |
There was a problem hiding this comment.
The fallback JSON write uses echo "{\"apiKeyHelper\":\"$CLAUDE_CODE_API_KEY_HELPER\"}", which will produce invalid JSON (or change semantics) if CLAUDE_CODE_API_KEY_HELPER contains characters like quotes, backslashes, or newlines. Since this branch is used when node is missing/fails, it would be safer to generate JSON via a proper encoder (e.g., Node/JSON.stringify or another escaping approach) rather than interpolating directly into a JSON string.
See below for a potential fix:
AWF_KEY_HELPER="$CLAUDE_CODE_API_KEY_HELPER" python - << 'EOF' > "$config_file"
import json, os, sys
helper = os.environ.get("AWF_KEY_HELPER", "")
json.dump({"apiKeyHelper": helper}, sys.stdout)
sys.stdout.write("\n")
EOF
chmod 666 "$config_file"
echo "[entrypoint] ✓ Wrote apiKeyHelper to $label (overwrite fallback)"
fi
fi
else
echo "[entrypoint] Creating $label with apiKeyHelper..."
AWF_KEY_HELPER="$CLAUDE_CODE_API_KEY_HELPER" python - << 'EOF' > "$config_file"
import json, os, sys
helper = os.environ.get("AWF_KEY_HELPER", "")
json.dump({"apiKeyHelper": helper}, sys.stdout)
sys.stdout.write("\n")
EOF
| echo "[entrypoint] $label exists but missing apiKeyHelper, merging..." | ||
| # Use node to safely add apiKeyHelper to existing JSON without losing other fields | ||
| # (e.g. hasCompletedOnboarding, session tokens, user preferences) | ||
| if AWF_CONFIG_FILE="$config_file" AWF_KEY_HELPER="$CLAUDE_CODE_API_KEY_HELPER" \ | ||
| node -e " | ||
| const fs = require('fs'); | ||
| const file = process.env.AWF_CONFIG_FILE; | ||
| const helper = process.env.AWF_KEY_HELPER; | ||
| let obj = {}; | ||
| try { obj = JSON.parse(fs.readFileSync(file, 'utf8')); } catch(e) {} | ||
| obj.apiKeyHelper = helper; | ||
| fs.writeFileSync(file, JSON.stringify(obj) + '\n'); | ||
| " 2>/dev/null; then | ||
| chmod 666 "$config_file" | ||
| echo "[entrypoint] ✓ Merged apiKeyHelper into $label" | ||
| else |
There was a problem hiding this comment.
This change is fixing a CI blocker by preserving existing Claude Code config fields while adding apiKeyHelper, but there doesn’t appear to be an automated test that exercises the write_api_key_helper behavior (e.g., pre-seeded ~/.claude.json and ~/.claude/settings.json with additional fields, then verifying they are preserved and apiKeyHelper is set). Adding an integration test for this merge path would help prevent regressions in future entrypoint edits.
….1.81+ (#1414) * fix: write apiKeyHelper to ~/.claude/settings.json for Claude Code v2.1.81+ Claude Code v2.1.81+ reads apiKeyHelper from ~/.claude/settings.json instead of ~/.claude.json. The entrypoint now writes to both paths for backward/forward compatibility. Fixes: github/gh-aw#22713 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * [WIP] Fix the failing GitHub Actions workflow agent (#1418) * Initial plan * fix: preserve existing claude config when merging apiKeyHelper Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/6efe3da1-78c0-44c2-b7ce-06b070ab91b8 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> * fix: exclude GITHUB_API_URL from agent container when api-proxy is enabled (#1419) * Initial plan * fix: exclude GITHUB_API_URL from agent container when api-proxy is enabled Regression introduced in commit 9761e87 (PR #1305) re-added an unconditional GITHUB_API_URL assignment that PR #1303 had fixed. Combined with the missing EXCLUDED_ENV_VARS entry for the --env-all code path, GITHUB_API_URL was leaking into the agent container when api-proxy is enabled. With GITHUB_API_URL present in the agent, the Copilot CLI routes its token exchange to api.github.com/copilot_internal/v2/token using the placeholder COPILOT_GITHUB_TOKEN instead of going through COPILOT_API_URL → api-proxy (which injects the real token), causing a 401 authentication failure. Fix: - Add GITHUB_API_URL to EXCLUDED_ENV_VARS when api-proxy is enabled (covers the --env-all path used by build-test.lock.yml) - Replace the duplicate unconditional assignment with the correct conditional version that was already present below it (from PR #1303) Tests: - should not leak GITHUB_API_URL to agent when api-proxy is enabled with envAll - should pass GITHUB_API_URL to agent when api-proxy is NOT enabled with envAll See: github/gh-aw#20875 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * fix: restore GITHUB_API_URL in agent container when api-proxy is enabled (#1420) * Initial plan * fix: restore GITHUB_API_URL in agent container when api-proxy is enabled Root cause: commit 5a56789 excluded GITHUB_API_URL from the agent container when api-proxy is enabled, based on the incorrect theory that its presence would cause the Copilot CLI to route token exchange through api.github.com with the placeholder token. Evidence from CI logs: successful runs (worktree-audit-observability) had GITHUB_API_URL present and worked; all failing runs lacked it and failed immediately with "Authentication failed" after ~1.2 seconds. The Copilot CLI needs GITHUB_API_URL to locate the GitHub API. Its Copilot-specific calls (token exchange, inference) already route through COPILOT_API_URL → api-proxy regardless of GITHUB_API_URL being set. Fix: - Remove EXCLUDED_ENV_VARS.add('GITHUB_API_URL') from api-proxy block - Change conditional GITHUB_API_URL assignment to unconditional - Update test to expect GITHUB_API_URL present even with api-proxy enabled Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw-firewall/sessions/db4a1afe-02b9-43f2-bfae-41febbcbc8b5 --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
write_api_key_helperinentrypoint.shoverwrites entire config file instead of mergingapiKeyHelperfield into existing JSONwrite_api_key_helperto usenodefor safe JSON merging (preserving existing config likehasCompletedOnboarding, session tokens, etc.)Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.