Skip to content

Release 0.3.10 (#1488) #16

Release 0.3.10 (#1488)

Release 0.3.10 (#1488) #16

Workflow file for this run

name: Release CLI Binaries
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version tag (e.g., v0.2.0)'
required: true
type: string
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
target: bun-linux-x64
binary: archon-linux-x64
- os: ubuntu-latest
target: bun-linux-arm64
binary: archon-linux-arm64
- os: ubuntu-latest
target: bun-windows-x64
binary: archon-windows-x64.exe
- os: macos-latest
target: bun-darwin-x64
binary: archon-darwin-x64
- os: macos-latest
target: bun-darwin-arm64
binary: archon-darwin-arm64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.11
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build binary
env:
# On workflow_dispatch, github.ref_name is the branch name (e.g. 'main'),
# not the version tag — fall back to the user-supplied `version` input.
VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
GIT_COMMIT: ${{ github.sha }}
TARGET: ${{ matrix.target }}
OUTFILE: dist/${{ matrix.binary }}
run: |
# Strip 'v' prefix from tag (e.g. v0.3.1 → 0.3.1)
VERSION="${VERSION#v}"
# Short commit (first 8 chars of SHA)
GIT_COMMIT="${GIT_COMMIT::8}"
mkdir -p dist
VERSION="$VERSION" GIT_COMMIT="$GIT_COMMIT" TARGET="$TARGET" OUTFILE="$OUTFILE" bash scripts/build-binaries.sh
- name: Smoke-test built binary
if: matrix.target == 'bun-linux-x64' && runner.os == 'Linux'
env:
RAW_VERSION: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.ref_name }}
run: |
chmod +x dist/${{ matrix.binary }}
if ! VERSION_OUTPUT=$(./dist/${{ matrix.binary }} version 2>&1); then
echo "::error::Binary failed to execute"
echo "$VERSION_OUTPUT"
exit 1
fi
echo "$VERSION_OUTPUT"
# Must not error with "Failed to read version" or similar
if echo "$VERSION_OUTPUT" | grep -qE "Failed to read version|package\.json not found|bad installation"; then
echo "::error::Binary is broken — version command cannot read embedded version"
echo "::error::This means BUNDLED_IS_BINARY was not set to true at build time."
exit 1
fi
# Must report 'Build: binary', not 'Build: source'
if ! echo "$VERSION_OUTPUT" | grep -q "Build: binary"; then
echo "::error::Binary reports wrong build type"
echo "::error::Expected 'Build: binary' in version output"
exit 1
fi
# Must report the (stripped) tag version. Compare against the same
# value that was baked into the binary (VERSION#v), not the raw ref,
# so the check doesn't rely on the CLI re-adding a 'v' prefix.
EXPECTED_VERSION="${RAW_VERSION#v}"
if echo "$VERSION_OUTPUT" | grep -qE "v?${EXPECTED_VERSION}(\s|$)"; then
echo "::notice::Binary correctly reports version ${EXPECTED_VERSION}"
else
echo "::error::Binary does not report version ${EXPECTED_VERSION}"
exit 1
fi
- name: Smoke-test bundled defaults load
if: matrix.target == 'bun-linux-x64' && runner.os == 'Linux'
run: |
# `workflow list` requires running from a git repo
BIN="$PWD/dist/${{ matrix.binary }}"
TMP_REPO=$(mktemp -d)
cd "$TMP_REPO"
git init -q
git -c user.email=ci@example.com -c user.name=ci commit --allow-empty -q -m init
if ! OUTPUT=$("$BIN" workflow list 2>&1); then
echo "::error::workflow list failed to execute"
echo "$OUTPUT"
exit 1
fi
echo "$OUTPUT"
if echo "$OUTPUT" | grep -q "archon-assist"; then
echo "::notice::Bundled workflows loaded correctly"
else
echo "::error::Bundled workflows did not load — embedded JSON may be missing from the binary"
exit 1
fi
- name: Smoke-test Claude binary-path resolver (negative case)
if: matrix.target == 'bun-linux-x64' && runner.os == 'Linux'
run: |
# With no CLAUDE_BIN_PATH and no config, running a Claude workflow must
# fail with a clear, user-facing error — NOT with "Module not found
# /Users/runner/..." which would indicate the resolver was bypassed.
BIN="$PWD/dist/${{ matrix.binary }}"
TMP_REPO=$(mktemp -d)
cd "$TMP_REPO"
git init -q
git -c user.email=ci@example.com -c user.name=ci commit --allow-empty -q -m init
# Run without CLAUDE_BIN_PATH set. Expect a clean resolver error.
# Capture both stdout and stderr; we only care that the resolver message is present.
# --no-worktree skips isolation: this test exercises the Claude resolver
# path, not worktree setup. Without it we hit the worktree auto-sync added
# in #1310 first and fail on "neither origin/HEAD nor origin/main exist"
# because the fresh `git init` tmp repo has no origin configured.
set +e
OUTPUT=$(env -u CLAUDE_BIN_PATH "$BIN" workflow run archon-assist --no-worktree "hello" 2>&1)
EXIT_CODE=$?
set -e
echo "$OUTPUT"
if echo "$OUTPUT" | grep -qE 'Module not found.*Users/runner'; then
echo "::error::Resolver was bypassed — SDK hit the import.meta.url fallback (regression of #1210)"
exit 1
fi
if ! echo "$OUTPUT" | grep -q "Claude Code not found"; then
echo "::error::Expected 'Claude Code not found' error when CLAUDE_BIN_PATH is unset"
exit 1
fi
if ! echo "$OUTPUT" | grep -q "CLAUDE_BIN_PATH"; then
echo "::error::Error message does not reference CLAUDE_BIN_PATH remediation"
exit 1
fi
echo "::notice::Resolver error path works (exit code: $EXIT_CODE)"
- name: Smoke-test Claude subprocess spawn (positive case)
if: matrix.target == 'bun-linux-x64' && runner.os == 'Linux'
run: |
# Install Claude Code via the native installer (Anthropic's recommended
# default) and run a workflow with CLAUDE_BIN_PATH set. The subprocess
# must spawn cleanly. We do NOT require the query to succeed (no auth
# in CI — an auth error is fine and expected); we only fail if the SDK
# can't find the executable, which would indicate a resolver regression.
curl -fsSL https://claude.ai/install.sh | bash
CLI_PATH="$HOME/.local/bin/claude"
if [ ! -x "$CLI_PATH" ]; then
echo "::error::Claude Code binary not found after curl install at $CLI_PATH"
ls -la "$HOME/.local/bin/" || true
exit 1
fi
echo "Using CLAUDE_BIN_PATH=$CLI_PATH"
BIN="$PWD/dist/${{ matrix.binary }}"
TMP_REPO=$(mktemp -d)
cd "$TMP_REPO"
git init -q
git -c user.email=ci@example.com -c user.name=ci commit --allow-empty -q -m init
# --no-worktree: same rationale as the negative-case test above — this
# test exercises the Claude subprocess spawn path, not worktree setup.
set +e
OUTPUT=$(CLAUDE_BIN_PATH="$CLI_PATH" "$BIN" workflow run archon-assist --no-worktree "hello" 2>&1)
EXIT_CODE=$?
set -e
echo "$OUTPUT"
if echo "$OUTPUT" | grep -qE 'Module not found.*(cli\.js|Users/runner)'; then
echo "::error::Subprocess could not find the executable (resolver regression)"
exit 1
fi
if echo "$OUTPUT" | grep -q "Claude Code not found"; then
echo "::error::Resolver failed even though CLAUDE_BIN_PATH was set to an existing file"
exit 1
fi
# Any of these outcomes are acceptable — they prove the subprocess spawned:
# - auth error ("credit balance", "unauthorized", "authentication")
# - rate-limit / API error
# - successful query (if auth was injected via some other mechanism)
echo "::notice::Claude subprocess spawn path is healthy (exit code: $EXIT_CODE)"
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.binary }}
path: dist/${{ matrix.binary }}
retention-days: 1
release:
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: 1.3.11
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Build web UI
run: bun --filter @archon/web build
- name: Package web dist
run: |
tar czf dist/archon-web.tar.gz -C packages/web/dist .
- name: Generate checksums
run: |
cd dist
sha256sum archon-* archon-web.tar.gz > checksums.txt
cat checksums.txt
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
name: Archon CLI ${{ steps.version.outputs.version }}
draft: false
prerelease: ${{ contains(steps.version.outputs.version, '-') }}
generate_release_notes: true
files: |
dist/archon-*
dist/archon-web.tar.gz
dist/checksums.txt
body: |
## Installation
### Quick Install (Recommended)
**macOS / Linux**
```bash
curl -fsSL https://archon.diy/install | bash
```
**Windows (PowerShell)**
```powershell
irm https://archon.diy/install.ps1 | iex
```
**Homebrew (macOS / Linux)**
```bash
brew install coleam00/archon/archon
```
**Docker**
```bash
docker run --rm -v "$PWD:/workspace" ghcr.io/coleam00/archon:latest workflow list
```
### Manual Installation
**macOS (Apple Silicon)**
```bash
curl -fsSL https://github.com/coleam00/Archon/releases/latest/download/archon-darwin-arm64 -o /usr/local/bin/archon
chmod +x /usr/local/bin/archon
```
**macOS (Intel)**
```bash
curl -fsSL https://github.com/coleam00/Archon/releases/latest/download/archon-darwin-x64 -o /usr/local/bin/archon
chmod +x /usr/local/bin/archon
```
**Linux (x64)**
```bash
curl -fsSL https://github.com/coleam00/Archon/releases/latest/download/archon-linux-x64 -o /usr/local/bin/archon
chmod +x /usr/local/bin/archon
```
**Linux (ARM64)**
```bash
curl -fsSL https://github.com/coleam00/Archon/releases/latest/download/archon-linux-arm64 -o /usr/local/bin/archon
chmod +x /usr/local/bin/archon
```
**Windows (Manual)**
Download `archon-windows-x64.exe` from the assets below, rename to `archon.exe`, and add to your PATH.
### Verify installation
```bash
archon version
```
update-homebrew:
needs: release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: dev
- name: Get version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Wait for release assets
run: sleep 30
- name: Update Homebrew formula
run: bash scripts/update-homebrew.sh ${{ steps.version.outputs.version }}
- name: Commit updated formula
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add homebrew/archon.rb
git diff --cached --quiet || git commit -m "chore: update Homebrew formula for ${{ steps.version.outputs.version }}"
git push origin dev