Skip to content

feat(hooks): one-shot ax hooks install --all + repo-free install nu… #639

feat(hooks): one-shot ax hooks install --all + repo-free install nu…

feat(hooks): one-shot ax hooks install --all + repo-free install nu… #639

name: Release Please
on:
push:
branches: [main]
workflow_dispatch:
inputs:
tag_name:
description: Existing release tag to build artifacts for. Leave empty to run release-please.
required: false
type: string
release:
types: [published]
permissions:
contents: write
pull-requests: write
jobs:
release-please:
if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.tag_name == '') }}
runs-on: ubuntu-latest
outputs:
releases_created: ${{ steps.release.outputs.releases_created }}
version: ${{ steps.release.outputs.version }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN || github.token }}
# Artifacts build only on the `release: published` event (or manual dispatch
# with a tag). The push run that creates the release via release-please must
# NOT also build - when it did, its publish job raced the release-event run's
# publish job and --clobber uploads interleaved, leaving a checksums.txt from
# one build next to a tarball from the other (v0.24.0 incident).
build-artifacts:
if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '') }}
name: Build ${{ matrix.artifact }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- runner: macos-14
artifact: axctl-darwin-arm64
- runner: ubuntu-24.04
artifact: axctl-linux-x64
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history + tags so build-axctl.ts can bake the release tag
- uses: oven-sh/setup-bun@v2
with:
bun-version: "1.3.10"
- name: Install ripgrep (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y ripgrep
- name: Install ripgrep (macOS)
if: runner.os == 'macOS'
run: brew install ripgrep
- run: bun install --frozen-lockfile
- run: bash -n install.sh
- run: bun run typecheck
- run: bun test
- run: bun run check:cli-reference
- run: bun scripts/build-axctl.ts apps/axctl/src/cli/index.ts dist/axctl
- name: Smoke compiled CLI
run: |
set -euo pipefail
./dist/axctl --version
./dist/axctl help
- name: Package binary
run: |
set -euo pipefail
file dist/axctl
mkdir -p package
cp dist/axctl package/axctl
chmod 755 package/axctl
tar -czf "${{ matrix.artifact }}.tar.gz" -C package axctl
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: ${{ matrix.artifact }}.tar.gz
if-no-files-found: error
publish-artifacts:
needs: build-artifacts
# Run even when a build leg failed so the platforms that DID build still get
# published - a flaky test on one runner must not zero out the whole release
# (the v0.29.0 incident: darwin's build failed on a flaky shiki test, so this
# job was skipped and `latest` shipped with 0 assets, 404ing every install).
# The verify step below then fails the run loudly if any asset is missing.
if: >-
${{ always()
&& needs.build-artifacts.result != 'cancelled'
&& (github.event_name == 'release'
|| (github.event_name == 'workflow_dispatch' && inputs.tag_name != '')) }}
runs-on: ubuntu-latest
concurrency:
group: release-assets-${{ github.event_name == 'release' && github.event.release.tag_name || inputs.tag_name }}
permissions:
contents: write
env:
GH_TOKEN: ${{ github.token }}
TAG_NAME: ${{ github.event_name == 'release' && github.event.release.tag_name || inputs.tag_name }}
GH_REPO: ${{ github.repository }}
steps:
- uses: actions/download-artifact@v4
with:
path: release-assets
merge-multiple: true
- name: Upload release assets
run: |
set -euo pipefail
cd release-assets
if [ -z "$TAG_NAME" ]; then
echo "TAG_NAME is empty - refusing to guess the target release" >&2
exit 1
fi
if ! ls ./*.tar.gz >/dev/null 2>&1; then
echo "::error::no platform binaries were built for $TAG_NAME - every build leg failed; nothing to publish" >&2
exit 1
fi
shasum -a 256 ./*.tar.gz > checksums.txt
gh release upload "$TAG_NAME" ./*.tar.gz checksums.txt --repo "$GH_REPO" --clobber
- name: Verify release has every expected asset
run: |
set -euo pipefail
# Keep in sync with the build-artifacts matrix.
expected="axctl-darwin-arm64.tar.gz axctl-linux-x64.tar.gz checksums.txt"
have="$(gh release view "$TAG_NAME" --repo "$GH_REPO" --json assets --jq '.assets[].name')"
missing=""
for asset in $expected; do
printf '%s\n' "$have" | grep -qx "$asset" || missing="$missing $asset"
done
if [ -n "$missing" ]; then
echo "::error::release $TAG_NAME is missing assets:$missing - a 'latest' install will 404 for those platforms. Fix the build, then re-run: gh workflow run release-please.yml -f tag_name=$TAG_NAME" >&2
exit 1
fi
echo "release $TAG_NAME has all expected assets: $expected"