From 884ca48dc36a025bfebeac9a138036a697118293 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 30 Jun 2025 07:48:14 +0100 Subject: [PATCH] docs: add release process improvements and quick reference guide - Document lessons learned from v1.0.0-beta.5 release - Add quick reference guide for common release tasks - Include troubleshooting for timeout and appcast issues - Clarify DMG notarization behavior (DMGs aren't notarized, only apps inside) --- mac/docs/RELEASE-IMPROVEMENTS-2024-06.md | 276 +++++++++++++++++++++++ mac/docs/RELEASE-LESSONS.md | 26 +++ mac/docs/RELEASE-QUICKREF.md | 159 +++++++++++++ 3 files changed, 461 insertions(+) create mode 100644 mac/docs/RELEASE-IMPROVEMENTS-2024-06.md create mode 100644 mac/docs/RELEASE-QUICKREF.md diff --git a/mac/docs/RELEASE-IMPROVEMENTS-2024-06.md b/mac/docs/RELEASE-IMPROVEMENTS-2024-06.md new file mode 100644 index 00000000..677e7614 --- /dev/null +++ b/mac/docs/RELEASE-IMPROVEMENTS-2024-06.md @@ -0,0 +1,276 @@ +# Release Process Improvements - June 2024 + +Based on the v1.0.0-beta.5 release experience, here are recommended improvements to the release process and tooling. + +## 🚨 Issues Encountered + +### 1. Command Timeouts +**Problem**: The release script timed out multiple times during execution, especially during notarization. +- Claude's 2-minute command timeout interrupted long-running operations +- Notarization can take 5-10 minutes depending on Apple's servers + +**Solution**: +- Add progress indicators and intermediate status updates +- Break down the release script into smaller, resumable steps +- Add a `--resume` flag to continue from the last successful step + +### 2. Notarization Delays +**Problem**: Notarization took longer than expected and caused script interruption. + +**Solution**: +- Add timeout handling with proper cleanup +- Implement async notarization with status polling +- Add estimated time remaining based on historical data + +### 3. Manual Recovery Required +**Problem**: After script failure, manual steps were needed: +- Creating DMG manually +- Creating GitHub release manually +- Updating appcast manually + +**Solution**: Implement idempotent operations and recovery: +```bash +# Check if DMG already exists +if [ -f "build/VibeTunnel-$VERSION.dmg" ]; then + echo "DMG already exists, skipping creation" +else + ./scripts/create-dmg.sh +fi + +# Check if GitHub release exists +if gh release view "v$VERSION" &>/dev/null; then + echo "Release already exists, skipping" +else + gh release create ... +fi +``` + +### 4. Generate Appcast Script Failure +**Problem**: `generate-appcast.sh` failed with GitHub API error despite valid authentication. + +**Solution**: Add better error handling and fallback options: +- Retry logic for transient API failures +- Manual appcast generation mode +- Better error messages indicating the actual problem + +## 📋 Recommended Script Improvements + +### 1. Release Script Enhancements + +```bash +# Add to release.sh + +# State file to track progress +STATE_FILE=".release-state" + +# Save state after each major step +save_state() { + echo "$1" > "$STATE_FILE" +} + +# Resume from last state +resume_from_state() { + if [ -f "$STATE_FILE" ]; then + LAST_STATE=$(cat "$STATE_FILE") + echo "Resuming from: $LAST_STATE" + fi +} + +# Add --resume flag handling +if [[ "$1" == "--resume" ]]; then + resume_from_state + shift +fi +``` + +### 2. Parallel Operations +Where possible, run independent operations in parallel: +```bash +# Run signing and changelog generation in parallel +{ + sign_app & + PID1=$! + + generate_changelog & + PID2=$! + + wait $PID1 $PID2 +} +``` + +### 3. Better Progress Reporting +```bash +# Add progress function +progress() { + local step=$1 + local total=$2 + local message=$3 + echo "[${step}/${total}] ${message}" +} + +# Use throughout script +progress 1 8 "Running pre-flight checks..." +progress 2 8 "Building application..." +``` + +## 📄 Documentation Improvements + +### 1. Add Troubleshooting Section +Create a new section in RELEASE.md: + +```markdown +## 🔧 Troubleshooting Common Issues + +### Script Timeouts +If the release script times out: +1. Check `.release-state` for the last successful step +2. Run `./scripts/release.sh --resume` to continue +3. Or manually complete remaining steps (see Manual Recovery below) + +### Manual Recovery Steps +If automated release fails after notarization: + +1. **Create DMG** (if missing): + ```bash + ./scripts/create-dmg.sh build/Build/Products/Release/VibeTunnel.app + ``` + +2. **Create GitHub Release**: + ```bash + gh release create "v$VERSION" \ + --title "VibeTunnel $VERSION" \ + --notes-file RELEASE_NOTES.md \ + --prerelease \ + build/VibeTunnel-*.dmg \ + build/VibeTunnel-*.zip + ``` + +3. **Sign DMG for Sparkle**: + ```bash + export SPARKLE_ACCOUNT="VibeTunnel" + sign_update build/VibeTunnel-$VERSION.dmg --account VibeTunnel + ``` + +4. **Update Appcast Manually**: + - Add entry to appcast-prerelease.xml with signature from step 3 + - Commit and push: `git add appcast*.xml && git commit -m "Update appcast" && git push` +``` + +### 2. Add Pre-Release Checklist Updates +```markdown +### Environment Setup +- [ ] Ensure stable internet connection (notarization requires consistent connectivity) +- [ ] Check Apple Developer status page for any service issues +- [ ] Have at least 30 minutes available (full release takes 15-20 minutes) +- [ ] Close other resource-intensive applications +``` + +## 🛠️ New Helper Scripts + +### 1. Release Status Script +Create `scripts/check-release-status.sh`: +```bash +#!/bin/bash +VERSION=$1 + +echo "Checking release status for v$VERSION..." + +# Check local artifacts +echo -n "✓ Local DMG: " +[ -f "build/VibeTunnel-$VERSION.dmg" ] && echo "EXISTS" || echo "MISSING" + +echo -n "✓ Local ZIP: " +[ -f "build/VibeTunnel-$VERSION.zip" ] && echo "EXISTS" || echo "MISSING" + +# Check GitHub +echo -n "✓ GitHub Release: " +gh release view "v$VERSION" &>/dev/null && echo "EXISTS" || echo "MISSING" + +# Check appcast +echo -n "✓ Appcast Entry: " +grep -q "$VERSION" ../appcast-prerelease.xml && echo "EXISTS" || echo "MISSING" +``` + +### 2. Quick Fix Script +Create `scripts/fix-incomplete-release.sh`: +```bash +#!/bin/bash +# Completes a partially finished release + +VERSION=$(grep MARKETING_VERSION VibeTunnel/version.xcconfig | cut -d' ' -f3) +BUILD=$(grep CURRENT_PROJECT_VERSION VibeTunnel/version.xcconfig | cut -d' ' -f3) + +echo "Fixing incomplete release for $VERSION (build $BUILD)..." + +# Check what's missing and fix +./scripts/check-release-status.sh "$VERSION" + +# ... implement fixes based on status +``` + +## 🔍 Monitoring Improvements + +### 1. Add Logging +- Create detailed logs for each release in `logs/release-$VERSION.log` +- Include timestamps for each operation +- Log all external command outputs + +### 2. Add Metrics +Track and report: +- Total release time +- Time per step (build, sign, notarize, upload) +- Success/failure rates +- Common failure points + +## 🎯 Quick Wins + +1. **Increase timeouts**: Set notarization timeout to 30 minutes +2. **Add retry logic**: Retry failed operations up to 3 times +3. **Better error messages**: Include specific recovery steps in error output +4. **State persistence**: Save progress to allow resumption +5. **Validation before each step**: Check prerequisites aren't already done + +## 📝 Updated Release Workflow + +Based on lessons learned, here's the recommended workflow: + +1. **Pre-release**: + ```bash + ./scripts/preflight-check.sh --comprehensive + ``` + +2. **Release with monitoring**: + ```bash + # Run in a screen/tmux session to prevent disconnection + screen -S release + ./scripts/release.sh beta 5 --verbose --log + ``` + +3. **If interrupted**: + ```bash + ./scripts/check-release-status.sh 1.0.0-beta.5 + ./scripts/release.sh --resume + ``` + +4. **Verify**: + ```bash + ./scripts/verify-release.sh 1.0.0-beta.5 + ``` + +## 🚀 Long-term Improvements + +1. **CI/CD Integration**: Move releases to GitHub Actions for reliability +2. **Release Dashboard**: Web UI showing release progress and status +3. **Automated Testing**: Test Sparkle updates in CI before publishing +4. **Rollback Capability**: Script to quickly revert a bad release +5. **Release Templates**: Pre-configured release notes and changelog formats + +## Summary + +The v1.0.0-beta.5 release was ultimately successful, but the process revealed several areas for improvement. The main issues were: +- Command timeouts during long operations +- Lack of resumability after failures +- Missing progress indicators +- No automated recovery options + +Implementing the improvements above will make future releases more reliable and less stressful, especially when using tools with timeout constraints like Claude. \ No newline at end of file diff --git a/mac/docs/RELEASE-LESSONS.md b/mac/docs/RELEASE-LESSONS.md index 05057e94..d0b5174a 100644 --- a/mac/docs/RELEASE-LESSONS.md +++ b/mac/docs/RELEASE-LESSONS.md @@ -211,6 +211,32 @@ export SPARKLE_ACCOUNT="VibeTunnel" 4. **Test the full update flow** before announcing the release 5. **Keep credentials secure** but easily accessible for scripts 6. **Document everything** - future you will thank present you +7. **Plan for long-running operations** - notarization can take 10+ minutes +8. **Implement resumable workflows** - scripts should handle interruptions gracefully +9. **DMG signing is separate from notarization** - DMGs themselves aren't notarized, only the app inside + +### Additional Lessons from v1.0.0-beta.5 Release + +#### DMG Notarization Confusion +**Issue**: The DMG shows as "Unnotarized Developer ID" when checked with spctl, but this is normal. +**Explanation**: +- DMGs are not notarized themselves - only the app inside is notarized +- The app inside the DMG shows correctly as "Notarized Developer ID" +- This is expected behavior and not an error + +#### Release Script Timeout Handling +**Issue**: Release script timed out during notarization (took ~5 minutes). +**Solution**: +- Run release scripts in a terminal without timeout constraints +- Consider using `screen` or `tmux` for long operations +- Add progress indicators to show the script is still running + +#### Appcast Generation Failures +**Issue**: `generate-appcast.sh` failed with GitHub API errors despite valid auth. +**Workaround**: +- Manually create appcast entries when automation fails +- Always verify the Sparkle signature with `sign_update --account VibeTunnel` +- Keep a template of appcast entries for quick manual updates ## References diff --git a/mac/docs/RELEASE-QUICKREF.md b/mac/docs/RELEASE-QUICKREF.md new file mode 100644 index 00000000..b59d89aa --- /dev/null +++ b/mac/docs/RELEASE-QUICKREF.md @@ -0,0 +1,159 @@ +# VibeTunnel Release Quick Reference + +## 🚀 Quick Release Commands + +### Standard Release Flow +```bash +# 1. Update versions +vim VibeTunnel/version.xcconfig # Set MARKETING_VERSION and increment CURRENT_PROJECT_VERSION +vim ../web/package.json # Match version with MARKETING_VERSION + +# 2. Update changelog +vim CHANGELOG.md # Add entry for new version + +# 3. Run release +export SPARKLE_ACCOUNT="VibeTunnel" +./scripts/release.sh beta 5 # For beta.5 +./scripts/release.sh stable # For stable release +``` + +### If Release Script Fails + +#### After Notarization Success +```bash +# 1. Create DMG (if missing) +./scripts/create-dmg.sh build/Build/Products/Release/VibeTunnel.app + +# 2. Create GitHub release +gh release create "v1.0.0-beta.5" \ + --title "VibeTunnel 1.0.0-beta.5" \ + --prerelease \ + --notes-file RELEASE_NOTES.md \ + build/VibeTunnel-*.dmg \ + build/VibeTunnel-*.zip + +# 3. Get Sparkle signature +sign_update build/VibeTunnel-*.dmg --account VibeTunnel + +# 4. Update appcast manually (add to appcast-prerelease.xml) +# 5. Commit and push +git add ../appcast-prerelease.xml +git commit -m "Update appcast for v1.0.0-beta.5" +git push +``` + +## 📋 Pre-Release Checklist + +- [ ] `grep MARKETING_VERSION VibeTunnel/version.xcconfig` - Check version +- [ ] `grep CURRENT_PROJECT_VERSION VibeTunnel/version.xcconfig` - Check build number +- [ ] `grep "version" ../web/package.json` - Verify web version matches +- [ ] `grep "## \[1.0.0-beta.5\]" CHANGELOG.md` - Changelog entry exists +- [ ] `git status` - Clean working directory +- [ ] `gh auth status` - GitHub CLI authenticated +- [ ] Apple notarization credentials set in environment + +## 🔍 Verification Commands + +```bash +# Check release artifacts +ls -la build/VibeTunnel-*.dmg +ls -la build/VibeTunnel-*.zip + +# Check GitHub release +gh release view v1.0.0-beta.5 + +# Verify Sparkle signature +curl -L -o test.dmg [github-dmg-url] +sign_update test.dmg --account VibeTunnel + +# Check appcast +grep "1.0.0-beta.5" ../appcast-prerelease.xml + +# Verify app in DMG +hdiutil attach test.dmg +spctl -a -vv /Volumes/VibeTunnel/VibeTunnel.app +hdiutil detach /Volumes/VibeTunnel +``` + +## ⚠️ Common Issues + +### "Uncommitted changes detected" +```bash +git status --porcelain # Check what's changed +git stash # Temporarily store changes +# Run release +git stash pop # Restore changes +``` + +### Notarization Taking Too Long +- Normal: 2-10 minutes +- If >15 minutes, check Apple System Status +- Can manually check: `xcrun notarytool history` + +### DMG Shows "Unnotarized" +- This is NORMAL - DMGs aren't notarized +- Check the app inside: it should show "Notarized Developer ID" + +### Generate Appcast Fails +- Manually add entry to appcast-prerelease.xml +- Use signature from: `sign_update [dmg] --account VibeTunnel` +- Follow existing entry format + +## 📝 Appcast Entry Template + +```xml + + VibeTunnel VERSION + https://github.com/amantus-ai/vibetunnel/releases/download/vVERSION/VibeTunnel-VERSION.dmg + BUILD_NUMBER + VERSION + VibeTunnel VERSION +

Pre-release version

+ + ]]>
+ DATE + +
+``` + +## 🎯 Release Success Criteria + +- [ ] GitHub release created with both DMG and ZIP +- [ ] DMG downloads and mounts correctly +- [ ] App inside DMG shows as notarized +- [ ] Appcast updated and pushed +- [ ] Sparkle signature in appcast matches DMG +- [ ] Version and build numbers correct everywhere +- [ ] Previous version can update via Sparkle + +## 🚨 Emergency Fixes + +### Wrong Sparkle Signature +```bash +# 1. Get correct signature +sign_update [dmg-url] --account VibeTunnel + +# 2. Update appcast-prerelease.xml with correct signature +# 3. Commit and push immediately +``` + +### Missing from Appcast +```bash +# Users won't see update until appcast is fixed +# Add entry manually following template above +# Test with: curl https://raw.githubusercontent.com/amantus-ai/vibetunnel/main/appcast-prerelease.xml +``` + +### Build Number Conflict +```bash +# If Sparkle complains about duplicate build number +# Increment build number in version.xcconfig +# Create new release with higher build number +# Old release will be ignored by Sparkle +``` \ No newline at end of file