From 3af7ca98b639903869603c08b440f3d43aa3eda4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Nov 2025 10:10:28 +0000 Subject: [PATCH 1/3] Add Homebrew installation support This commit adds comprehensive Homebrew support for installing the ejson CLI: ## Changes Made: 1. **Added --version flag to CLI** (Sources/ejson/main.swift) - Responds to -v, --version, and version commands - Prints version and compatibility information 2. **Created Homebrew formula** (Formula/ejson.rb) - Installs pre-built universal macOS binaries - Includes comprehensive tests (version, help, keygen) - Provides helpful caveats for first-time users - Supports both Intel and Apple Silicon 3. **Created Homebrew documentation** (HOMEBREW.md) - Installation instructions for users - Tap setup guide for maintainers - Formula update procedures - Troubleshooting section 4. **Created formula update script** (scripts/update-formula.sh) - Automates SHA256 checksum updates - Downloads and verifies releases - Updates version and URLs automatically - Provides clear instructions for committing 5. **Updated README.md** - Added Homebrew as recommended installation method - Includes both tap and direct installation options - Links to detailed Homebrew documentation 6. **Updated RELEASING.md** - Added post-release Homebrew formula update steps - Documents both in-repo and separate tap workflows ## Installation Methods: Users can now install ejson via: - `brew tap diogot/ejson && brew install ejson` (via tap) - `brew install https://raw.githubusercontent.com/diogot/swift-ejson/main/Formula/ejson.rb` (direct) - Traditional binary download (still supported) - Build from source (still supported) ## Next Steps: After the first release (v1.0.0): 1. Run `./scripts/update-formula.sh 1.0.0` to update SHA256 2. Commit and push the updated formula 3. Optionally create a separate tap repository (diogot/homebrew-ejson) --- Formula/ejson.rb | 57 ++++++++++++ HOMEBREW.md | 187 ++++++++++++++++++++++++++++++++++++++ README.md | 24 ++++- RELEASING.md | 26 +++++- Sources/ejson/main.swift | 7 ++ scripts/update-formula.sh | 82 +++++++++++++++++ 6 files changed, 378 insertions(+), 5 deletions(-) create mode 100644 Formula/ejson.rb create mode 100644 HOMEBREW.md create mode 100755 scripts/update-formula.sh diff --git a/Formula/ejson.rb b/Formula/ejson.rb new file mode 100644 index 0000000..7ffdb6a --- /dev/null +++ b/Formula/ejson.rb @@ -0,0 +1,57 @@ +class Ejson < Formula + desc "Swift implementation of Shopify's EJSON for managing encrypted secrets" + homepage "https://github.com/diogot/swift-ejson" + version "1.0.0" + + on_macos do + if Hardware::CPU.arm? + url "https://github.com/diogot/swift-ejson/releases/download/v1.0.0/ejson-1.0.0-macos-universal.tar.gz" + sha256 "PLACEHOLDER_SHA256_WILL_BE_UPDATED_ON_RELEASE" + else + url "https://github.com/diogot/swift-ejson/releases/download/v1.0.0/ejson-1.0.0-macos-universal.tar.gz" + sha256 "PLACEHOLDER_SHA256_WILL_BE_UPDATED_ON_RELEASE" + end + end + + def install + bin.install "ejson" + end + + test do + # Test version command + assert_match "ejson version", shell_output("#{bin}/ejson --version") + + # Test help command + assert_match "Usage: ejson", shell_output("#{bin}/ejson help") + + # Test keygen command (generates a keypair) + output = shell_output("#{bin}/ejson keygen") + assert_match "Public Key:", output + assert_match "Private Key:", output + end + + def caveats + <<~EOS + ejson has been installed! + + To get started: + 1. Generate a keypair: + ejson keygen + + 2. Create a secrets file with the public key: + echo '{"_public_key": "YOUR_PUBLIC_KEY", "secret": "value"}' > secrets.json + + 3. Encrypt the file: + ejson encrypt secrets.json + + 4. Store the private key in the keydir: + mkdir -p /opt/ejson/keys + echo "YOUR_PRIVATE_KEY" > /opt/ejson/keys/YOUR_PUBLIC_KEY + + 5. Decrypt the file: + ejson decrypt secrets.json + + For more information: https://github.com/diogot/swift-ejson + EOS + end +end diff --git a/HOMEBREW.md b/HOMEBREW.md new file mode 100644 index 0000000..8dc3db5 --- /dev/null +++ b/HOMEBREW.md @@ -0,0 +1,187 @@ +# Homebrew Installation Guide + +This guide explains how to install `ejson` via Homebrew. + +## Installation Options + +### Option 1: Direct Formula Installation (Quick) + +You can install directly from the formula file without setting up a tap: + +```bash +brew install https://raw.githubusercontent.com/diogot/swift-ejson/main/Formula/ejson.rb +``` + +### Option 2: Using a Homebrew Tap (Recommended) + +A Homebrew tap provides a better user experience with simpler commands. + +#### For Users + +Once the tap is set up, install with: + +```bash +# Add the tap +brew tap diogot/ejson + +# Install ejson +brew install ejson +``` + +To upgrade: + +```bash +brew upgrade ejson +``` + +To uninstall: + +```bash +brew uninstall ejson +brew untap diogot/ejson +``` + +#### For Maintainers: Setting Up a Tap + +1. **Create a tap repository** named `homebrew-ejson`: + ```bash + # Create a new repository on GitHub: diogot/homebrew-ejson + git clone https://github.com/diogot/homebrew-ejson.git + cd homebrew-ejson + ``` + +2. **Copy the formula**: + ```bash + # Create Formula directory in the tap + mkdir -p Formula + + # Copy the formula from this repo + cp /path/to/swift-ejson/Formula/ejson.rb Formula/ + ``` + +3. **Update the SHA256 checksum** after creating a release: + ```bash + # Download the release tarball + VERSION="1.0.0" + curl -L -o ejson.tar.gz "https://github.com/diogot/swift-ejson/releases/download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz" + + # Calculate SHA256 + shasum -a 256 ejson.tar.gz + + # Update the sha256 value in Formula/ejson.rb + ``` + +4. **Commit and push**: + ```bash + git add Formula/ejson.rb + git commit -m "Add ejson formula v${VERSION}" + git push origin main + ``` + +5. **Test the tap**: + ```bash + brew tap diogot/ejson + brew install ejson + ejson --version + ``` + +## Updating the Formula for New Releases + +When a new version is released: + +1. **Download the new release tarball**: + ```bash + VERSION="1.1.0" # New version + curl -L -o ejson.tar.gz "https://github.com/diogot/swift-ejson/releases/download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz" + ``` + +2. **Calculate the SHA256**: + ```bash + shasum -a 256 ejson.tar.gz + # Output: abc123def456... + ``` + +3. **Update the formula** in `homebrew-ejson/Formula/ejson.rb`: + - Update the `version` line + - Update the `url` with the new version number + - Update the `sha256` with the new checksum + +4. **Commit and push**: + ```bash + cd homebrew-ejson + git add Formula/ejson.rb + git commit -m "Update ejson to v${VERSION}" + git push origin main + ``` + +5. **Users can then upgrade**: + ```bash + brew update + brew upgrade ejson + ``` + +## Testing the Formula Locally + +Before pushing changes, test the formula locally: + +```bash +# Install from local formula +brew install --build-from-source Formula/ejson.rb + +# Or test without installing +brew audit --strict Formula/ejson.rb +brew test Formula/ejson.rb + +# Uninstall after testing +brew uninstall ejson +``` + +## Submitting to Homebrew Core (Optional) + +For wider distribution, you can submit to the official Homebrew repository: + +1. **Requirements**: + - Project must be stable and well-maintained + - Binaries should be notarized (macOS) + - Formula must follow Homebrew guidelines + +2. **Process**: + ```bash + # Fork homebrew-core + # Add formula to Formula/ejson.rb + # Submit a pull request + ``` + +See: https://docs.brew.sh/Adding-Software-to-Homebrew + +## Troubleshooting + +### Formula Not Found + +If `brew install ejson` fails with "No available formula": + +1. Ensure the tap is added: `brew tap diogot/ejson` +2. Update Homebrew: `brew update` +3. Try the direct URL installation method + +### SHA256 Mismatch + +If installation fails with SHA256 mismatch: + +1. The formula needs to be updated with the correct checksum +2. Contact the maintainer or open an issue + +### Binary Not Found After Installation + +If `ejson` command is not found: + +1. Check if it's installed: `brew list ejson` +2. Check your PATH: `echo $PATH | grep -o '/usr/local/bin'` +3. Try running with full path: `/usr/local/bin/ejson --version` +4. Restart your terminal + +## Resources + +- [Homebrew Formula Cookbook](https://docs.brew.sh/Formula-Cookbook) +- [Homebrew Taps Documentation](https://docs.brew.sh/Taps) +- [swift-ejson Repository](https://github.com/diogot/swift-ejson) diff --git a/README.md b/README.md index f64e592..d9c012d 100644 --- a/README.md +++ b/README.md @@ -284,7 +284,29 @@ EJSONKit includes a command-line tool compatible with the [Go EJSON CLI](https:/ ### Installation -#### Pre-built Binaries (Recommended) +#### Homebrew (Recommended for macOS) + +The easiest way to install on macOS: + +```bash +# Option 1: Via tap (after tap is set up) +brew tap diogot/ejson +brew install ejson + +# Option 2: Direct installation +brew install https://raw.githubusercontent.com/diogot/swift-ejson/main/Formula/ejson.rb +``` + +Upgrade to the latest version: + +```bash +brew update +brew upgrade ejson +``` + +See [HOMEBREW.md](HOMEBREW.md) for detailed instructions on setting up the tap. + +#### Pre-built Binaries Download the latest release for your platform from [GitHub Releases](https://github.com/diogot/swift-ejson/releases): diff --git a/RELEASING.md b/RELEASING.md index 646cf53..e87d0b2 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -144,7 +144,25 @@ rm -rf .build release After releasing: -1. Announce the release (Twitter, forums, etc.) -2. Update documentation sites if applicable -3. Close related issues/PRs -4. Plan next release milestone +1. **Update Homebrew Formula**: + ```bash + # Run the update script with the new version + ./scripts/update-formula.sh 1.0.0 + + # Review and commit the changes + git add Formula/ejson.rb + git commit -m "Update Homebrew formula to v1.0.0" + git push + + # If using a separate tap repository: + cd ../homebrew-ejson + cp ../swift-ejson/Formula/ejson.rb Formula/ + git add Formula/ejson.rb + git commit -m "Update ejson to v1.0.0" + git push + ``` + +2. Announce the release (Twitter, forums, etc.) +3. Update documentation sites if applicable +4. Close related issues/PRs +5. Plan next release milestone diff --git a/Sources/ejson/main.swift b/Sources/ejson/main.swift index 9eacda2..3490022 100644 --- a/Sources/ejson/main.swift +++ b/Sources/ejson/main.swift @@ -210,6 +210,11 @@ func decryptCommand(args: [String]) { } } +func printVersion() { + print("ejson version 1.0.0") + print("Swift EJSON - Compatible with Shopify EJSON") +} + func printUsage() { print(""" Usage: ejson [options] @@ -260,6 +265,8 @@ func main() { decryptCommand(args: commandArgs) case "-h", "--help", "help": printUsage() + case "-v", "--version", "version": + printVersion() default: exitWithError("Unknown command: \(command)\nRun 'ejson help' for usage information") } diff --git a/scripts/update-formula.sh b/scripts/update-formula.sh new file mode 100755 index 0000000..61d8a6b --- /dev/null +++ b/scripts/update-formula.sh @@ -0,0 +1,82 @@ +#!/bin/bash +set -e + +# Script to update the Homebrew formula with the correct SHA256 checksum +# Usage: ./scripts/update-formula.sh +# Example: ./scripts/update-formula.sh 1.0.0 + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 1.0.0" + exit 1 +fi + +VERSION=$1 +FORMULA_FILE="Formula/ejson.rb" +RELEASE_URL="https://github.com/diogot/swift-ejson/releases/download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz" + +echo "Updating Homebrew formula for version ${VERSION}..." + +# Check if formula file exists +if [ ! -f "$FORMULA_FILE" ]; then + echo "Error: Formula file not found at $FORMULA_FILE" + exit 1 +fi + +# Download the release tarball +echo "Downloading release tarball..." +TEMP_FILE=$(mktemp) +trap "rm -f $TEMP_FILE" EXIT + +if ! curl -L -f -o "$TEMP_FILE" "$RELEASE_URL"; then + echo "Error: Failed to download release from $RELEASE_URL" + echo "Make sure the release v${VERSION} exists on GitHub" + exit 1 +fi + +# Calculate SHA256 +echo "Calculating SHA256 checksum..." +if command -v sha256sum &> /dev/null; then + SHA256=$(sha256sum "$TEMP_FILE" | awk '{print $1}') +elif command -v shasum &> /dev/null; then + SHA256=$(shasum -a 256 "$TEMP_FILE" | awk '{print $1}') +else + echo "Error: Neither sha256sum nor shasum found" + exit 1 +fi + +echo "SHA256: $SHA256" + +# Create backup of formula +cp "$FORMULA_FILE" "${FORMULA_FILE}.backup" + +# Update the formula +echo "Updating formula..." + +# Update version +sed -i.tmp "s/version \".*\"/version \"${VERSION}\"/" "$FORMULA_FILE" + +# Update URL +sed -i.tmp "s|download/v[0-9.]\+/ejson-[0-9.]\+-macos-universal.tar.gz|download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz|g" "$FORMULA_FILE" + +# Update SHA256 (replace PLACEHOLDER or existing hash) +sed -i.tmp "s/sha256 \".*\"/sha256 \"${SHA256}\"/" "$FORMULA_FILE" + +# Clean up sed backup files +rm -f "${FORMULA_FILE}.tmp" + +echo "" +echo "Formula updated successfully!" +echo "" +echo "Changes made to $FORMULA_FILE:" +echo " - version: ${VERSION}" +echo " - sha256: ${SHA256}" +echo "" +echo "Please review the changes:" +git diff "$FORMULA_FILE" || diff -u "${FORMULA_FILE}.backup" "$FORMULA_FILE" || true +echo "" +echo "If everything looks good:" +echo " 1. Commit: git add $FORMULA_FILE && git commit -m \"Update formula to v${VERSION}\"" +echo " 2. Push: git push" +echo "" +echo "To restore the backup: mv ${FORMULA_FILE}.backup $FORMULA_FILE" From d59b327f37409eef4698f35ebe6cfe39a5481979 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Nov 2025 10:29:10 +0000 Subject: [PATCH 2/3] Implement centralized version management and automated releases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit establishes a single source of truth for version management and automates the entire release process via GitHub Actions. ## Version Management **Single Source of Truth:** - Version is now defined in `Sources/EJSONKit/Version.swift` - All components (binary, releases, tags, formula) sync from this file - No more version drift between components **Created Files:** - `Sources/EJSONKit/Version.swift` - Central version definition - `scripts/get-version.sh` - Extracts version from code - `VERSION_MANAGEMENT.md` - Comprehensive documentation ## Automated Release Workflow **New Manual Workflow** (`.github/workflows/create-release.yml`): - Trigger: Manual dispatch (requires typing "release" to confirm) - Process: 1. Extracts version from Version.swift 2. Validates format and checks if tag exists 3. Runs all tests 4. Builds universal macOS binary 5. Creates and pushes git tag 6. Creates GitHub release with binaries 7. **Automatically updates Homebrew formula with SHA256** 8. Commits updated formula back to main - Everything is automated - no manual SHA256 calculation needed **Updated Existing Workflow** (`.github/workflows/release.yml`): - Renamed to "Release (Tag-based)" for clarity - Kept for backward compatibility - Now serves as fallback if manual workflow is unavailable ## CLI Changes **Updated Binary** (`Sources/ejson/main.swift`): - Now imports version from EJSONKit.Version - Responds to `--version`, `-v`, and `version` commands - Prints: "ejson version 1.0.0" ## Documentation Updates **RELEASING.md:** - Completely rewritten for automated workflow - New recommended process: Update Version.swift → Trigger workflow → Done - Added version synchronization table - Manual process documented as alternative **HOMEBREW.md:** - Added section on automated formula updates - Explains version management - Manual update process for edge cases **README.md:** - Added "Version Management" section - Links to VERSION_MANAGEMENT.md - Updated contributing guidelines **VERSION_MANAGEMENT.md (NEW):** - Complete guide to version management - How version syncing works - Benefits and validation - Instructions for contributors and maintainers ## Release Process **Before this commit:** 1. Manually update version in multiple places 2. Create and push tag 3. Wait for build 4. Download binary, calculate SHA256 5. Manually update Homebrew formula 6. Commit formula changes **After this commit:** 1. Edit `Sources/EJSONKit/Version.swift` 2. Commit and push 3. Click "Run workflow" on GitHub Actions 4. Type "release" to confirm 5. Done! Everything automated. ## Benefits 1. ✅ **No version drift** - Single source ensures consistency 2. ✅ **Fully automated** - One-click releases 3. ✅ **Validated** - Prevents duplicate tags, invalid versions 4. ✅ **SHA256 auto-calculated** - No manual checksum work 5. ✅ **Formula auto-updated** - Committed back to main 6. ✅ **Traceable** - Version changes visible in git history 7. ✅ **Error-proof** - Workflow validates everything ## Version Synchronization | Component | Source | Method | |---------------------|-------------------------------|----------------------| | Library Version | Version.swift | Direct definition | | Binary Version | CLI --version | Import from EJSONKit | | Git Tag | GitHub Actions | Extract from code | | GitHub Release | GitHub Actions | Uses git tag | | Homebrew Formula | Auto-updated by workflow | SHA256 calculated | ## Testing To test the version extraction: ```bash ./scripts/get-version.sh # Returns: 1.0.0 ``` To test the binary version (after building): ```bash swift build .build/debug/ejson --version # Returns: ejson version 1.0.0 ``` ## Next Steps After merging to main, create the first release: 1. Go to: https://github.com/diogot/swift-ejson/actions/workflows/create-release.yml 2. Click "Run workflow" 3. Type "release" to confirm 4. Monitor the automated process 5. Verify release and formula were created/updated This establishes the foundation for streamlined, automated releases going forward. --- .github/workflows/create-release.yml | 250 +++++++++++++++++++++++++++ .github/workflows/release.yml | 6 +- HOMEBREW.md | 52 ++++-- README.md | 5 + RELEASING.md | 160 +++++++++++------ Sources/EJSONKit/Version.swift | 17 ++ Sources/ejson/main.swift | 4 +- VERSION_MANAGEMENT.md | 176 +++++++++++++++++++ scripts/get-version.sh | 28 +++ 9 files changed, 629 insertions(+), 69 deletions(-) create mode 100644 .github/workflows/create-release.yml create mode 100644 Sources/EJSONKit/Version.swift create mode 100644 VERSION_MANAGEMENT.md create mode 100755 scripts/get-version.sh diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 0000000..5f67b9a --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,250 @@ +name: Create Release + +on: + workflow_dispatch: + inputs: + confirm: + description: 'Type "release" to confirm' + required: true + default: '' + +jobs: + validate: + name: Validate Release + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + tag: ${{ steps.get_version.outputs.tag }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Validate confirmation + run: | + if [ "${{ github.event.inputs.confirm }}" != "release" ]; then + echo "Error: You must type 'release' to confirm" + exit 1 + fi + + - name: Get version from code + id: get_version + run: | + VERSION=$(./scripts/get-version.sh) + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "tag=v$VERSION" >> $GITHUB_OUTPUT + echo "Version to release: $VERSION" + + - name: Check if tag exists + run: | + if git ls-remote --tags origin | grep -q "refs/tags/${{ steps.get_version.outputs.tag }}"; then + echo "Error: Tag ${{ steps.get_version.outputs.tag }} already exists" + echo "Please update the version in Sources/EJSONKit/Version.swift" + exit 1 + fi + echo "Tag ${{ steps.get_version.outputs.tag }} does not exist - OK to proceed" + + - name: Run tests + run: | + swift test + + build-macos: + name: Build macOS Universal Binary + needs: validate + runs-on: macos-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Check Swift version + run: swift --version + + - name: Run tests + run: swift test + + - name: Build release binary + run: ./scripts/build-release.sh ${{ needs.validate.outputs.version }} + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: macos-universal + path: | + release/*.tar.gz + release/*.sha256 + + create-release: + name: Create GitHub Release + needs: [validate, build-macos] + runs-on: ubuntu-latest + permissions: + contents: write + outputs: + sha256: ${{ steps.get_sha.outputs.sha256 }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download macOS artifact + uses: actions/download-artifact@v4 + with: + name: macos-universal + path: release/ + + - name: Get SHA256 + id: get_sha + run: | + SHA256=$(cat release/ejson-${{ needs.validate.outputs.version }}-macos-universal.tar.gz.sha256 | awk '{print $1}') + echo "sha256=$SHA256" >> $GITHUB_OUTPUT + echo "SHA256: $SHA256" + + - name: Create and push tag + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a ${{ needs.validate.outputs.tag }} -m "Release version ${{ needs.validate.outputs.version }}" + git push origin ${{ needs.validate.outputs.tag }} + + - name: Generate release notes + id: release_notes + run: | + cat > release_notes.md << 'EOF' + ## Installation + + ### Homebrew (Recommended for macOS) + + ```bash + # Via tap + brew tap diogot/ejson + brew install ejson + + # Or direct installation + brew install https://raw.githubusercontent.com/diogot/swift-ejson/main/Formula/ejson.rb + ``` + + ### macOS (Universal Binary - x86_64 + ARM64) + + Download and install: + ```bash + curl -L https://github.com/${{ github.repository }}/releases/download/${{ needs.validate.outputs.tag }}/ejson-${{ needs.validate.outputs.version }}-macos-universal.tar.gz | tar xz + sudo mv ejson /usr/local/bin/ + ejson --version + ``` + + Or with wget: + ```bash + wget https://github.com/${{ github.repository }}/releases/download/${{ needs.validate.outputs.tag }}/ejson-${{ needs.validate.outputs.version }}-macos-universal.tar.gz + tar xzf ejson-${{ needs.validate.outputs.version }}-macos-universal.tar.gz + sudo mv ejson /usr/local/bin/ + ejson --version + ``` + + ### Verify Checksum + + ```bash + # Download checksum file + curl -L https://github.com/${{ github.repository }}/releases/download/${{ needs.validate.outputs.tag }}/ejson-${{ needs.validate.outputs.version }}-macos-universal.tar.gz.sha256 -o ejson.sha256 + + # Verify (macOS) + shasum -a 256 -c ejson.sha256 + + # Verify (Linux) + sha256sum -c ejson.sha256 + ``` + + ## Features + + - 🔐 NaCl Box encryption compatible with Shopify EJSON + - 🔄 Full compatibility with Go EJSON implementation + - ⚡ Fast and native Swift implementation + - 📦 Universal macOS binary (works on both Intel and Apple Silicon) + + ## Usage + + ```bash + # Generate a keypair + ejson keygen + + # Encrypt a file + ejson encrypt secrets.json + + # Decrypt a file + ejson decrypt secrets.json + ``` + + For more information, see the [README](https://github.com/${{ github.repository }}/blob/main/README.md). + EOF + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.validate.outputs.tag }} + name: Release ${{ needs.validate.outputs.version }} + body_path: release_notes.md + files: | + release/*.tar.gz + release/*.sha256 + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + update-formula: + name: Update Homebrew Formula + needs: [validate, create-release] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: main + + - name: Update formula with SHA256 + run: | + VERSION="${{ needs.validate.outputs.version }}" + SHA256="${{ needs.create-release.outputs.sha256 }}" + FORMULA_FILE="Formula/ejson.rb" + + echo "Updating formula..." + echo "Version: $VERSION" + echo "SHA256: $SHA256" + + # Update version + sed -i "s/version \".*\"/version \"${VERSION}\"/" "$FORMULA_FILE" + + # Update URL + sed -i "s|download/v[0-9.]\+/ejson-[0-9.]\+-macos-universal.tar.gz|download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz|g" "$FORMULA_FILE" + + # Update SHA256 + sed -i "s/sha256 \".*\"/sha256 \"${SHA256}\"/" "$FORMULA_FILE" + + echo "Formula updated:" + cat "$FORMULA_FILE" + + - name: Commit and push formula + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add Formula/ejson.rb + git commit -m "Update Homebrew formula to v${{ needs.validate.outputs.version }}" + git push origin main + + - name: Summary + run: | + echo "## Release Created Successfully! 🎉" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ needs.validate.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "**Tag:** ${{ needs.validate.outputs.tag }}" >> $GITHUB_STEP_SUMMARY + echo "**SHA256:** ${{ needs.create-release.outputs.sha256 }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Installation" >> $GITHUB_STEP_SUMMARY + echo '```bash' >> $GITHUB_STEP_SUMMARY + echo "brew tap diogot/ejson" >> $GITHUB_STEP_SUMMARY + echo "brew install ejson" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Next Steps" >> $GITHUB_STEP_SUMMARY + echo "1. Test the installation: \`brew install ejson\`" >> $GITHUB_STEP_SUMMARY + echo "2. If using a separate tap, copy Formula/ejson.rb to homebrew-ejson repo" >> $GITHUB_STEP_SUMMARY + echo "3. Announce the release" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a4d33e0..96a1ffe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,8 @@ -name: Release +name: Release (Tag-based) + +# This workflow is kept for backward compatibility +# The recommended approach is to use the "Create Release" workflow (create-release.yml) +# which reads version from code and automates everything on: push: diff --git a/HOMEBREW.md b/HOMEBREW.md index 8dc3db5..e8ae84d 100644 --- a/HOMEBREW.md +++ b/HOMEBREW.md @@ -87,39 +87,57 @@ brew untap diogot/ejson ## Updating the Formula for New Releases -When a new version is released: +### Automated Updates (Recommended) -1. **Download the new release tarball**: - ```bash - VERSION="1.1.0" # New version - curl -L -o ejson.tar.gz "https://github.com/diogot/swift-ejson/releases/download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz" - ``` +The formula is **automatically updated** when a release is created using the GitHub Actions workflow. The maintainer only needs to: + +1. Update version in `Sources/EJSONKit/Version.swift` +2. Trigger the "Create Release" workflow +3. Everything else happens automatically: + - Git tag created + - Binary built + - Release created + - **Formula updated with correct SHA256** -2. **Calculate the SHA256**: +See [RELEASING.md](RELEASING.md) for complete instructions. + +### Manual Updates (If Needed) + +If you need to manually update the formula: + +1. **Use the update script**: ```bash - shasum -a 256 ejson.tar.gz - # Output: abc123def456... - ``` + # This script downloads the release and updates the formula + ./scripts/update-formula.sh 1.1.0 -3. **Update the formula** in `homebrew-ejson/Formula/ejson.rb`: - - Update the `version` line - - Update the `url` with the new version number - - Update the `sha256` with the new checksum + # Review the changes + git diff Formula/ejson.rb -4. **Commit and push**: + # Commit and push + git add Formula/ejson.rb + git commit -m "Update formula to v1.1.0" + git push origin main + ``` + +2. **For separate tap repository**: ```bash cd homebrew-ejson + cp ../swift-ejson/Formula/ejson.rb Formula/ git add Formula/ejson.rb - git commit -m "Update ejson to v${VERSION}" + git commit -m "Update ejson to v1.1.0" git push origin main ``` -5. **Users can then upgrade**: +3. **Users can then upgrade**: ```bash brew update brew upgrade ejson ``` +### Version Management + +Version is centrally managed in `Sources/EJSONKit/Version.swift`. All releases and formula updates sync from this single source. This ensures the binary version, git tags, GitHub releases, and Homebrew formula are always in sync. + ## Testing the Formula Locally Before pushing changes, test the formula locally: diff --git a/README.md b/README.md index d9c012d..59cd037 100644 --- a/README.md +++ b/README.md @@ -454,6 +454,10 @@ swift test - macOS 10.15+ / iOS 13+ / tvOS 13+ / watchOS 6+ - Linux: libsodium-dev package required +## Version Management + +Version is managed centrally in `Sources/EJSONKit/Version.swift`. All components (binary, releases, tags, Homebrew formula) automatically sync from this file. See [VERSION_MANAGEMENT.md](VERSION_MANAGEMENT.md) for details. + ## Contributing Contributions are welcome! Please ensure: @@ -462,6 +466,7 @@ Contributions are welcome! Please ensure: - New features include tests - Code follows Swift conventions - Changes maintain compatibility with Go EJSON +- Don't manually update version numbers (handled by maintainers) ## License diff --git a/RELEASING.md b/RELEASING.md index e87d0b2..c42f9f9 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -2,81 +2,134 @@ This document describes how to create a new release of swift-ejson. +## Version Management + +**Version is defined in code** - The single source of truth for version information is: +``` +Sources/EJSONKit/Version.swift +``` + +All version references (binary, releases, tags, Homebrew formula) automatically sync from this file. + ## Prerequisites - Write access to the repository - All tests passing on main branch -- Updated CHANGELOG (if applicable) +- All changes merged to main -## Release Steps +## Recommended Release Process (Automated) -### 1. Prepare the Release +### 1. Update the Version -Ensure all changes for the release are merged to the main branch: +Edit `Sources/EJSONKit/Version.swift` and update the version: -```bash -git checkout main -git pull origin main +```swift +public static let current = "1.0.0" // Change to your new version ``` -### 2. Update Version References - -Update version references in documentation if needed: - -- README.md (example version numbers in CLI installation) -- Package.swift (if you maintain a version constant) - -### 3. Create and Push a Tag - -Create a version tag following semantic versioning (vMAJOR.MINOR.PATCH): +Commit and push to main: ```bash -# Create an annotated tag -git tag -a v1.0.0 -m "Release version 1.0.0" +git checkout main +git add Sources/EJSONKit/Version.swift +git commit -m "Bump version to 1.0.0" +git push origin main +``` + +### 2. Trigger the Release Workflow -# Push the tag to GitHub -git push origin v1.0.0 +Go to the GitHub Actions page: +``` +https://github.com/diogot/swift-ejson/actions/workflows/create-release.yml ``` -### 4. Automated Build Process +1. Click "Run workflow" +2. Type "release" to confirm +3. Click "Run workflow" button -Once you push the tag, GitHub Actions will automatically: +### 3. Automated Process -1. **Run Tests** - Ensure all tests pass on macOS and Linux -2. **Build macOS Binary** - Create a universal binary (x86_64 + ARM64) -3. **Create Archive** - Package the binary as `.tar.gz` -4. **Calculate Checksums** - Generate SHA256 checksums -5. **Create GitHub Release** - Publish release with all artifacts -6. **Upload Assets** - Attach binaries and checksums +The workflow will automatically: -You can monitor the progress at: `https://github.com/diogot/swift-ejson/actions` +1. ✅ **Validate** - Extract version from code, check tests pass +2. 🏗️ **Build** - Create universal macOS binary (x86_64 + ARM64) +3. 🏷️ **Tag** - Create and push git tag (e.g., v1.0.0) +4. 📦 **Release** - Create GitHub release with binaries +5. 🍺 **Update Formula** - Update Homebrew formula with SHA256 +6. ✅ **Commit** - Push updated formula to main -### 5. Verify the Release +Monitor progress at: `https://github.com/diogot/swift-ejson/actions` + +### 4. Verify the Release After the workflow completes: 1. Go to https://github.com/diogot/swift-ejson/releases 2. Verify the release was created with: - - Release notes + - Correct version number - Binary archive (`.tar.gz`) - Checksum file (`.sha256`) + - Release notes -### 6. Test the Release +### 5. Test the Installation -Download and test the binary: +Test the Homebrew installation: + +```bash +# Update Homebrew +brew update + +# Install via direct URL +brew install https://raw.githubusercontent.com/diogot/swift-ejson/main/Formula/ejson.rb + +# Or via tap (if set up) +brew tap diogot/ejson +brew install ejson + +# Verify version +ejson --version +``` + +Test manual download: ```bash VERSION="1.0.0" curl -L "https://github.com/diogot/swift-ejson/releases/download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz" | tar xz -./ejson help -./ejson keygen +./ejson --version +``` + +## Alternative: Manual Release Process + +If you prefer manual control or the automated workflow fails: + +### 1. Update Version in Code + +```bash +# Edit Sources/EJSONKit/Version.swift +git add Sources/EJSONKit/Version.swift +git commit -m "Bump version to 1.0.0" +git push origin main ``` -Verify the checksum: +### 2. Create and Push Tag ```bash -curl -L "https://github.com/diogot/swift-ejson/releases/download/v${VERSION}/ejson-${VERSION}-macos-universal.tar.gz.sha256" -o ejson.sha256 -shasum -a 256 -c ejson.sha256 +VERSION=$(./scripts/get-version.sh) +git tag -a v${VERSION} -m "Release version ${VERSION}" +git push origin v${VERSION} +``` + +This triggers the tag-based release workflow (release.yml). + +### 3. Update Homebrew Formula + +After the release is created: + +```bash +./scripts/update-formula.sh 1.0.0 +git add Formula/ejson.rb +git commit -m "Update Homebrew formula to v1.0.0" +git push origin main ``` ## Versioning Guidelines @@ -144,17 +197,10 @@ rm -rf .build release After releasing: -1. **Update Homebrew Formula**: - ```bash - # Run the update script with the new version - ./scripts/update-formula.sh 1.0.0 - - # Review and commit the changes - git add Formula/ejson.rb - git commit -m "Update Homebrew formula to v1.0.0" - git push +1. **Update Separate Tap (Optional)**: - # If using a separate tap repository: + If using a separate `homebrew-ejson` tap repository: + ```bash cd ../homebrew-ejson cp ../swift-ejson/Formula/ejson.rb Formula/ git add Formula/ejson.rb @@ -162,7 +208,23 @@ After releasing: git push ``` + Note: The formula in the main repo is already updated automatically. + 2. Announce the release (Twitter, forums, etc.) 3. Update documentation sites if applicable 4. Close related issues/PRs 5. Plan next release milestone + +## Version Synchronization + +The version system ensures everything stays in sync: + +| Component | Source | How it Syncs | +|-----------|--------|--------------| +| **Library Version** | `Sources/EJSONKit/Version.swift` | Direct reference | +| **Binary Version** | CLI `--version` flag | Imports from EJSONKit.Version | +| **Git Tag** | GitHub Actions | Extracted via `scripts/get-version.sh` | +| **GitHub Release** | GitHub Actions | Uses git tag | +| **Homebrew Formula** | `Formula/ejson.rb` | Auto-updated by workflow | + +**To change version**: Edit `Sources/EJSONKit/Version.swift` only. Everything else updates automatically. diff --git a/Sources/EJSONKit/Version.swift b/Sources/EJSONKit/Version.swift new file mode 100644 index 0000000..5ad0d28 --- /dev/null +++ b/Sources/EJSONKit/Version.swift @@ -0,0 +1,17 @@ +/// Version information for EJSONKit and ejson CLI +/// +/// This is the single source of truth for version information. +/// All other version references should derive from this. +public enum Version { + /// The current version of EJSONKit + /// + /// Update this value when preparing a new release. + /// Format: MAJOR.MINOR.PATCH following Semantic Versioning + public static let current = "1.0.0" + + /// Full version string with additional information + public static let full = "ejson version \(current)" + + /// Version description + public static let description = "Swift EJSON - Compatible with Shopify EJSON" +} diff --git a/Sources/ejson/main.swift b/Sources/ejson/main.swift index 3490022..a483fbc 100644 --- a/Sources/ejson/main.swift +++ b/Sources/ejson/main.swift @@ -211,8 +211,8 @@ func decryptCommand(args: [String]) { } func printVersion() { - print("ejson version 1.0.0") - print("Swift EJSON - Compatible with Shopify EJSON") + print(Version.full) + print(Version.description) } func printUsage() { diff --git a/VERSION_MANAGEMENT.md b/VERSION_MANAGEMENT.md new file mode 100644 index 0000000..9e5f540 --- /dev/null +++ b/VERSION_MANAGEMENT.md @@ -0,0 +1,176 @@ +# Version Management + +## Single Source of Truth + +The version for swift-ejson is defined in **one place only**: + +``` +Sources/EJSONKit/Version.swift +``` + +All other components automatically sync from this file: +- CLI binary `--version` output +- Git tags +- GitHub releases +- Homebrew formula + +## Updating the Version + +To release a new version: + +1. **Edit the version file**: + ```swift + // Sources/EJSONKit/Version.swift + public static let current = "1.1.0" // Update this line + ``` + +2. **Commit and push**: + ```bash + git add Sources/EJSONKit/Version.swift + git commit -m "Bump version to 1.1.0" + git push origin main + ``` + +3. **Trigger the release**: + - Go to GitHub Actions: https://github.com/diogot/swift-ejson/actions/workflows/create-release.yml + - Click "Run workflow" + - Type "release" to confirm + - The workflow will: + - Extract version from code + - Create git tag (v1.1.0) + - Build binaries + - Create GitHub release + - Update Homebrew formula + +## How It Works + +### Version Extraction + +The script `scripts/get-version.sh` extracts the version from code: + +```bash +VERSION=$(./scripts/get-version.sh) +echo $VERSION # Outputs: 1.0.0 +``` + +This is used by: +- Manual release commands +- GitHub Actions workflows +- Build scripts + +### CLI Binary + +The binary imports the version directly: + +```swift +// Sources/ejson/main.swift +import EJSONKit + +func printVersion() { + print(Version.full) // "ejson version 1.0.0" + print(Version.description) // "Swift EJSON - Compatible with Shopify EJSON" +} +``` + +### GitHub Actions + +The `create-release.yml` workflow: + +1. Runs `./scripts/get-version.sh` to extract version +2. Validates the version format +3. Checks if tag already exists +4. Creates tag, release, and updates formula automatically + +### Homebrew Formula + +The formula is automatically updated by the release workflow with: +- Correct version number +- Download URL with version +- SHA256 checksum of the binary + +## Version Format + +We follow [Semantic Versioning](https://semver.org/): + +``` +MAJOR.MINOR.PATCH +``` + +Examples: +- `1.0.0` - Initial release +- `1.1.0` - New features (backward compatible) +- `1.0.1` - Bug fixes +- `2.0.0` - Breaking changes + +The version must match the regex: `^[0-9]+\.[0-9]+\.[0-9]+$` + +## Validation + +The version extraction script validates: +- File exists (`Sources/EJSONKit/Version.swift`) +- Version can be extracted +- Format is valid (MAJOR.MINOR.PATCH) + +The release workflow validates: +- Version format is correct +- Tag doesn't already exist +- Tests pass before releasing + +## Manual Override + +If you need to bypass the automated workflow: + +```bash +# Get current version from code +VERSION=$(./scripts/get-version.sh) + +# Create tag manually +git tag -a v${VERSION} -m "Release version ${VERSION}" +git push origin v${VERSION} + +# This triggers the tag-based release workflow (release.yml) +# Then manually update the formula: +./scripts/update-formula.sh ${VERSION} +``` + +## Benefits + +1. **No version drift** - Binary, releases, and formula always match +2. **Single update point** - Change version in one place +3. **Automated releases** - Less manual work, fewer errors +4. **Validation** - Prevents duplicate tags and invalid versions +5. **Traceable** - Version changes are visible in git history + +## Checking Current Version + +```bash +# From code +./scripts/get-version.sh + +# From binary (if built) +.build/release/ejson --version + +# From installed binary +ejson --version +``` + +## For Contributors + +When working on features: +- **Don't** manually update version numbers in PRs +- **Do** wait for maintainers to bump version before release +- Version bumps happen on `main` branch only +- Releases are created from `main` branch + +## For Maintainers + +Release checklist: +1. ✅ All PRs merged to main +2. ✅ All tests passing +3. ✅ Update `Sources/EJSONKit/Version.swift` +4. ✅ Commit version bump +5. ✅ Run manual release workflow +6. ✅ Verify release was created +7. ✅ Test installation + +See [RELEASING.md](RELEASING.md) for detailed instructions. diff --git a/scripts/get-version.sh b/scripts/get-version.sh new file mode 100755 index 0000000..f9b64cc --- /dev/null +++ b/scripts/get-version.sh @@ -0,0 +1,28 @@ +#!/bin/bash +set -e + +# Extract version from Version.swift +# This is the single source of truth for version information + +VERSION_FILE="Sources/EJSONKit/Version.swift" + +if [ ! -f "$VERSION_FILE" ]; then + echo "Error: Version file not found at $VERSION_FILE" >&2 + exit 1 +fi + +# Extract version string from: public static let current = "1.0.0" +VERSION=$(grep -E 'static let current = "' "$VERSION_FILE" | sed -E 's/.*"([^"]+)".*/\1/') + +if [ -z "$VERSION" ]; then + echo "Error: Could not extract version from $VERSION_FILE" >&2 + exit 1 +fi + +# Validate version format (MAJOR.MINOR.PATCH) +if ! echo "$VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then + echo "Error: Invalid version format: $VERSION (expected MAJOR.MINOR.PATCH)" >&2 + exit 1 +fi + +echo "$VERSION" From 402e6fd0248b55e42cd2d58d38610f5f453a9df4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Nov 2025 10:35:12 +0000 Subject: [PATCH 3/3] Add comprehensive PR description --- PR_DESCRIPTION.md | 187 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 PR_DESCRIPTION.md diff --git a/PR_DESCRIPTION.md b/PR_DESCRIPTION.md new file mode 100644 index 0000000..f4e1c96 --- /dev/null +++ b/PR_DESCRIPTION.md @@ -0,0 +1,187 @@ +# Add Homebrew Installation and Centralized Version Management + +This PR adds comprehensive Homebrew support and implements a centralized version management system with fully automated releases. + +## 🎯 Overview + +This PR makes `ejson` easily installable via Homebrew and establishes a single source of truth for version management across all components (binary, releases, tags, and Homebrew formula). + +## ✨ What's New + +### 1. Homebrew Installation Support + +Users can now install ejson via Homebrew: + +```bash +# Via tap (recommended) +brew tap diogot/ejson +brew install ejson + +# Or direct installation +brew install https://raw.githubusercontent.com/diogot/swift-ejson/main/Formula/ejson.rb +``` + +**Created:** +- `Formula/ejson.rb` - Homebrew formula with comprehensive tests +- `HOMEBREW.md` - Complete installation and maintenance guide +- `scripts/update-formula.sh` - Helper script for formula updates + +**CLI Improvements:** +- Added `--version`, `-v`, and `version` commands +- Prints version and compatibility information + +### 2. Centralized Version Management + +**Single Source of Truth** - Version is now defined in one place: +```swift +// Sources/EJSONKit/Version.swift +public static let current = "1.0.0" +``` + +All components automatically sync from this file: +- ✅ CLI binary `--version` output +- ✅ Git tags +- ✅ GitHub releases +- ✅ Homebrew formula + +**Created:** +- `Sources/EJSONKit/Version.swift` - Central version definition +- `scripts/get-version.sh` - Version extraction script +- `VERSION_MANAGEMENT.md` - Comprehensive documentation + +### 3. Automated Release Workflow + +**New Manual Workflow** (`.github/workflows/create-release.yml`): + +Trigger from GitHub Actions UI → Type "release" to confirm → Done! + +The workflow automatically: +1. ✅ Extracts version from code +2. ✅ Validates format and runs tests +3. ✅ Builds universal macOS binary (Intel + Apple Silicon) +4. ✅ Creates and pushes git tag +5. ✅ Creates GitHub release with binaries +6. ✅ **Calculates SHA256 and updates Homebrew formula** +7. ✅ Commits updated formula back to main + +**Updated:** +- `.github/workflows/release.yml` - Renamed to "Release (Tag-based)", kept for backward compatibility + +### 4. Documentation + +**New Files:** +- `HOMEBREW.md` - Homebrew installation guide +- `VERSION_MANAGEMENT.md` - Version management documentation + +**Updated:** +- `RELEASING.md` - Completely rewritten for automated workflow +- `README.md` - Added Homebrew installation and version management sections + +## 📦 Release Process Comparison + +### Before This PR: +1. Manually update version in multiple places +2. Create and push git tag +3. Wait for build to complete +4. Download binary and calculate SHA256 +5. Manually update Homebrew formula +6. Commit formula changes + +### After This PR: +1. Edit `Sources/EJSONKit/Version.swift` +2. Commit and push to main +3. Click "Run workflow" on GitHub Actions +4. Type "release" to confirm +5. ✨ **Done! Everything automated** + +## 🎁 Benefits + +1. **No Version Drift** - Single source ensures all components stay in sync +2. **Fully Automated Releases** - One-click release process +3. **Easy Installation** - Homebrew support for macOS users +4. **Error-Proof** - Workflow validates version format, prevents duplicate tags +5. **SHA256 Auto-Calculated** - No manual checksum work needed +6. **Formula Auto-Updated** - Committed back to main automatically +7. **Traceable** - Version changes visible in git history + +## 📊 Version Synchronization + +| Component | Source | How it Syncs | +|-----------|--------|--------------| +| Library Version | `Version.swift` | Direct definition | +| Binary Version | CLI `--version` | Imports from `EJSONKit.Version` | +| Git Tag | GitHub Actions | Extracted via `scripts/get-version.sh` | +| GitHub Release | GitHub Actions | Uses git tag | +| Homebrew Formula | Auto-updated | SHA256 calculated by workflow | + +## 🧪 Testing + +Version extraction works: +```bash +$ ./scripts/get-version.sh +1.0.0 +``` + +CLI shows version: +```bash +$ swift build && .build/debug/ejson --version +ejson version 1.0.0 +Swift EJSON - Compatible with Shopify EJSON +``` + +## 🚀 How to Create a Release (After Merge) + +**Simple 3-step process:** + +1. **Update version** in `Sources/EJSONKit/Version.swift`: + ```swift + public static let current = "1.0.0" // Change to new version + ``` + +2. **Commit and push to main**: + ```bash + git add Sources/EJSONKit/Version.swift + git commit -m "Bump version to 1.0.0" + git push origin main + ``` + +3. **Trigger workflow**: + - Go to: https://github.com/diogot/swift-ejson/actions/workflows/create-release.yml + - Click "Run workflow" + - Type "release" to confirm + - Monitor automated process + +The workflow handles everything: tag creation, binary building, release creation, and formula updates. + +## 📋 Files Changed + +### New Files +- `Sources/EJSONKit/Version.swift` - Central version definition +- `Formula/ejson.rb` - Homebrew formula +- `HOMEBREW.md` - Homebrew documentation +- `VERSION_MANAGEMENT.md` - Version management guide +- `.github/workflows/create-release.yml` - Automated release workflow +- `scripts/get-version.sh` - Version extraction script +- `scripts/update-formula.sh` - Formula update helper + +### Modified Files +- `Sources/ejson/main.swift` - Added version command using `EJSONKit.Version` +- `.github/workflows/release.yml` - Renamed, updated description +- `README.md` - Added Homebrew installation and version management sections +- `RELEASING.md` - Rewritten for automated workflow + +## 🔍 Breaking Changes + +None. This PR is fully backward compatible. + +## 📝 Next Steps After Merge + +1. Test the automated release workflow with version 1.0.0 +2. Optionally create a separate tap repository (`homebrew-ejson`) for simpler installation +3. Announce Homebrew availability to users + +## 🙏 Notes + +- The formula uses placeholder SHA256 initially - it will be updated automatically when the first release is created +- The tag-based workflow (`release.yml`) is kept for backward compatibility +- All documentation has been updated to reflect the new processes