Simple App to help @jaspermayone make it through COMP1050 with a professor who won't use version control.

Add local release script

+214 -21
+15 -16
CLAUDE.md
··· 40 40 cp -r build/Release/ZipMerge.app /Applications/ 41 41 ``` 42 42 43 - ### Automated Release Pipeline 43 + ### Release Process 44 44 45 - **See RELEASING.md for complete setup instructions.** 45 + **Use the local release script for simplicity:** 46 46 47 - The project uses GitHub Actions for automated releases. When you push a version tag, it automatically: 47 + ```bash 48 + ./release.sh v1.0.0 49 + ``` 50 + 51 + This automated script handles everything: 48 52 1. Builds with Developer ID signing 49 53 2. Notarizes with Apple 50 54 3. Creates GitHub release with signed .zip 51 - 4. Outputs SHA256 for Homebrew cask 55 + 4. Calculates SHA256 hash 56 + 5. Updates Homebrew cask automatically 57 + 6. Commits and pushes cask update 52 58 53 - **Quick release process:** 54 - ```bash 55 - git tag v1.0.0 56 - git push origin v1.0.0 57 - ``` 59 + **Prerequisites:** 60 + - `gh` CLI installed and authenticated 61 + - Developer ID Application certificate in Keychain 62 + - Apple ID app-specific password (prompted during script) 58 63 59 - Then update the SHA256 in `/Users/jsp/dev/projects/homebrew-tap/Casks/zipmerge.rb` from the release notes. 60 - 61 - **Required GitHub Secrets** (one-time setup - see RELEASING.md): 62 - - `CERTIFICATE_BASE64` - Developer ID certificate 63 - - `CERTIFICATE_PASSWORD` - Certificate password 64 - - `APPLE_ID` - Apple ID email 65 - - `APPLE_ID_PASSWORD` - App-specific password for notarization 64 + The script is fully automated and requires no manual steps. See RELEASING.md for details. 66 65 67 66 ### Distributing via Homebrew 68 67
+23 -5
RELEASING.md
··· 1 1 # Release Process 2 2 3 - This document describes the automated release pipeline for ZipMerge. 3 + This document describes how to release ZipMerge. 4 4 5 - ## Automated Release Pipeline 5 + ## Local Release Script (Recommended) 6 6 7 - Releases are automated via GitHub Actions. When you push a version tag, the workflow will: 7 + The easiest way to create a release is using the local `release.sh` script: 8 8 9 + ```bash 10 + ./release.sh v1.0.0 11 + ``` 12 + 13 + This script will: 9 14 1. Build the app with Developer ID signing 10 15 2. Notarize the app with Apple 11 16 3. Create a GitHub release with the signed .zip 12 - 4. Output the SHA256 hash for the Homebrew cask 17 + 4. Calculate the SHA256 hash 18 + 5. Automatically update the Homebrew cask 19 + 6. Commit and push the cask update 13 20 14 - ## Required GitHub Secrets 21 + **Prerequisites:** 22 + - `gh` CLI installed (`brew install gh`) and authenticated 23 + - Developer ID Application certificate in Keychain 24 + - Apple ID app-specific password (create at https://appleid.apple.com/account/manage) 25 + 26 + The script will prompt for your Apple ID and app-specific password. 27 + 28 + ## Alternative: GitHub Actions (Optional) 29 + 30 + If you prefer CI/CD, there's also a GitHub Actions workflow. However, it requires exporting your signing certificate. 31 + 32 + ## Required GitHub Secrets (GitHub Actions only) 15 33 16 34 Before creating your first release, set up these secrets in GitHub repository settings (Settings → Secrets and variables → Actions): 17 35
+176
release.sh
··· 1 + #!/bin/bash 2 + set -e 3 + 4 + # ZipMerge Local Release Script 5 + # This script builds, signs, notarizes, and releases ZipMerge 6 + 7 + # Colors for output 8 + RED='\033[0;31m' 9 + GREEN='\033[0;32m' 10 + YELLOW='\033[1;33m' 11 + NC='\033[0m' # No Color 12 + 13 + # Configuration 14 + HOMEBREW_TAP_PATH="/Users/jsp/dev/projects/homebrew-tap" 15 + APPLE_ID="${APPLE_ID:-}" # Set via environment variable or it will prompt 16 + TEAM_ID="M67B42LX8D" 17 + 18 + echo -e "${GREEN}🚀 ZipMerge Release Script${NC}" 19 + echo "" 20 + 21 + # Check for version argument 22 + if [ -z "$1" ]; then 23 + echo -e "${RED}Error: Version number required${NC}" 24 + echo "Usage: ./release.sh v1.0.0" 25 + exit 1 26 + fi 27 + 28 + VERSION="$1" 29 + echo -e "Release version: ${YELLOW}${VERSION}${NC}" 30 + echo "" 31 + 32 + # Check if gh CLI is installed 33 + if ! command -v gh &> /dev/null; then 34 + echo -e "${RED}Error: gh CLI not found. Install with: brew install gh${NC}" 35 + exit 1 36 + fi 37 + 38 + # Check if logged in to gh 39 + if ! gh auth status &> /dev/null; then 40 + echo -e "${YELLOW}Please login to GitHub CLI:${NC}" 41 + gh auth login 42 + fi 43 + 44 + # Prompt for Apple ID if not set 45 + if [ -z "$APPLE_ID" ]; then 46 + echo -e "${YELLOW}Enter your Apple ID email:${NC}" 47 + read APPLE_ID 48 + fi 49 + 50 + # Prompt for app-specific password 51 + echo -e "${YELLOW}Enter your Apple ID app-specific password:${NC}" 52 + echo "(Create one at: https://appleid.apple.com/account/manage)" 53 + read -s APPLE_PASSWORD 54 + echo "" 55 + 56 + # Clean previous builds 57 + echo -e "${GREEN}🧹 Cleaning previous builds...${NC}" 58 + rm -rf build/ 59 + rm -f ZipMerge.zip 60 + 61 + # Build the app 62 + echo -e "${GREEN}🔨 Building ZipMerge...${NC}" 63 + xcodebuild -project ZipMerge.xcodeproj \ 64 + -scheme ZipMerge \ 65 + -configuration Release \ 66 + -derivedDataPath ./build \ 67 + CODE_SIGN_IDENTITY="Developer ID Application" \ 68 + clean build 69 + 70 + if [ $? -ne 0 ]; then 71 + echo -e "${RED}Build failed!${NC}" 72 + exit 1 73 + fi 74 + 75 + APP_PATH="./build/Build/Products/Release/ZipMerge.app" 76 + 77 + # Verify code signing 78 + echo -e "${GREEN}✅ Verifying code signature...${NC}" 79 + codesign -dv --verbose=4 "$APP_PATH" 80 + 81 + # Create zip for notarization 82 + echo -e "${GREEN}📦 Creating archive...${NC}" 83 + cd build/Build/Products/Release 84 + zip -r ../../../../ZipMerge.zip ZipMerge.app 85 + cd ../../../../ 86 + 87 + # Notarize the app 88 + echo -e "${GREEN}🔐 Submitting for notarization...${NC}" 89 + echo "This may take 5-10 minutes..." 90 + 91 + xcrun notarytool submit ZipMerge.zip \ 92 + --apple-id "$APPLE_ID" \ 93 + --team-id "$TEAM_ID" \ 94 + --password "$APPLE_PASSWORD" \ 95 + --wait 96 + 97 + if [ $? -ne 0 ]; then 98 + echo -e "${RED}Notarization failed!${NC}" 99 + exit 1 100 + fi 101 + 102 + # Staple the notarization ticket 103 + echo -e "${GREEN}📎 Stapling notarization ticket...${NC}" 104 + unzip -q ZipMerge.zip 105 + xcrun stapler staple ZipMerge.app 106 + rm ZipMerge.zip 107 + zip -r -q ZipMerge.zip ZipMerge.app 108 + rm -rf ZipMerge.app 109 + 110 + # Calculate SHA256 111 + echo -e "${GREEN}🔢 Calculating SHA256...${NC}" 112 + SHA256=$(shasum -a 256 ZipMerge.zip | awk '{print $1}') 113 + echo -e "SHA256: ${YELLOW}${SHA256}${NC}" 114 + 115 + # Create git tag 116 + echo -e "${GREEN}🏷️ Creating git tag...${NC}" 117 + git tag -a "$VERSION" -m "Release $VERSION" || echo "Tag already exists" 118 + git push origin "$VERSION" || echo "Tag already pushed" 119 + 120 + # Create GitHub release 121 + echo -e "${GREEN}📤 Creating GitHub release...${NC}" 122 + gh release create "$VERSION" ZipMerge.zip \ 123 + --title "ZipMerge $VERSION" \ 124 + --notes "## Installation 125 + 126 + ### Via Homebrew 127 + \`\`\`bash 128 + brew tap jaspermayone/tap 129 + brew install --cask zipmerge 130 + \`\`\` 131 + 132 + ### Manual Installation 133 + 1. Download ZipMerge.zip 134 + 2. Unzip and move ZipMerge.app to /Applications 135 + 136 + ## SHA256 Checksum 137 + \`\`\` 138 + $SHA256 139 + \`\`\`" 140 + 141 + if [ $? -ne 0 ]; then 142 + echo -e "${RED}GitHub release failed!${NC}" 143 + exit 1 144 + fi 145 + 146 + # Update Homebrew cask 147 + echo -e "${GREEN}🍺 Updating Homebrew cask...${NC}" 148 + 149 + CASK_FILE="$HOMEBREW_TAP_PATH/Casks/zipmerge.rb" 150 + 151 + if [ ! -f "$CASK_FILE" ]; then 152 + echo -e "${RED}Error: Cask file not found at $CASK_FILE${NC}" 153 + exit 1 154 + fi 155 + 156 + # Update version and SHA256 in cask file 157 + sed -i '' "s/version \".*\"/version \"${VERSION#v}\"/" "$CASK_FILE" 158 + sed -i '' "s/sha256 .*/sha256 \"$SHA256\"/" "$CASK_FILE" 159 + 160 + echo -e "${GREEN}✅ Cask file updated${NC}" 161 + 162 + # Commit and push cask update 163 + echo -e "${GREEN}📝 Committing cask update...${NC}" 164 + cd "$HOMEBREW_TAP_PATH" 165 + git add Casks/zipmerge.rb 166 + git commit -m "Update zipmerge to $VERSION" 167 + git push 168 + 169 + echo "" 170 + echo -e "${GREEN}✨ Release complete!${NC}" 171 + echo "" 172 + echo "Users can now install with:" 173 + echo -e "${YELLOW}brew tap jaspermayone/tap${NC}" 174 + echo -e "${YELLOW}brew install --cask zipmerge${NC}" 175 + echo "" 176 + echo "SHA256: $SHA256"