fix: fall back to unauthenticated GitHub API when SAML-enforced token…#40250
Conversation
… fails When the current token (e.g. an enterprise SAML-enforced token) cannot access cross-organization public repositories, the update command now falls back to unauthenticated GitHub public API calls instead of failing immediately. Affected functions in pkg/cli/update_workflows.go: - getRepoDefaultBranch - getLatestBranchCommitSHA - defaultWorkflowUpdateDeps (releases API) Affected functions in pkg/parser/remote_fetch.go: - listDirSubdirsForHost - downloadFileFromGitHubWithDepth - listWorkflowFilesForHost - listDirAllFilesForHost - resolveRefToSHA Each function now tries: authenticated API → git clone → unauthenticated HTTP to api.github.com (for public repos). Also includes action version bumps and container pin updates from the update run. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment MemoryNote This comment is managed by comment memory.It stores persistent context for this thread in the code block at the top of this comment.
|
UpdateContainerPins runs after compilation, so lock files were missing the @sha256: digest suffixes on container images. Now UpdateContainerPins returns whether new pins were added, and both update and upgrade commands recompile all workflows when new container pins are stored. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves gh aw update resilience when the active GH_TOKEN is SAML-enforced / cross-org restricted by adding an unauthenticated GitHub.com REST API fallback after authenticated API and git-based fallbacks fail. It also refreshes pinned action versions (notably actions/checkout@v7) and updates various generated lock/pin artifacts produced by the update run.
Changes:
- Add unauthenticated
api.github.comfallback logic for repo/branch/release lookups in the update command and for remote workflow/file/ref fetching in the parser. - Bump pinned action versions (e.g.,
actions/checkout@v7.0.0,actions/setup-java@v5.3.0,github/stale-repos@v9.0.15) and update workflow sources accordingly. - Refresh generated
.lock.ymlworkflows and action/container pin JSON artifacts.
Show a summary per file
| File | Description |
|---|---|
| pkg/cli/update_workflows.go | Adds unauthenticated GitHub.com REST fallback for repo default-branch, branch head SHA, and releases listing when auth fails. |
| pkg/parser/remote_fetch.go | Adds unauthenticated GitHub.com REST fallback paths for ref resolution and contents-based listing/download after auth+git fallbacks fail. |
| pkg/actionpins/data/action_pins.json | Updates embedded action pins; container pins were pruned too aggressively (blocking issue). |
| pkg/workflow/data/action_pins.json | Updates action pins data used by workflow compilation; container pins were pruned too aggressively (blocking issue). |
| .github/aw/actions-lock.json | Updates repo action/cache pin data and container pins cache produced by the update run. |
| .github/workflows/visual-regression-checker.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/visual-regression-checker.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/update-astro.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/update-astro.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/unbloat-docs.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/unbloat-docs.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/super-linter.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/super-linter.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/stale-repo-identifier.md | Bumps github/stale-repos to v9.0.15 in workflow source. |
| .github/workflows/stale-repo-identifier.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/shared/mcp-debug.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/release.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/release.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/hourly-ci-cleaner.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/hourly-ci-cleaner.lock.yml | Regenerated lock; contains incorrect checkout version metadata (blocking issue). |
| .github/workflows/go-pattern-detector.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/go-pattern-detector.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/daily-skill-optimizer.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/daily-skill-optimizer.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/daily-geo-optimizer.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/daily-geo-optimizer.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/daily-astrostylelite-markdown-spellcheck.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/daily-astrostylelite-markdown-spellcheck.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/copilot-centralization-optimizer.md | Pins actions/upload-artifact to v7.0.1 in workflow source. |
| .github/workflows/copilot-centralization-optimizer.lock.yml | Regenerates compiled lock workflow with updated pins. |
| .github/workflows/avenger.md | Bumps actions/checkout to v7.0.0 in workflow source. |
| .github/workflows/avenger.lock.yml | Regenerated lock; contains incorrect checkout version metadata (blocking issue). |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 35/35 changed files
- Comments generated: 14
| endpoint := fmt.Sprintf("https://api.github.com/repos/%s/%s/contents/%s?ref=%s", | ||
| owner, repo, url.PathEscape(path), url.QueryEscape(ref)) |
| remoteLog.Printf("Git fallback also failed, attempting unauthenticated API for %s/%s@%s", owner, repo, ref) | ||
| return resolveRefToSHAViaPublicAPI(owner, repo, ref) |
| remoteLog.Printf("Git fallback also failed, attempting unauthenticated API for %s/%s/%s@%s", owner, repo, path, ref) | ||
| return downloadFileViaPublicAPI(owner, repo, path, ref) |
| remoteLog.Printf("Git fallback also failed, attempting unauthenticated API for %s/%s@%s", owner, repo, ref) | ||
| return listWorkflowFilesViaPublicAPI(owner, repo, ref, workflowPath) |
| remoteLog.Printf("Git fallback also failed, attempting unauthenticated API for %s/%s@%s", owner, repo, ref) | ||
| return listDirAllFilesViaPublicAPI(owner, repo, ref, dirPath) |
| # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"59322418e4416285cdf6f2652d03ef51d831d150733af0dc3d593ab4c01f9270","body_hash":"4d51ef429f578f6a81277bb5b7fb6972093ac204c21c50b06168c848812076b4","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.179"}} | ||
| # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.7"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.7"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.7"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.27","digest":"sha256:fe984bddde4ec05d756d9043edb0a32912e6b7b72f6a121b1082f29221421cc7","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.27@sha256:fe984bddde4ec05d756d9043edb0a32912e6b7b72f6a121b1082f29221421cc7"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.3.0","digest":"sha256:5c83359327a0bacc3d34db730bea6557d39d341cee0bf6c58c9a896e33150e80","pinned_image":"ghcr.io/github/github-mcp-server:v1.3.0@sha256:5c83359327a0bacc3d34db730bea6557d39d341cee0bf6c58c9a896e33150e80"}]} | ||
| # gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"25cb376cd027add89e92da99ef0c8b00edfe0fbb21dfb12f16f88af3ea7c52cd","body_hash":"4d51ef429f578f6a81277bb5b7fb6972093ac204c21c50b06168c848812076b4","strict":true,"agent_id":"claude","engine_versions":{"claude":"2.1.179"}} | ||
| # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0","version":"9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-go","sha":"4a3601121dd01d1626a1e23e37211e3254c1c06c","version":"v6.4.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.7"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.7"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.7"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.27","digest":"sha256:fe984bddde4ec05d756d9043edb0a32912e6b7b72f6a121b1082f29221421cc7","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.27@sha256:fe984bddde4ec05d756d9043edb0a32912e6b7b72f6a121b1082f29221421cc7"},{"image":"ghcr.io/github/gh-aw-node","digest":"sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b","pinned_image":"ghcr.io/github/gh-aw-node@sha256:529d02eb970b1161aa25c593a9c3df57fdfad5a8add328cb3b6eccef66f3183b"},{"image":"ghcr.io/github/github-mcp-server:v1.3.0","digest":"sha256:5c83359327a0bacc3d34db730bea6557d39d341cee0bf6c58c9a896e33150e80","pinned_image":"ghcr.io/github/github-mcp-server:v1.3.0@sha256:5c83359327a0bacc3d34db730bea6557d39d341cee0bf6c58c9a896e33150e80"}]} |
|
@copilot run pr-finisher skill |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…, fix path escaping, restore container pins Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Addressed all open review threads in commit
|
|
Hey @pelikhan 👋 — thanks for tackling the SAML token fallback! The three-tier retry strategy (authenticated API → git clone → unauthenticated HTTP) is a solid approach for handling enterprise SAML restrictions on public repos, and the review feedback addressing the GHES host guard and path-escaping fixes is exactly the right kind of hardening. A couple of things that would make this easier to land cleanly:
If you'd like a hand, you can assign this prompt to your coding agent:
|
Summary
Two related improvements land together:
SAML-enforcement fallback — when a SAML-enforced enterprise token is rejected while accessing a public cross-org
github.comrepo,update_workflowsandremote_fetchnow transparently retry the same request against the unauthenticated public GitHub API (60 req/hour tier), instead of surfacing an authentication error to the user.Container-pin auto-recompile —
UpdateContainerPinsnow returns a boolean signalling whether new digests were written; callers (updateandupgradecommands) use that signal to automatically invokerecompileAllWorkflowswhen fresh pins are detected and--no-compileis not set, eliminating the manual re-run step previously required.Bundled alongside these fixes: a sweep bumping
actions/checkoutfrom v6.0.3 → v7.0.0 andgithub/stale-reposfrom v9.0.14 → v9.0.15, with bothaction_pins.jsondata files updated and all.mdworkflow specs recompiled.Changes by area
SAML / unauthenticated API fallback (
pkg/cli/update_workflows.go,pkg/parser/remote_fetch.go)fetchPublicGitHubAPI(CLI layer) andfetchPublicGitHubContentsAPI(parser layer) — shared HTTP helpers that call the unauthenticatedapi.github.comendpoint with correct per-segment path encoding (preserving/separators).github.comhosts only and is only attempted whengitutil.IsAuthErrorconfirms the upstream error is authentication-related.resolveRefToSHAViaPublicAPI), file download (downloadFileViaPublicAPI), workflow/directory file listing (listWorkflowFilesViaPublicAPI,listDirAllFilesViaPublicAPI), and subdirectory listing (listDirSubdirsViaPublicAPI).getRepoDefaultBranch,getLatestBranchCommitSHA, and the releases API closure inupdate_workflows.goall route through the new fallback.Container-pin recompile signal (
pkg/cli/update_container_pins.go,pkg/cli/update_command.go,pkg/cli/upgrade_command.go)UpdateContainerPins() errorUpdateContainerPins() (bool, error).mdfiles whenbool == true && !noCompileupdate_command.go—RunUpdateWorkflowscaptures the new boolean and calls the newrecompileAllWorkflowshelper.upgrade_command.go— same pattern applied to the upgrade command'sUpdateContainerPinscall site.UpdateContainerPinsmust update their call sites to capture the additional return value.Action-pin data (
pkg/actionpins/data/action_pins.json,pkg/workflow/data/action_pins.json)actions/checkoutpinned tov7.0.0(SHA9c091bb), replacing v6.0.3 (SHAdf4cb1c).github/stale-reposbumped fromv9.0.14→v9.0.15.containerssection placed beforeentries; object fields ordered alphabetically.Workflow spec recompilation (
.github/workflows/*.md,agentic_commands.yml,agentics-maintenance.yml).mdworkflow specs updated with the newactions/checkout@v7.0.0pin.agentic_commands.ymlandagentics-maintenance.yml(the two compiled YAML files in the diff) regenerated to match.actions/upload-artifactupdated to the more specificv7.0.1tag incopilot-centralization-optimizer.md.Impact assessment
UpdateContainerPinssignatureTesting notes
gh aw updateagainst a SAML-enforced repo no longer fails with an auth error when the target workflow references a publicgithub.comaction.gh aw updateorgh aw upgradewhen container pins change automatically triggers recompilation without requiring a separategh aw compileinvocation.--no-compilesuppresses the automatic recompile step.UpdateContainerPinsmust be updated to capture(bool, error).