mirror of
https://github.com/samsonjs/vibetunnel.git
synced 2026-06-28 05:29:29 +00:00
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)
This commit is contained in:
parent
6be9578db7
commit
884ca48dc3
3 changed files with 461 additions and 0 deletions
276
mac/docs/RELEASE-IMPROVEMENTS-2024-06.md
Normal file
276
mac/docs/RELEASE-IMPROVEMENTS-2024-06.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
159
mac/docs/RELEASE-QUICKREF.md
Normal file
159
mac/docs/RELEASE-QUICKREF.md
Normal file
|
|
@ -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
|
||||
<item>
|
||||
<title>VibeTunnel VERSION</title>
|
||||
<link>https://github.com/amantus-ai/vibetunnel/releases/download/vVERSION/VibeTunnel-VERSION.dmg</link>
|
||||
<sparkle:version>BUILD_NUMBER</sparkle:version>
|
||||
<sparkle:shortVersionString>VERSION</sparkle:shortVersionString>
|
||||
<description><![CDATA[
|
||||
<h2>VibeTunnel VERSION</h2>
|
||||
<p><strong>Pre-release version</strong></p>
|
||||
<!-- Copy from CHANGELOG.md -->
|
||||
]]></description>
|
||||
<pubDate>DATE</pubDate>
|
||||
<enclosure url="https://github.com/amantus-ai/vibetunnel/releases/download/vVERSION/VibeTunnel-VERSION.dmg"
|
||||
sparkle:version="BUILD_NUMBER"
|
||||
sparkle:shortVersionString="VERSION"
|
||||
length="SIZE_IN_BYTES"
|
||||
type="application/x-apple-diskimage"
|
||||
sparkle:edSignature="SIGNATURE_FROM_SIGN_UPDATE"/>
|
||||
</item>
|
||||
```
|
||||
|
||||
## 🎯 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
|
||||
```
|
||||
Loading…
Reference in a new issue