From 766a7df84780ee8933317f310be83414142ec6af Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 5 Aug 2026 16:01:05 -0400 Subject: [PATCH] build: Add gh-aw-version single source of truth + justfile wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compiling a .md workflow source with a gh-aw CLI version other than the one ci.yml's check-drift job is pinned to can silently produce a different .lock.yml (compiler behavior, embedded action SHAs, etc. all vary by version), which then either falls out of sync with the .md source or looks fine locally but diffs against what CI recompiles. Previously the pinned version (v0.81.6) was a literal hardcoded in ci.yml, with no way for a human or an agent (drafter.md/fix.md, which both recompile lockfiles as part of their own workflow) to discover or match it short of reading that file. .github/aw/gh-aw-version is now the single place that version lives. ci.yml reads it instead of hardcoding the pin, and a new justfile wraps the two commands anyone touching a workflow .md file needs: `just setup` (installs/re-pins the extension to match the file) and `just compile` (runs the actual gh-aw compile). README.md, drafter.md, and fix.md are updated to point at `just setup && just compile` instead of telling readers to invoke gh-aw directly with no version guidance. review.md is untouched: it never edits workflow .md files or compiles, so it has no need for this instruction. Verified `gh aw compile drafter review fix --approve` (v0.81.6, matching the pin) against the new drafter.md/fix.md: only each file's embedded body_hash metadata comment changes in its .lock.yml, since gh-aw runtime-imports the prompt body rather than inlining it at compile time — no frontmatter or generated-workflow behavior changed. Assisted-by: AI Signed-off-by: Colin Walters --- .github/aw/gh-aw-version | 1 + .github/workflows/ci.yml | 4 ++-- .github/workflows/drafter.lock.yml | 2 +- .github/workflows/drafter.md | 6 +++++- .github/workflows/fix.lock.yml | 2 +- .github/workflows/fix.md | 7 ++++++- README.md | 13 ++++++++----- justfile | 27 +++++++++++++++++++++++++++ 8 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 .github/aw/gh-aw-version create mode 100644 justfile diff --git a/.github/aw/gh-aw-version b/.github/aw/gh-aw-version new file mode 100644 index 0000000..87f1de3 --- /dev/null +++ b/.github/aw/gh-aw-version @@ -0,0 +1 @@ +v0.81.6 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f19b6ac..f081a5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail - gh extension install github/gh-aw --pin v0.81.6 + gh extension install github/gh-aw --pin "$(cat .github/aw/gh-aw-version)" - name: Compile workflows env: @@ -35,6 +35,6 @@ jobs: run: | set -euo pipefail git diff --exit-code -- .github/workflows/ || { - echo "::error::Compiled .lock.yml files are out of sync with their .md sources — run 'gh aw compile drafter review fix --approve' locally and commit the result." + echo "::error::Compiled .lock.yml files are out of sync with their .md sources — run 'just setup && just compile' locally and commit the result." exit 1 } diff --git a/.github/workflows/drafter.lock.yml b/.github/workflows/drafter.lock.yml index daf9696..3fb64b9 100644 --- a/.github/workflows/drafter.lock.yml +++ b/.github/workflows/drafter.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c63e43cf3367847c4905a8f552762317e2f23bf7dec9f6aeda06e1533c3c02a0","body_hash":"ba20b548a109d0543cc97c40c4489adf959746f827804fe9bb9a92e092c3019d","compiler_version":"v0.81.6","strict":true,"agent_id":"claude","agent_model":"claude-sonnet-4-5-20250929","engine_versions":{"claude":"2.1.191"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"c63e43cf3367847c4905a8f552762317e2f23bf7dec9f6aeda06e1533c3c02a0","body_hash":"4a75fbb575d36ee47fb2137429e62f373f47407302a9ced1b37fb0c171fd9d43","compiler_version":"v0.81.6","strict":true,"agent_id":"claude","agent_model":"claude-sonnet-4-5-20250929","engine_versions":{"claude":"2.1.191"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_APP_PRIVATE_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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":"v7.0.0"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"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.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/.github/workflows/drafter.md b/.github/workflows/drafter.md index a0c22b6..b488677 100644 --- a/.github/workflows/drafter.md +++ b/.github/workflows/drafter.md @@ -153,7 +153,11 @@ implementation. the repo has no such tooling, validate by inspection and, where reasonable, a small ad hoc check (e.g. `python3 -c '...'`) instead of assuming a command that may not exist. -5. Once validation passes, open a pull request via the `create-pull-request` +5. If your change edits any `.github/workflows/*.md` file, recompile the + lockfiles before opening the pull request: run `just setup && just + compile` (this recompiles *all* workflows, not just the one you touched — + every `.lock.yml` must stay in sync with its `.md` source). +6. Once validation passes, open a pull request via the `create-pull-request` safe-output. The PR description should summarize the change and state how it was validated. diff --git a/.github/workflows/fix.lock.yml b/.github/workflows/fix.lock.yml index d7bb101..af509f5 100644 --- a/.github/workflows/fix.lock.yml +++ b/.github/workflows/fix.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1ca03aeaba21a98c0281ed6b2b276ee71ad6359d4c80f9651f85b9ab5cbfa82f","body_hash":"7abbeff6513848492ccd1df75734d5450c138545f9f90a4e1ac3343c00c006c4","compiler_version":"v0.81.6","strict":true,"agent_id":"claude","agent_model":"claude-sonnet-4-5-20250929","engine_versions":{"claude":"2.1.191"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"1ca03aeaba21a98c0281ed6b2b276ee71ad6359d4c80f9651f85b9ab5cbfa82f","body_hash":"a56233d53ce1d403009c4c9edab85ba96661bbc596ded0e9796f9661dddb3538","compiler_version":"v0.81.6","strict":true,"agent_id":"claude","agent_model":"claude-sonnet-4-5-20250929","engine_versions":{"claude":"2.1.191"}} # gh-aw-manifest: {"version":1,"secrets":["ANTHROPIC_API_KEY","GH_AW_APP_PRIVATE_KEY","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","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":"v7.0.0"},{"repo":"actions/create-github-app-token","sha":"bcd2ba49218906704ab6c1aa796996da409d3eb1","version":"v3.2.0"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"ba6380cc6e5be5d21677bebe04d52fb48e3abec7","version":"v0.81.6"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11","digest":"sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.11@sha256:979723c628182da7729333f2208bb249fd25ddee579645cf9a3892d681a929c7"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11","digest":"sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.11@sha256:807e4831999b44513b0a66e5859d478dc4da7ae74ab1918cec967d513f95bf9d"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11","digest":"sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.11@sha256:ff27ea0525ad953a6adee28a5fbe9d2e22be47dbec755c15767af4ea3f91df7d"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.30","digest":"sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.30@sha256:35625d1a2269b1238606078c879f59a91cffc4ac33eb54bf39c6418822c1a8be"},{"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.4.0","digest":"sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036","pinned_image":"ghcr.io/github/github-mcp-server:v1.4.0@sha256:2afb26356481d1a350e14544a6e160f7f7ec1561a1ea309b823665abf0309036"}]} # This file was automatically generated by gh-aw (v0.81.6). DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/.github/workflows/fix.md b/.github/workflows/fix.md index 77e1cdf..a4aa381 100644 --- a/.github/workflows/fix.md +++ b/.github/workflows/fix.md @@ -216,7 +216,12 @@ cause a duplicate re-trigger. 6. Validate your change using whatever the repo actually provides (tests, a lint command, or a small ad hoc check) — do not assume tooling that may not exist. -7. Push your fix as a new commit on the same branch via the +7. If your change edits any `.github/workflows/*.md` file, recompile the + lockfiles: run `just setup && just compile` (this recompiles *all* + workflows, not just the one you touched — every `.lock.yml` must stay in + sync with its `.md` source). Include the resulting `.lock.yml` changes in + your commit. +8. Push your fix as a new commit on the same branch via the `push-to-pull-request-branch` safe-output. Do not open a new PR. ## Constraints diff --git a/README.md b/README.md index 7adb544..5562512 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,8 @@ A few things here are non-obvious and were hard-won getting this to actually wor and an upgrade once shipped a compiler whose AI-credits pricing table had fallen out of sync with Anthropic's current model line — agents started failing with errors like ` has no AI credits pricing`. The fix: pin the extension to a known-good version - (`gh extension install github/gh-aw --pin v0.81.6`, as `ci.yml` does) and set + (the pinned version lives in `.github/aw/gh-aw-version`, used by both `ci.yml` and `just + setup` — run `just setup` locally to install it) and set `engine.model` explicitly in each `.md` file's frontmatter to an exact dated model ID (e.g. `claude-sonnet-4-5-20250929`) instead of a floating alias, then recompile. If workflows that were working suddenly start failing with a pricing-lookup error, this is @@ -313,9 +314,9 @@ now at least readable by the agent, but it was never the intended recovery path. (The App used for this specific demo instance is `bootc-bot`; the steps above are written generically so you can register your own App if adapting this repo.) -3. Make sure `gh aw compile` runs cleanly against the `.md` files (see below) — run `gh - aw compile drafter review fix --approve` after any workflow edit. Pin the gh-aw - extension version when you do (see "Design notes and gotchas" above). +3. Make sure the workflows compile cleanly from the `.md` files (see below) — run `just + setup && just compile` after any workflow edit (see "Design notes and gotchas" above + for why the extension version must stay pinned). 4. If validating your project needs network access beyond gh-aw's engine defaults — e.g. `cargo test`/`cargo check` reaching a crate registry, or any other compiled language's package manager — add a `network:` block to `drafter.md`'s and `fix.md`'s @@ -414,9 +415,11 @@ the same names. After editing any `.md` file, recompile with: ``` -gh aw compile drafter review fix --approve +just setup && just compile ``` +(see the `justfile` at the repo root). + ## Files The pipeline lives entirely in diff --git a/justfile b/justfile new file mode 100644 index 0000000..723cc9d --- /dev/null +++ b/justfile @@ -0,0 +1,27 @@ +# gh-agentic-workflows development helpers. +# Run `just --list` to see available recipes. + +gh_aw_version := `cat .github/aw/gh-aw-version` + +# Install (or re-pin) the gh-aw CLI extension to the version this repo requires. +setup: + #!/usr/bin/env bash + set -euo pipefail + wanted="{{ gh_aw_version }}" + if gh extension list 2>/dev/null | grep -q 'github/gh-aw'; then + installed=$(gh aw version 2>&1 | awk '{print $NF}') + if [ "$installed" = "$wanted" ]; then + echo "gh-aw $wanted already installed." + exit 0 + fi + echo "gh-aw installed at ${installed:-unknown}, re-pinning to $wanted..." + gh extension remove gh-aw + fi + gh extension install github/gh-aw --pin "$wanted" + +# Compile all gh-aw workflow .md sources to .lock.yml (run `just setup` first). +compile: + gh aw compile drafter review fix --approve + +# Setup + compile in one step. +all: setup compile