Skip to content

headroom-release-watch #46

headroom-release-watch

headroom-release-watch #46

# Watch upstream headroom (headroomlabs-ai/headroom) for a NEW release and, when one appears that is
# newer than what we're built against, bump our `headroom-core` pin to that release TAG, prove it
# builds + tests green (lexical / no-ml), then bump our own patch version and push the commit to
# `dev` and open (or update) a PR to `main`. Tagging + republishing (docker.yml/release.yml) happens
# separately, in headroom-release-publish.yml, only once that PR is actually merged — see that
# file's header for why.
#
# Deliberately does NOT touch `main` directly: it isn't a repo admin, so pushing straight to a
# protected main via GITHUB_TOKEN doesn't actually work (required-review branch protection blocks
# it, same as it would for any non-admin). `dev` has no such protection, which is the point of the
# split — see RELEASING.md.
#
# Why polling (not a webhook): we don't control headroomlabs-ai/headroom, so their side can't dispatch
# to us. A daily poll is the realistic catch. Manual `workflow_dispatch` is provided for an immediate run.
#
# FLOOR = the last headroom release that PREDATES the `ml`-feature gate (#2165). Only releases strictly
# newer than the floor carry the gate, so we never bump onto a pre-gate release (which would drag the
# whole ONNX stack back in). Until the first post-gate release ships we stay pinned to the merge commit.
name: headroom-release-watch
on:
schedule:
- cron: "17 6 * * *" # 06:17 UTC daily (off the :00 pileup)
workflow_dispatch: {}
permissions:
contents: write # commit the bump + push to dev
pull-requests: write # open/update the dev -> main PR
env:
UPSTREAM: headroomlabs-ai/headroom
FLOOR: v0.31.0
# Same BUSBAR_REF convention ci.yml/release.yml use for the sibling path dependency this crate
# needs (busbar-plugin-sdk) — see the sibling-checkout step below for why it's required at all.
BUSBAR_REF: dev
jobs:
watch:
runs-on: ubuntu-latest
steps:
# headroom-hook's Cargo.toml declares busbar-plugin-sdk as `path = "../busbarAI/crates/..."`
# — a real sibling-relative path (see the `a61e7f8` fix), which means whatever checks this
# repo out MUST also check out a real `busbarAI` as an actual filesystem sibling. This job
# was checking out ONLY headroom-hook at the workspace root with no sibling at all — `../busbarAI`
# resolved to nothing, so `cargo build`/`cargo test` below failed immediately on every real
# (bump=yes) run. Fix: check both repos out into explicit sibling paths under the workspace,
# matching release.yml's own layout, and run every later step with
# `working-directory: headroom-hook` instead of the (implicit) workspace root.
- name: Checkout headroom-hook
uses: actions/checkout@v4
with:
ref: dev
path: headroom-hook
fetch-depth: 0
- name: Checkout busbar (sibling path dependency)
uses: actions/checkout@v4
with:
repository: GetBusbar/busbar
ref: ${{ env.BUSBAR_REF }}
path: busbarAI
- uses: dtolnay/rust-toolchain@stable
- name: Resolve latest upstream release + current pin
id: resolve
working-directory: headroom-hook
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
latest="$(gh api "repos/${UPSTREAM}/releases/latest" --jq .tag_name)"
current="$(grep -m1 'headroom-core' Cargo.toml | grep -oE 'tag = "[^"]+"' | cut -d'"' -f2 || true)"
echo "latest=$latest" >> "$GITHUB_OUTPUT"
echo "current=$current" >> "$GITHUB_OUTPUT"
# A bump is warranted iff latest is strictly greater than BOTH the floor and our current tag.
newest_vs_floor="$(printf '%s\n%s\n' "$latest" "$FLOOR" | sort -V | tail -1)"
bump=no
if [ "$latest" != "$FLOOR" ] && [ "$newest_vs_floor" = "$latest" ] && [ "$latest" != "$current" ]; then
bump=yes
fi
echo "bump=$bump" >> "$GITHUB_OUTPUT"
echo "::notice::upstream latest=$latest, current pin=${current:-<commit>}, floor=$FLOOR -> bump=$bump"
- name: Bump pin, build + test (lexical/no-ml), push to dev, open/update PR to main
if: steps.resolve.outputs.bump == 'yes'
working-directory: headroom-hook
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LATEST: ${{ steps.resolve.outputs.latest }}
run: |
set -euo pipefail
# Re-pin headroom-core to the new release TAG (drops any rev pin), keeping default-features = false.
# NOTE: use `~` as the s/// delimiter, NOT `{}` — the pattern/replacement contain literal braces
# and `[^}]`, which perl mis-balances against `{}` delimiters (dies with "Substitution replacement
# not terminated"). `~` never appears in a Cargo git-dep line, so it is a safe delimiter.
perl -0pi -e 's~headroom-core = \{ git = "https://github.com/headroomlabs-ai/headroom"[^}]*\}~headroom-core = { git = "https://github.com/headroomlabs-ai/headroom", tag = "'"$LATEST"'", default-features = false }~' Cargo.toml
grep headroom-core Cargo.toml
cargo update -p headroom-core
# Prove the lexical build + tests are green against the new headroom BEFORE pushing anything.
cargo build --release --locked
cargo test --locked
# Bump our own patch version (a dependency bump is a new hook release).
old="$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)"
new="$(echo "$old" | awk -F. '{printf "%s.%s.%s", $1, $2, $3+1}')"
perl -0pi -e 's/^version = "'"$old"'"/version = "'"$new"'"/m' Cargo.toml
cargo update -p headroom-hook --precise "$new" 2>/dev/null || cargo generate-lockfile
git config user.name "headroom-release-watch"
git config user.email "actions@users.noreply.github.com"
git add Cargo.toml Cargo.lock
git commit -m "chore(deps): headroom-core -> ${LATEST}; headroom-hook v${new}
Auto-bump by headroom-release-watch: upstream headroom released ${LATEST}, which now carries
the ml-feature gate. Built + tested green (lexical/no-ml)."
git push origin HEAD:dev
echo "new_version=${new}" >> "$GITHUB_ENV"
# Open a dev -> main PR if one isn't already open (a second bump before the first is
# reviewed just adds a commit to the same PR, since it's pushing to the same dev branch).
existing="$(gh pr list --repo "${GITHUB_REPOSITORY}" --base main --head dev --state open --json number --jq '.[0].number // empty')"
if [ -z "$existing" ]; then
gh pr create --repo "${GITHUB_REPOSITORY}" --base main --head dev \
--reviewer MattJackson \
--title "Release: headroom-hook v${new} (headroom-core ${LATEST})" \
--body "Auto-opened by headroom-release-watch. Bumps headroom-core to ${LATEST} and headroom-hook to v${new}. Built + tested green (lexical/no-ml) before this PR was opened. Merging this triggers headroom-release-publish.yml, which tags the merge commit and republishes docker.yml + release.yml."
else
echo "::notice::PR #$existing already open dev -> main, pushed additional commit onto it"
fi
echo "::notice::pushed headroom-hook v${new} (headroom-core ${LATEST}) to dev; awaiting PR review/merge to publish"