diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 6f94a1f3db..8540b4dd72 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -190,13 +190,16 @@ already ships. Every agentic workflow run therefore downloads the CLI twice — job, once in the `detection` job — and each download is a chance to hit a transient GitHub CDN 5xx. The gap is structural, not a stale-image problem: `github/gh-aw-actions`'s `compat.json` caps `max-agent` at `1.0.56` (exactly what the runner image caches), while `DefaultCopilotVersion` is -already `1.0.73` on gh-aw v0.83.1 and `1.0.75` on `main` — so bumping gh-aw *widens* the gap. +`1.0.73` on the gh-aw v0.83.1 compiler this repo's lock files are pinned to, and `1.0.75` as of +gh-aw v0.83.4 — so bumping gh-aw *widens* the gap. -**There is no repo-side fix.** All of the following were evaluated and rejected: +**There is no repo-side fix *today*.** All of the following were evaluated and rejected: - `engine.version` is silently ignored for the Copilot engine — gh-aw overwrites it with - `DefaultCopilotVersion` (`pkg/workflow/copilot_engine_installation.go`, still the case on `main`). - `gh aw compile --strict` reports no error, and the regenerated lock keeps the pinned version. + `DefaultCopilotVersion` (`pkg/workflow/copilot_engine_installation.go`, still the case in + v0.83.4). `gh aw compile --strict` reports no error, and the regenerated lock keeps the pinned + version. This is the one rejected option upstream is actively changing — see + [Tracking the upstream fix](#tracking-the-upstream-fix). - Hand-editing a `.lock.yml` (older pin, extra retries) is overwritten on the next `gh aw compile`. - `engine.command:` pointed at `/opt/hostedtoolcache/copilot-cli//x64/bin/copilot` bypasses the install step, but hardcodes a path that rotates with runner images and skips the `.copilot` @@ -215,6 +218,56 @@ version the hosted runner toolcache is expected to contain (in practice the `com when a version is pinned. Merely choosing a default somewhere inside the compat window still downloads unless that exact version is cached. +#### Tracking the upstream fix + +The drift is filed upstream as [github/gh-aw#48358][gh-aw-48358] — *"DefaultCopilotVersion drifts +past compat.json max-agent, forcing a network install on every job and disabling the toolcache +path"*. It is still open, and nothing in gh-aw v0.83.2 – v0.83.4 touches the install path: +v0.83.4 only bumps `DefaultCopilotVersion` to `1.0.75`, and `install_copilot_cli.sh` is byte-for-byte +unchanged since v0.83.1 (both curls already carry `--retry 3 --retry-delay 5`, which is the retry +budget the failing run exhausted). + +The unblocking change is [github/gh-aw#48519][gh-aw-48519] — *"honor `engine.version` for +copilot"*, open against `main`. It makes the compiler emit `install_copilot_cli.sh ` +instead of always substituting `DefaultCopilotVersion`. That alone does **not** restore compat-matrix +resolution — an explicit version still skips it — but it hands us the lever we currently lack, +because `find_cached_copilot_bin` already short-circuits on an exact match: + +```text +Found candidate: /opt/hostedtoolcache/copilot-cli/1.0.56/x64/bin/copilot (version: 1.0.56, arch: x64) +Exact version match found: /opt/hostedtoolcache/copilot-cli/1.0.56/x64/bin/copilot +``` + +That branch returns *before* the cache-TTL check, so pinning the version the runner image already +caches skips both downloads outright — which is precisely what today's `range: none..none` lookup +cannot do. + +**Once #48519 ships in a gh-aw release**, the repo-side follow-up is: + +1. Bump the pinned gh-aw toolchain, recompile with `gh aw compile --strict`, review the `.lock.yml` + diff, and run `python .github/scripts/check_action_pins.py` (see + [Compile on the pinned toolchain](#compile-on-the-pinned-toolchain-and-check-the-pins-afterwards)). +2. Pin the engine to the version the hosted runner caches: + + ```yaml + engine: + id: copilot + version: "1.0.56" # == compat.json max-agent == hosted-runner toolcache entry + ``` + + No workflow here declares `engine:` today, so this is new frontmatter. Check whether gh-aw's + frontmatter merging lets a `shared/` import carry it before adding the block to all ~30 + workflows individually. +3. Verify a run logs `Exact version match found:` instead of `No compatible toolcache entry found` + followed by `-> Downloading ...`. + +Re-check *both* the `compat.json` window and the version the runner image actually caches before +choosing the pin, and only pin a version that satisfies both: it must sit inside +`min-agent`..`max-agent` *and* exist in the toolcache (`1.0.56` is both today). If they diverge — +the image caches something outside the compat window — stay on a compat-sanctioned version and keep +paying for the download. `max-agent` is the supported ceiling; pinning past it to chase a cache hit +would run every agentic workflow on an unsupported CLI. + ## Catalog ### Agentic workflows @@ -312,3 +365,5 @@ Reusable agentic-workflow snippets imported via `imports:` in workflow frontmatt - **Minimal permissions.** Workflows declare the least privilege they need; write capabilities flow through gh-aw `safe-outputs:` rather than direct `permissions: write-all`. [gh-aw]: https://github.com/github/gh-aw +[gh-aw-48358]: https://github.com/github/gh-aw/issues/48358 +[gh-aw-48519]: https://github.com/github/gh-aw/pull/48519