Skip to content

feat: release pplx 2026.07.23.1784784046+c8b317a #2

feat: release pplx 2026.07.23.1784784046+c8b317a

feat: release pplx 2026.07.23.1784784046+c8b317a #2

Workflow file for this run

# Cuts a public release whenever the Buildkite release-sync job lands a new
# dist/ payload on main, then hands off to release.yml (stage -> smoke -> publish).
#
# Design notes:
# - The human gate is upstream (manual Buildkite trigger); this workflow is fully
# automatic and uses only GITHUB_TOKEN (no PAT, no PRs, no admin).
# - Releases created here are DRAFTS: no events fire, no git tag exists, and
# releases/latest (used by install.sh) is unaffected until release.yml's
# publish job uploads all assets and flips the draft to published.
# - GITHUB_TOKEN-created releases/tags never trigger other workflows, so the
# handoff to release.yml is an explicit `gh workflow run` (workflow_dispatch
# is the documented exception that always starts runs).
# - The `paths:` filter is an economy filter only; correctness comes from the
# in-job idempotency guard (dist-version marker in the release body). Never
# strip that HTML comment when editing release notes, or the version will be
# re-released under a new tag.
# - Stale drafts (superseded calvers) should be DELETED, never published by
# hand: publishing an asset-less draft creates a real tag and can mis-point
# releases/latest.
name: Cut Release
on:
push:
branches: [main]
paths:
- dist/metadata.json
# Backfill / recovery: re-run detection for whatever dist/ is at main HEAD.
workflow_dispatch: {}
permissions: {}
# Serialize runs so tag computation + draft creation never race.
# cancel-in-progress must stay false: a running cut is never killed; one newest
# pending run waits and older pending runs are superseded (intermediate
# metadata.json pushes collapse into the newest run, which is intended).
concurrency:
group: cut-release
cancel-in-progress: false
defaults:
run:
shell: bash
jobs:
cut:
name: Detect dist version and cut draft release
# push is already main-scoped; this extends the same provenance gate to
# manual dispatch (which can otherwise target any ref).
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write # list/create/edit releases
actions: write # dispatch release.yml
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
- name: Verify dist payload
run: |
set -euo pipefail
for f in metadata.json pplx-aarch64-apple-darwin.bin pplx-x86_64-linux-gnu.bin pplx-aarch64-linux-gnu.bin; do
if [[ ! -f "dist/${f}" ]]; then
echo "::error::missing dist/${f} at ${GITHUB_SHA}"
exit 1
fi
done
- name: Read dist metadata
id: meta
run: |
set -euo pipefail
version="$(jq -er '.version' dist/metadata.json)"
agi_commit="$(jq -er '.agi_commit' dist/metadata.json)"
# Whole-string anchors (no per-line grep) so multi-line values cannot
# smuggle extra $GITHUB_OUTPUT lines; charset matches install.sh's
# VERSION allowlist.
if [[ ! "${version}" =~ ^[0-9A-Za-z][0-9A-Za-z.+-]*$ ]]; then
echo "::error::unexpected version format in dist/metadata.json: ${version}"
exit 1
fi
if [[ ! "${agi_commit}" =~ ^[0-9a-f]{7,40}$ ]]; then
echo "::error::unexpected agi_commit format in dist/metadata.json: ${agi_commit}"
exit 1
fi
{
echo "version=${version}"
echo "agi_commit=${agi_commit}"
} >> "$GITHUB_OUTPUT"
- name: Resolve release for this version
id: resolve
env:
VERSION: ${{ steps.meta.outputs.version }}
run: |
set -euo pipefail
marker="<!-- pplx-dist-version: ${VERSION} -->"
# Draft releases have no git tag, so the REST list (which includes
# drafts for tokens with push access) is the source of truth.
gh api --paginate "repos/${GH_REPO}/releases" > /tmp/releases.json
match="$(jq -cs --arg marker "${marker}" \
'first(add[]? | select((.body // "") | contains($marker)) | {id, tag_name, draft}) // empty' \
/tmp/releases.json)"
if [[ -n "${match}" ]]; then
tag="$(jq -r '.tag_name' <<<"${match}")"
draft="$(jq -r '.draft' <<<"${match}")"
release_id="$(jq -r '.id' <<<"${match}")"
if [[ "${draft}" == "false" ]]; then
echo "Version ${VERSION} already published as ${tag}; nothing to do."
echo "action=skip" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Version ${VERSION} already has draft ${tag} (a prior run stalled); re-dispatching the pipeline."
{
echo "action=reuse"
echo "tag=${tag}"
echo "release_id=${release_id}"
} >> "$GITHUB_OUTPUT"
exit 0
fi
# Next public tag: patch bump of the highest vA.B.C across ALL
# releases (drafts included) and git tags. Minor/major bumps are
# human decisions (cut such a tag manually; the counter continues
# from it).
latest="$(
{
jq -r '.[].tag_name' /tmp/releases.json
git ls-remote --tags origin 'refs/tags/v*' \
| awk '{print $2}' | sed -e 's#^refs/tags/##' -e 's#\^{}$##'
} | { grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' || true; } | sort -V | tail -n 1
)"
latest="${latest:-v0.0.0}"
IFS=. read -r major minor patch <<<"${latest#v}"
tag="v${major}.${minor}.$((patch + 1))"
echo "Version ${VERSION} is unreleased; next tag is ${tag} (after ${latest})."
{
echo "action=create"
echo "tag=${tag}"
} >> "$GITHUB_OUTPUT"
- name: Create draft release
if: steps.resolve.outputs.action == 'create'
env:
VERSION: ${{ steps.meta.outputs.version }}
AGI_COMMIT: ${{ steps.meta.outputs.agi_commit }}
TAG: ${{ steps.resolve.outputs.tag }}
run: |
set -euo pipefail
body="$(printf '%s\n' \
"pplx CLI \`${VERSION}\` (agi commit \`${AGI_COMMIT}\`)." \
"" \
"Install via the README one-liner; binaries, manifest.json and SHA256SUMS are attached by the release pipeline." \
"" \
"<!-- pplx-dist-version: ${VERSION} -->")"
gh api -X POST "repos/${GH_REPO}/releases" \
-f tag_name="${TAG}" \
-f target_commitish="${GITHUB_SHA}" \
-f name="${TAG}" \
-f body="${body}" \
-F draft=true \
-F generate_release_notes=true \
--jq '.html_url'
- name: Retarget existing draft
if: steps.resolve.outputs.action == 'reuse'
env:
RELEASE_ID: ${{ steps.resolve.outputs.release_id }}
run: |
set -euo pipefail
gh api -X PATCH "repos/${GH_REPO}/releases/${RELEASE_ID}" \
-f target_commitish="${GITHUB_SHA}" \
--jq '.html_url'
- name: Dispatch release pipeline
if: steps.resolve.outputs.action != 'skip'
env:
TAG: ${{ steps.resolve.outputs.tag }}
run: |
set -euo pipefail
if [[ -z "${TAG}" ]]; then
echo "::error::resolved tag is empty; refusing to dispatch"
exit 1
fi
gh workflow run release.yml --ref main \
-f dry_run=false \
-f tag_name="${TAG}" \
-f sha="${GITHUB_SHA}"
echo "Dispatched release.yml for ${TAG} @ ${GITHUB_SHA}"