Skip to content

chore(release): Reset to v0.1.0 #7

chore(release): Reset to v0.1.0

chore(release): Reset to v0.1.0 #7

Workflow file for this run

name: Release
on:
push:
branches:
- main
- alpha
- beta
workflow_dispatch:
inputs:
version:
description: 'Version to release (leave empty for auto)'
required: false
channel:
description: 'Release channel'
required: true
default: 'beta'
type: choice
options:
- alpha
- beta
- release
permissions:
contents: write
pull-requests: write
issues: write
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
channel: ${{ steps.determine.outputs.channel }}
version: ${{ steps.version.outputs.version }}
should_release: ${{ steps.check.outputs.should_release }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Determine release channel
id: determine
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "channel=${{ github.event.inputs.channel }}" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" = "refs/heads/main" ]; then
echo "channel=release" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" = "refs/heads/beta" ]; then
echo "channel=beta" >> $GITHUB_OUTPUT
elif [ "${{ github.ref }}" = "refs/heads/alpha" ]; then
echo "channel=alpha" >> $GITHUB_OUTPUT
else
echo "channel=beta" >> $GITHUB_OUTPUT
fi
- name: Check if should release
id: check
run: |
# Check if last commit is a version bump (skip if so)
if git log -1 --pretty=%B | grep -q "chore(release):"; then
echo "should_release=false" >> $GITHUB_OUTPUT
else
echo "should_release=true" >> $GITHUB_OUTPUT
fi
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install dependencies
run: bun install
- name: Get version
id: version
run: |
CURRENT_VERSION=$(node -p "require('./package.json').version")
CHANNEL="${{ steps.determine.outputs.channel }}"
# Parse semantic version
MAJOR=$(echo $CURRENT_VERSION | cut -d. -f1)
MINOR=$(echo $CURRENT_VERSION | cut -d. -f2)
PATCH=$(echo $CURRENT_VERSION | cut -d. -f3 | cut -d- -f1)
# Determine version bump based on commit messages
if git log --format=%B -n 20 | grep -qi "BREAKING CHANGE\|!:"; then
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
elif git log --format=%B -n 10 | grep -qi "^feat"; then
MINOR=$((MINOR + 1))
PATCH=0
else
PATCH=$((PATCH + 1))
fi
# Manual override
if [ -n "${{ github.event.inputs.version }}" ]; then
NEW_VERSION="${{ github.event.inputs.version }}"
else
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
# Add prerelease tag for non-release channels
if [ "$CHANNEL" = "alpha" ]; then
BUILD_NUM=$(date +%Y%m%d%H%M%S)
NEW_VERSION="${NEW_VERSION}-alpha.${BUILD_NUM}"
elif [ "$CHANNEL" = "beta" ]; then
BUILD_NUM=$(date +%Y%m%d%H%M)
NEW_VERSION="${NEW_VERSION}-beta.${BUILD_NUM}"
fi
fi
echo "version=${NEW_VERSION}" >> $GITHUB_OUTPUT
echo "🎯 Version: ${NEW_VERSION} (${CHANNEL})"
build:
needs: prepare
if: needs.prepare.outputs.should_release == 'true'
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: macos-latest
target: darwin-arm64
artifact: autohand-macos-arm64
- os: macos-latest
target: darwin-x64
artifact: autohand-macos-x64
- os: ubuntu-latest
target: linux-x64
artifact: autohand-linux-x64
- os: ubuntu-latest
target: linux-arm64
artifact: autohand-linux-arm64
- os: windows-latest
target: windows-x64
artifact: autohand-windows-x64.exe
steps:
- uses: actions/checkout@v6
- name: Setup Bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install dependencies
run: bun install
- name: Build TypeScript
run: bun run build
- name: Compile binary
run: |
mkdir -p binaries
bun build ./src/index.ts --compile --target=bun-${{ matrix.target }} --outfile ./binaries/${{ matrix.artifact }}
- name: Verify binary
if: runner.os != 'Windows'
run: |
chmod +x ./binaries/${{ matrix.artifact }}
file ./binaries/${{ matrix.artifact }}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact }}
path: ./binaries/${{ matrix.artifact }}
retention-days: 1
release:
needs: [prepare, build]
if: needs.prepare.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Bun
uses: oven-sh/setup-bun@v1
- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Update version in package.json
run: |
bun --version
VERSION="${{ needs.prepare.outputs.version }}"
echo "Updating to version: $VERSION"
npm version $VERSION --no-git-tag-version --allow-same-version
git add package.json
git commit -m "chore(release): v$VERSION [skip ci]" || echo "No changes to commit"
git push origin ${{ github.ref_name }} || echo "No changes to push"
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Prepare release binaries
run: |
mkdir -p release-binaries
find artifacts -type f -exec cp {} release-binaries/ \;
ls -lh release-binaries/
- name: Generate changelog
id: changelog
uses: actions/github-script@v7
env:
RELEASE_VERSION: ${{ needs.prepare.outputs.version }}
with:
script: |
const { execSync } = require('child_process');
const version = process.env.RELEASE_VERSION;
// Get commits since last tag
let commits;
try {
const lastTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
commits = execSync(`git log ${lastTag}..HEAD --pretty=format:"%h %s"`, { encoding: 'utf8' });
} catch {
commits = execSync('git log --pretty=format:"%h %s" -n 20', { encoding: 'utf8' });
}
const lines = commits.split('\n').filter(line => line.trim());
// Categorize commits
const features = [];
const fixes = [];
const chores = [];
const breaking = [];
for (const line of lines) {
const [hash, ...msgParts] = line.split(' ');
const msg = msgParts.join(' ');
if (msg.includes('BREAKING CHANGE') || msg.includes('!:')) {
breaking.push(`- ${msg} (${hash})`);
} else if (msg.startsWith('feat')) {
features.push(`- ${msg.replace('feat:', '').replace('feat(', '(').trim()} (${hash})`);
} else if (msg.startsWith('fix')) {
fixes.push(`- ${msg.replace('fix:', '').replace('fix(', '(').trim()} (${hash})`);
} else if (!msg.startsWith('chore(release)')) {
chores.push(`- ${msg} (${hash})`);
}
}
// Build changelog
let changelog = '## 🚀 What\'s Changed\n\n';
if (breaking.length > 0) {
changelog += '### ⚠️ BREAKING CHANGES\n' + breaking.join('\n') + '\n\n';
}
if (features.length > 0) {
changelog += '### ✨ Features\n' + features.join('\n') + '\n\n';
}
if (fixes.length > 0) {
changelog += '### 🐛 Bug Fixes\n' + fixes.join('\n') + '\n\n';
}
if (chores.length > 0 && chores.length < 10) {
changelog += '### 🔧 Maintenance\n' + chores.join('\n') + '\n\n';
}
// Add installation instructions
const cb = '`' + '`' + '`';
changelog += '\n## 📦 Installation\n\n';
changelog += '### Recommended: Install Script\n';
changelog += cb + 'bash\ncurl -fsSL https://autohand.ai/install.sh | sh\n' + cb + '\n\n';
changelog += '### Or install a specific version\n';
changelog += cb + 'bash\nAUTOHAND_VERSION=' + version + ' curl -fsSL https://autohand.ai/install.sh | sh\n' + cb + '\n\n';
changelog += '### Via npm/bun\n';
changelog += cb + 'bash\nnpm install -g autohand-cli\n# or\nbun install -g autohand-cli\n' + cb + '\n\n';
changelog += '### Manual Download\n';
changelog += 'Download the appropriate binary for your system from the assets below.\n\n';
changelog += '## 📋 Available Binaries\n';
changelog += '| Platform | Architecture | Binary |\n';
changelog += '|----------|--------------|--------|\n';
changelog += '| macOS | Apple Silicon (M1/M2/M3/M4) | `autohand-macos-arm64` |\n';
changelog += '| macOS | Intel | `autohand-macos-x64` |\n';
changelog += '| Linux | x64 | `autohand-linux-x64` |\n';
changelog += '| Linux | ARM64 | `autohand-linux-arm64` |\n';
changelog += '| Windows | x64 | `autohand-windows-x64.exe` |\n';
core.setOutput('changelog', changelog);
return changelog;
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.prepare.outputs.version }}
name: ${{ needs.prepare.outputs.channel == 'release' && format('Release v{0}', needs.prepare.outputs.version) || format('{0} v{1}', needs.prepare.outputs.channel, needs.prepare.outputs.version) }}
body: ${{ steps.changelog.outputs.changelog }}
files: |
release-binaries/*
install.sh
draft: false
prerelease: ${{ needs.prepare.outputs.channel != 'release' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build JS dist for npm
if: needs.prepare.outputs.channel == 'release'
run: |
bun install
bun run build
ls -lh dist/
- name: Publish to npm (release only)
if: needs.prepare.outputs.channel == 'release'
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "$NPM_TOKEN" ]; then
echo "⚠️ NPM_TOKEN not set, skipping npm publish"
exit 0
fi
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > ~/.npmrc
npm publish --access public