Skip to content

release: v0.9.0 (worker 0.2.0, receiver 0.2.0, admin 0.6.0) #9

release: v0.9.0 (worker 0.2.0, receiver 0.2.0, admin 0.6.0)

release: v0.9.0 (worker 0.2.0, receiver 0.2.0, admin 0.6.0) #9

Workflow file for this run

# Cut a GitHub Release for the WHOLE pi-dispatch tool when the ROOT package.json version changes on main.
#
# This is distinct from release.yml, which PUBLISHES the @edgehero/pi-dispatch-admin npm package (and tags
# its own releases admin-v*). This workflow owns the v* tags = the product's releases. To cut one, bump
# `version` in the root package.json in a PR; it is idempotent (skips when the tag already exists), so an
# unrelated root package.json edit — a dependency bump, a script tweak — is a no-op.
#
# main is branch-protected (a PR is required and the five contract checks in pi-upgrade-check.yml must be
# green, admins included), so a push here is an already-gated merge — nothing here merges anything
# (CONST-MERGE-NEVER-AUTOMATIC). No secret is required to tag a release; the optional
# repo secret ANTHROPIC_API_KEY enables AI-written notes, and without it the release falls back to a plain
# commit list. Optional repo variable RELEASE_MODEL (default: claude-sonnet-5).
name: repo-release
on:
push:
branches: [main]
paths:
- "package.json" # the ROOT one only (a bare path does not match nested workspace package.json files)
- ".github/workflows/repo-release.yml"
- ".github/scripts/release-notes.mjs"
workflow_dispatch: {}
permissions:
contents: write # create tags + releases
concurrency:
group: repo-release
cancel-in-progress: false
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history for the release-notes commit range
- uses: actions/setup-node@v4
with:
node-version: "22.19"
- name: Resolve version + decide release
id: v
env:
GH_TOKEN: ${{ github.token }}
run: |
V=$(node -p "require('./package.json').version")
echo "version=$V" >> "$GITHUB_OUTPUT"
if gh release view "v$V" >/dev/null 2>&1; then
echo "release=no" >> "$GITHUB_OUTPUT"; echo "release v$V already exists — skip"
else
echo "release=yes" >> "$GITHUB_OUTPUT"
fi
- name: Build release notes
if: steps.v.outputs.release == 'yes'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
RELEASE_MODEL: ${{ vars.RELEASE_MODEL }}
# Which artifact is being described. release.yml passes its own — the script used to name the
# admin extension unconditionally, so every tool release described the wrong thing.
PRODUCT: pi-dispatch
PRODUCT_DESC: a self-hosted service that runs pi coding-agent jobs, one isolated container per job
run: |
# Range since the previous tool release (v*); the whole repo, not just one workspace.
PREV=$(git tag --list 'v*' --sort=-v:refname | head -n1)
RANGE=${PREV:+$PREV..HEAD}
COMMITS=$(git log $RANGE --no-merges --pretty=format:'- %s' | head -n 80)
if [ -n "$ANTHROPIC_API_KEY" ] && COMMITS="$COMMITS" VERSION="v${{ steps.v.outputs.version }}" \
node .github/scripts/release-notes.mjs > /tmp/notes.md 2>/tmp/notes.err; then
echo "release notes: AI-written"
else
echo "release notes: AI unavailable ($(head -n1 /tmp/notes.err 2>/dev/null)) — using commit list"
# Capped for the same reason the AI notes are: eighty commit subjects is a diff, not notes. The
# count is stated rather than trimmed silently — a truncated list that looks complete is worse
# than a long one.
TOTAL=$(printf '%s\n' "$COMMITS" | wc -l | tr -d ' ')
{
echo "### Changes"; echo
printf '%s\n' "$COMMITS" | head -n 12
if [ "$TOTAL" -gt 12 ]; then printf -- '- …and %s more\n' "$((TOTAL - 12))"; fi
} > /tmp/notes.md
fi
# The detail escape hatch, appended on BOTH paths. This link is what earns the brevity above:
# nothing is hidden, it is one click away instead of in the body.
if [ -n "$PREV" ]; then
printf '\n**Full changelog**: %s/%s/compare/%s...v%s\n' \
"${{ github.server_url }}" "${{ github.repository }}" "$PREV" "${{ steps.v.outputs.version }}" >> /tmp/notes.md
fi
- name: Create GitHub Release
if: steps.v.outputs.release == 'yes'
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "v${{ steps.v.outputs.version }}" \
--title "pi-dispatch v${{ steps.v.outputs.version }}" \
--notes-file /tmp/notes.md