Add full release automation script
Amp-Thread-ID: https://ampcode.com/threads/T-789d9ba6-2aea-4ee9-b4dc-ce73e8f496f4 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
20
RELEASING.md
20
RELEASING.md
@@ -2,7 +2,25 @@
|
|||||||
|
|
||||||
Quick guide for releasing a new version of beads.
|
Quick guide for releasing a new version of beads.
|
||||||
|
|
||||||
## Pre-Release Checklist
|
## 🚀 The Easy Way (Recommended)
|
||||||
|
|
||||||
|
Use the fully automated release script:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/release.sh 0.9.3
|
||||||
|
```
|
||||||
|
|
||||||
|
This does **everything**: version bump, tests, git tag, Homebrew update, and local installation.
|
||||||
|
|
||||||
|
See [scripts/README.md](scripts/README.md#releasesh--the-easy-button) for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 The Manual Way
|
||||||
|
|
||||||
|
If you prefer step-by-step control:
|
||||||
|
|
||||||
|
### Pre-Release Checklist
|
||||||
|
|
||||||
1. **Kill all running daemons (CRITICAL)**:
|
1. **Kill all running daemons (CRITICAL)**:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -2,6 +2,71 @@
|
|||||||
|
|
||||||
Utility scripts for maintaining the beads project.
|
Utility scripts for maintaining the beads project.
|
||||||
|
|
||||||
|
## release.sh (⭐ The Easy Button)
|
||||||
|
|
||||||
|
**One-command release** from version bump to local installation.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full release (does everything)
|
||||||
|
./scripts/release.sh 0.9.3
|
||||||
|
|
||||||
|
# Preview what would happen
|
||||||
|
./scripts/release.sh 0.9.3 --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### What It Does
|
||||||
|
|
||||||
|
This master script automates the **entire release process**:
|
||||||
|
|
||||||
|
1. ✅ Kills running daemons (avoids version conflicts)
|
||||||
|
2. ✅ Runs tests and linting
|
||||||
|
3. ✅ Bumps version in all files
|
||||||
|
4. ✅ Commits and pushes version bump
|
||||||
|
5. ✅ Creates and pushes git tag
|
||||||
|
6. ✅ Updates Homebrew formula
|
||||||
|
7. ✅ Upgrades local brew installation
|
||||||
|
8. ✅ Verifies everything works
|
||||||
|
|
||||||
|
**After this script completes, your system is running the new version!**
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Release version 0.9.3
|
||||||
|
./scripts/release.sh 0.9.3
|
||||||
|
|
||||||
|
# Preview a release (no changes made)
|
||||||
|
./scripts/release.sh 1.0.0 --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Clean git working directory
|
||||||
|
- All changes committed
|
||||||
|
- golangci-lint installed
|
||||||
|
- Homebrew installed (for local upgrade)
|
||||||
|
- Push access to steveyegge/beads and steveyegge/homebrew-beads
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
The script provides colorful, step-by-step progress output:
|
||||||
|
- 🟨 Yellow: Current step
|
||||||
|
- 🟩 Green: Step completed
|
||||||
|
- 🟥 Red: Errors
|
||||||
|
- 🟦 Blue: Section headers
|
||||||
|
|
||||||
|
### What Happens Next
|
||||||
|
|
||||||
|
After the script finishes:
|
||||||
|
- GitHub Actions builds binaries for all platforms (~5 minutes)
|
||||||
|
- PyPI package is published automatically
|
||||||
|
- Users can `brew upgrade bd` to get the new version
|
||||||
|
- GitHub Release is created with binaries and changelog
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## bump-version.sh
|
## bump-version.sh
|
||||||
|
|
||||||
Bumps the version number across all beads components in a single command.
|
Bumps the version number across all beads components in a single command.
|
||||||
|
|||||||
222
scripts/release.sh
Executable file
222
scripts/release.sh
Executable file
@@ -0,0 +1,222 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: $0 <version> [--dry-run]
|
||||||
|
|
||||||
|
Fully automate a beads release from version bump to local installation.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
version Version number (e.g., 0.9.3)
|
||||||
|
--dry-run Show what would happen without making changes
|
||||||
|
|
||||||
|
This script performs the complete release workflow:
|
||||||
|
1. Kill running daemons
|
||||||
|
2. Run tests and linting
|
||||||
|
3. Bump version in all files
|
||||||
|
4. Commit and push version bump
|
||||||
|
5. Create and push git tag
|
||||||
|
6. Update Homebrew formula
|
||||||
|
7. Upgrade local brew installation
|
||||||
|
8. Verify everything is working
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$0 0.9.3 # Full release
|
||||||
|
$0 0.9.3 --dry-run # Preview what would happen
|
||||||
|
|
||||||
|
After this script completes, your system will be running the new version!
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
DRY_RUN=false
|
||||||
|
VERSION=""
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
VERSION="$arg"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Strip 'v' prefix if present
|
||||||
|
VERSION="${VERSION#v}"
|
||||||
|
|
||||||
|
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BLUE}║${NC} ${GREEN}Beads Full Release Automation${NC} ${BLUE}║${NC}"
|
||||||
|
echo -e "${BLUE}║${NC} Version: ${YELLOW}v${VERSION}${NC} ${BLUE}║${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo -e "${BLUE}║${NC} ${YELLOW}Mode: DRY RUN (no changes will be made)${NC} ${BLUE}║${NC}"
|
||||||
|
fi
|
||||||
|
echo -e "${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Step 1: Kill daemons
|
||||||
|
echo -e "${YELLOW}Step 1/8: Killing running daemons...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: pkill -f 'bd.*daemon'"
|
||||||
|
else
|
||||||
|
pkill -f "bd.*daemon" 2>/dev/null || true
|
||||||
|
sleep 1
|
||||||
|
if pgrep -lf "bd.*daemon" > /dev/null 2>&1; then
|
||||||
|
echo -e "${RED}✗ Daemons still running${NC}"
|
||||||
|
pgrep -lf "bd.*daemon"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ All daemons stopped${NC}\n"
|
||||||
|
|
||||||
|
# Step 2: Run tests
|
||||||
|
echo -e "${YELLOW}Step 2/8: Running tests and linting...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: TMPDIR=/tmp go test ./..."
|
||||||
|
echo "[DRY RUN] Would run: golangci-lint run ./..."
|
||||||
|
else
|
||||||
|
if ! TMPDIR=/tmp go test ./...; then
|
||||||
|
echo -e "${RED}✗ Tests failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! golangci-lint run ./...; then
|
||||||
|
echo -e "${YELLOW}⚠ Linting warnings (see LINTING.md for baseline)${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Tests passed${NC}\n"
|
||||||
|
|
||||||
|
# Step 3: Bump version
|
||||||
|
echo -e "${YELLOW}Step 3/8: Bumping version to ${VERSION}...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: $SCRIPT_DIR/bump-version.sh $VERSION --commit"
|
||||||
|
$SCRIPT_DIR/bump-version.sh "$VERSION" 2>/dev/null || true
|
||||||
|
else
|
||||||
|
if ! $SCRIPT_DIR/bump-version.sh "$VERSION" --commit; then
|
||||||
|
echo -e "${RED}✗ Version bump failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Version bumped and committed${NC}\n"
|
||||||
|
|
||||||
|
# Step 4: Rebuild local binary
|
||||||
|
echo -e "${YELLOW}Step 4/8: Rebuilding local binary...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: go build -o bd ./cmd/bd"
|
||||||
|
else
|
||||||
|
if ! go build -o bd ./cmd/bd; then
|
||||||
|
echo -e "${RED}✗ Build failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
BUILT_VERSION=$(./bd version 2>/dev/null | head -1)
|
||||||
|
echo "Built version: $BUILT_VERSION"
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Binary rebuilt${NC}\n"
|
||||||
|
|
||||||
|
# Step 5: Push version bump
|
||||||
|
echo -e "${YELLOW}Step 5/8: Pushing version bump to GitHub...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: git push origin main"
|
||||||
|
else
|
||||||
|
if ! git push origin main; then
|
||||||
|
echo -e "${RED}✗ Push failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Version bump pushed${NC}\n"
|
||||||
|
|
||||||
|
# Step 6: Create and push tag
|
||||||
|
echo -e "${YELLOW}Step 6/8: Creating and pushing git tag v${VERSION}...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: git tag v${VERSION}"
|
||||||
|
echo "[DRY RUN] Would run: git push origin v${VERSION}"
|
||||||
|
else
|
||||||
|
if git rev-parse "v${VERSION}" >/dev/null 2>&1; then
|
||||||
|
echo -e "${YELLOW}⚠ Tag v${VERSION} already exists, skipping tag creation${NC}"
|
||||||
|
else
|
||||||
|
git tag "v${VERSION}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! git push origin "v${VERSION}"; then
|
||||||
|
echo -e "${RED}✗ Tag push failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Tag v${VERSION} pushed${NC}\n"
|
||||||
|
|
||||||
|
# Wait for GitHub to generate tarball
|
||||||
|
if [ "$DRY_RUN" = false ]; then
|
||||||
|
echo -e "${YELLOW}Waiting 10 seconds for GitHub to generate release tarball...${NC}"
|
||||||
|
sleep 10
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 7: Update Homebrew formula
|
||||||
|
echo -e "${YELLOW}Step 7/8: Updating Homebrew formula...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: $SCRIPT_DIR/update-homebrew.sh ${VERSION}"
|
||||||
|
else
|
||||||
|
if ! $SCRIPT_DIR/update-homebrew.sh "$VERSION"; then
|
||||||
|
echo -e "${RED}✗ Homebrew update failed${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Homebrew formula updated${NC}\n"
|
||||||
|
|
||||||
|
# Step 8: Upgrade local installation
|
||||||
|
echo -e "${YELLOW}Step 8/8: Upgrading local Homebrew installation...${NC}"
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo "[DRY RUN] Would run: brew update"
|
||||||
|
echo "[DRY RUN] Would run: brew upgrade bd"
|
||||||
|
else
|
||||||
|
brew update
|
||||||
|
|
||||||
|
# Check if bd is installed via brew
|
||||||
|
if brew list bd >/dev/null 2>&1; then
|
||||||
|
brew upgrade bd || brew reinstall bd
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}⚠ bd not installed via Homebrew, skipping upgrade${NC}"
|
||||||
|
echo "To install: brew install steveyegge/beads/bd"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo -e "${GREEN}✓ Local installation upgraded${NC}\n"
|
||||||
|
|
||||||
|
# Final verification
|
||||||
|
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
|
echo -e "${GREEN}✓ Release Complete!${NC}\n"
|
||||||
|
|
||||||
|
if [ "$DRY_RUN" = false ]; then
|
||||||
|
echo "Verification:"
|
||||||
|
echo " Installed version: $(bd version 2>/dev/null | head -1 || echo 'Error getting version')"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " • GitHub Actions is building release binaries"
|
||||||
|
echo " • Monitor: https://github.com/steveyegge/beads/actions"
|
||||||
|
echo " • PyPI publish happens automatically"
|
||||||
|
echo " • Update CHANGELOG.md if not done yet"
|
||||||
|
echo ""
|
||||||
|
echo "Your system is now running v${VERSION}!"
|
||||||
|
else
|
||||||
|
echo "[DRY RUN] No changes were made."
|
||||||
|
echo "Run without --dry-run to perform the actual release."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}═══════════════════════════════════════════════════════════════${NC}"
|
||||||
Reference in New Issue
Block a user