Updating Agentic Workflow Versions
Use this skill when the gh-aw Version Check workflow
(.github/workflows/gh-aw-version-check.yml) opens a "Workflow version drift"
issue, or whenever you need to bump the versions the compiled workflow
.lock.yml files are pinned to.
There is no automation for the regeneration itself — it is a deliberate,
human-reviewed step. Pushing changes under .github/workflows/ requires a token
with the workflows permission, which the built-in GITHUB_TOKEN lacks, so a
maintainer (or an agent with suitably-permissioned credentials) performs the
recompile locally and opens a PR.
Background
Each agentic workflow source (.github/workflows/*.md) is compiled by the
gh-aw compiler into a committed *.lock.yml. The version baked into a lock is
whatever compiler produced it, and every workflow tracks the same gh-aw
version: the newest github/gh-aw release or prerelease, whichever was
published most recently. There are no per-workflow categories — a bump
recompiles all the locks together.
The detector version is baked into the locks. gh-aw's
buildInstallThreatDetectStep unconditionally emits
constants.DefaultThreatDetectVersion (a hardcoded tag, e.g. v0.4.12) as the
argument to install_threat_detect_binary.sh. There is no CLI flag, env var, or
frontmatter field that consults an alternate version at compile time. The
detector pin therefore only moves when either:
github/gh-awbumps the constant upstream (typically after a detector promotion) and a normal drift-recompile picks up the new tag, or- a maintainer does a targeted post-compile edit of the lock (see Testing an unpromoted detector prerelease in the smokes below).
Promoting a detector release is not by itself enough to put it into the smokes — it takes effect only once the upstream constant is bumped and this repo's locks are recompiled against that gh-aw tag.
1. Determine the target gh-aw version
The drift issue lists it. To confirm or resolve it yourself (any method works —
gh, curl, or the GitHub Releases UI): newest github/gh-aw release or
prerelease, i.e. the most recent by publish date whose tag looks like
v<digit>...; ignore drafts.
For example, with gh available:
gh api repos/github/gh-aw/releases --paginate \
--jq '.[] | select(.draft == false) | select(.tag_name | test("^v[0-9]")) | [.published_at, .tag_name] | @tsv' \
| sort | tail -n1 | cut -f2
In the steps below, refer to this as <TARGET_GH_AW>.
2. Recompile the locks
Recompile every workflow with the same tag. The released gh aw extension is
the simplest route:
gh extension install github/gh-aw --pin <TARGET_GH_AW> --force
gh aw compile --action-mode action --action-tag <TARGET_GH_AW> --no-check-update \
.github/workflows/*.md
Building the compiler from source instead
If gh extension install is unavailable (no gh auth, offline, etc.), build
gh-aw from source — but you must set both version ldflags:
git clone --depth 1 --branch <TAG> https://github.com/github/gh-aw /tmp/gh-aw-src
( cd /tmp/gh-aw-src && go build -ldflags "-X main.version=<TAG> -X main.isRelease=true" -o /tmp/gh-aw ./cmd/gh-aw )
[!IMPORTANT]
-X main.isRelease=trueis not optional.cmd/gh-aw/main.godefaultsisReleaseto"false"and passes it toworkflow.SetIsRelease(), which normalizes the emittedcompiler_version/GH_AW_VERSIONtodevand skips release-only generation. Locks compiled without it look superficially fine but carrydevat runtime.
Verify before compiling:
/tmp/gh-aw version # must print the target tag, not "dev"
3. Verify and open a PR
- Sanity-check that only the intended version bumps changed:
Confirm each regenerated lock carries the target version in both places — they must not saygit status --short -- .github/workflows git diff -- .github/workflowsdev:
Re-running the gh-aw Version Check workflow after the PR merges should report no drift.grep -o '"compiler_version":"[^"]*"' .github/workflows/*.lock.yml grep -n 'GH_AW_VERSION:' .github/workflows/*.lock.yml - Commit only the regenerated
*.lock.ymlfiles (and any intended.mdchanges). The compiler also refreshes.github/aw/actions-lock.jsonand may touch.gitattributes— that churn is expected. Open a PR describing the version bumps. - Pushing workflow-file changes requires a token with the
workflowspermission. The built-inGITHUB_TOKEN(github-actions[bot]) is rejected for changes under.github/workflows/, so this regeneration is done by a maintainer / agent whose credentials carry that permission — not by an automated push in the version-check workflow. - After merging, dispatch the top-level Smoke workflow to confirm the new versions run green.
Testing an unpromoted detector prerelease
There are two sanctioned paths, depending on what you want to exercise.
Replay path (preferred for most prerelease iteration)
Dispatch .github/workflows/replay-detection.yml with
detector_source=release, detector_ref=<prerelease tag>, and use_awf=true.
It downloads that exact release asset and runs it under AWF against a prior
gh-aw run's artifacts. No lock edit needed.
Smoke path (when you specifically need fresh AWF + fresh artifacts)
The smokes only ever see whatever tag gh-aw's constant currently points at (promoted, stable). To point them at an unpromoted prerelease, do a targeted post-compile edit of the smoke locks:
sed -i 's|install_threat_detect_binary.sh" v0\.[0-9.]*|install_threat_detect_binary.sh" <PRERELEASE_TAG>|' \
.github/workflows/smoke-copilot-standalone.lock.yml \
.github/workflows/smoke-claude-standalone.lock.yml \
.github/workflows/smoke-codex-standalone.lock.yml
Commit those three files and open a PR. Do not patch
constants.DefaultThreatDetectVersion in a gh-aw fork to accomplish this:
that route corrupts the compiler-version story (locks would carry a fork tag or
lie about upstream), and it inverts the invariant that the constant tracks the
promoted detector.
Only touch the smoke locks. Leave detection-stats-daily,
detection-failure-monitor, gh-aw-issue-digest, and gh-aw-parity-monitor on
the compiler-emitted tag — they are not the test bed for detector prereleases.
The edit is deliberately ephemeral: the next gh aw compile run will regenerate
the locks from constants.DefaultThreatDetectVersion and revert the pin. That
is intentional — prerelease pins should not survive a routine recompile. Once
the detector is promoted and gh-aw bumps its constant, a normal drift-recompile
picks it up on the standard path.