diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 433e3be..a79c689 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,6 +8,13 @@ on:
jobs:
build:
runs-on: ubuntu-latest
+ outputs:
+ win_x64_sha256: ${{ steps.checksums.outputs.win_x64_sha256 }}
+ win_arm64_sha256: ${{ steps.checksums.outputs.win_arm64_sha256 }}
+ linux_x64_sha256: ${{ steps.checksums.outputs.linux_x64_sha256 }}
+ linux_arm64_sha256: ${{ steps.checksums.outputs.linux_arm64_sha256 }}
+ osx_x64_sha256: ${{ steps.checksums.outputs.osx_x64_sha256 }}
+ osx_arm64_sha256: ${{ steps.checksums.outputs.osx_arm64_sha256 }}
permissions:
contents: write
@@ -52,6 +59,18 @@ jobs:
cd ./publish/linux-arm64 && tar -czf ../../dotnet-api-diff-linux-arm64.tar.gz . && cd ../..
cd ./publish/osx-arm64 && tar -czf ../../dotnet-api-diff-osx-arm64.tar.gz . && cd ../..
+ - name: Calculate checksums
+ id: checksums
+ run: |
+ {
+ echo "win_x64_sha256=$(sha256sum "dotnet-api-diff-win-x64.zip" | cut -d' ' -f1)"
+ echo "win_arm64_sha256=$(sha256sum "dotnet-api-diff-win-arm64.zip" | cut -d' ' -f1)"
+ echo "linux_x64_sha256=$(sha256sum "dotnet-api-diff-linux-x64.tar.gz" | cut -d' ' -f1)"
+ echo "linux_arm64_sha256=$(sha256sum "dotnet-api-diff-linux-arm64.tar.gz" | cut -d' ' -f1)"
+ echo "osx_x64_sha256=$(sha256sum "dotnet-api-diff-osx-x64.tar.gz" | cut -d' ' -f1)"
+ echo "osx_arm64_sha256=$(sha256sum "dotnet-api-diff-osx-arm64.tar.gz" | cut -d' ' -f1)"
+ } >> "$GITHUB_OUTPUT"
+
- name: Create Release
uses: softprops/action-gh-release@v1
with:
@@ -63,3 +82,53 @@ jobs:
dotnet-api-diff-linux-arm64.tar.gz
dotnet-api-diff-osx-arm64.tar.gz
generate_release_notes: true
+
+ chocolatey:
+ needs: build
+ runs-on: windows-latest
+ if: startsWith(github.ref, 'refs/tags/v')
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup PowerShell
+ shell: pwsh
+ run: |
+ # Install Chocolatey CLI if not present
+ if (-not (Get-Command choco -ErrorAction SilentlyContinue)) {
+ Set-ExecutionPolicy Bypass -Scope Process -Force
+ [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
+ iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
+ }
+
+ - name: Build and publish Chocolatey package
+ shell: pwsh
+ env:
+ CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
+ run: |
+ $version = "${{ github.ref }}" -replace 'refs/tags/v', ''
+ .\scripts\build-chocolatey.ps1 -Version "$version" -ChecksumX64 "${{ needs.build.outputs.win_x64_sha256 }}" -ChecksumArm64 "${{ needs.build.outputs.win_arm64_sha256 }}" -ApiKey "$env:CHOCOLATEY_API_KEY" -Publish
+
+ homebrew:
+ needs: build
+ runs-on: ubuntu-latest
+ if: startsWith(github.ref, 'refs/tags/v')
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Get release version
+ id: release_info
+ run: |
+ VERSION=${GITHUB_REF#refs/tags/v}
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
+
+ - name: Update Homebrew formula
+ run: |
+ ./scripts/update-homebrew.sh "${{ steps.release_info.outputs.version }}" "${{ needs.build.outputs.osx_arm64_sha256 }}" "${{ needs.build.outputs.osx_x64_sha256 }}" "${{ needs.build.outputs.linux_arm64_sha256 }}" "${{ needs.build.outputs.linux_x64_sha256 }}"
+
+ - name: Upload Homebrew formula as artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: homebrew-formula
+ path: artifacts/dotnetapidiff.rb
diff --git a/.gitignore b/.gitignore
index 188bfec..1ecac0c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -92,5 +92,8 @@ node_modules/
# Local History for Visual Studio
.localhistory/test-report/
-
glide-testing/
+
+# Package build directories
+build/
+artifacts/
diff --git a/README.md b/README.md
index a587ed6..accdc44 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,21 @@ task ci
### Installation
-#### Quick Install (Linux/macOS)
+#### Package Managers (Recommended)
+
+**Windows (Chocolatey):**
+
+```powershell
+choco install dotnetapidiff
+```
+
+**macOS/Linux (Homebrew):**
+
+```bash
+brew install dotnetapidiff
+```
+
+#### Quick Install Script (Linux/macOS)
```bash
# Install latest version to user directory
diff --git a/docs/package-manager-setup.md b/docs/package-manager-setup.md
new file mode 100644
index 0000000..378dfd5
--- /dev/null
+++ b/docs/package-manager-setup.md
@@ -0,0 +1,199 @@
+# Package Manager Setup Guide
+
+This document explains how to set up automated publishing to Chocolatey and Homebrew package managers for DotNet API Diff releases.
+
+## Overview
+
+The release workflow automatically builds and publishes packages to:
+
+- **Chocolatey** (Windows package manager)
+- **Homebrew** (macOS/Linux package manager)
+
+## Prerequisites
+
+### Repository Secrets
+
+The following secrets must be configured in the GitHub repository settings:
+
+1. **CHOCOLATEY_API_KEY**: API key for publishing to Chocolatey
+
+### Package Manager Accounts
+
+#### Chocolatey Setup
+
+1. **Create Chocolatey Account**:
+ - Visit [Chocolatey Community](https://community.chocolatey.org/)
+ - Create an account or sign in
+ - Navigate to your profile and generate an API key
+
+2. **Package Registration**:
+ - The first package version must be manually submitted for approval
+ - Subsequent versions will be automatically published via the API
+ - Package ID: `dotnetapidiff`
+
+3. **Configure GitHub Secret**:
+
+ ```bash
+ # In GitHub repository settings > Secrets and variables > Actions
+ # Add new repository secret:
+ Name: CHOCOLATEY_API_KEY
+ Value: [Your Chocolatey API key]
+ ```
+
+#### Homebrew Setup
+
+Homebrew publishing is currently handled by generating an updated formula that can be:
+
+1. **Submitted to homebrew-core** (requires community approval)
+2. **Published to a custom tap** (immediate publishing)
+
+For custom tap approach:
+
+1. Create a repository named `homebrew-dotnetapidiff`
+2. The workflow generates the updated formula as an artifact
+3. Manually or automatically commit the formula to the tap repository
+
+## Workflow Details
+
+### Chocolatey Publishing
+
+The workflow automatically:
+
+1. Builds Windows x64 and ARM64 binaries
+2. Calculates SHA256 checksums
+3. Creates a Chocolatey package (.nupkg)
+4. Publishes to Chocolatey Community using the API key
+
+**Package Structure:**
+
+```text
+dotnetapidiff/
+├── tools/
+│ ├── chocolateyinstall.ps1 # Installation script
+│ ├── chocolateyuninstall.ps1 # Uninstallation script
+│ └── dotnetapidiff.bat # Command wrapper
+└── dotnetapidiff.nuspec # Package metadata
+```
+
+### Homebrew Formula
+
+The workflow automatically:
+
+1. Downloads all platform binaries (macOS/Linux, x64/ARM64)
+2. Calculates SHA256 checksums for each platform
+3. Generates an updated Homebrew formula with correct URLs and checksums
+4. Uploads the formula as a build artifact
+
+**Formula Features:**
+
+- Platform detection (macOS/Linux, Intel/ARM)
+- Automatic binary selection based on platform
+- SHA256 verification
+- Installs binary as `dotnetapidiff`
+
+## Package Testing
+
+### Chocolatey Testing
+
+```powershell
+# Install package
+choco install dotnetapidiff
+
+# Test installation
+dotnetapidiff --version
+
+# Uninstall
+choco uninstall dotnetapidiff
+```
+
+### Homebrew Testing
+
+```bash
+# Install from custom tap (if using tap approach)
+brew tap jbrinkman/dotnetapidiff
+brew install dotnetapidiff
+
+# Test installation
+dotnetapidiff --version
+
+# Uninstall
+brew uninstall dotnetapidiff
+```
+
+## Manual Package Creation
+
+For testing or manual publishing:
+
+### Chocolatey
+
+```powershell
+# Build package locally
+.\scripts\build-chocolatey.ps1 -Version "1.0.0" -ChecksumX64 "abc123..." -ChecksumArm64 "def456..."
+
+# Test package locally
+choco install .\build\chocolatey\dotnetapidiff.1.0.0.nupkg
+
+# Publish manually
+.\scripts\build-chocolatey.ps1 -Version "1.0.0" -ChecksumX64 "abc123..." -ChecksumArm64 "def456..." -ApiKey "your-api-key" -Publish
+```
+
+### Homebrew
+
+```bash
+# Generate formula
+./scripts/update-homebrew.sh "1.0.0" "osx_arm64_hash" "osx_x64_hash" "linux_arm64_hash" "linux_x64_hash"
+
+# Test formula (if brew is available)
+brew install ./build/homebrew/dotnetapidiff.rb
+```
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Chocolatey API Key Invalid**:
+ - Verify the API key in repository secrets
+ - Check if the key has expired or been revoked
+
+2. **Package Approval Required**:
+ - First-time packages on Chocolatey require manual approval
+ - Check the package status on Chocolatey Community
+
+3. **Checksum Mismatch**:
+ - Ensure release assets are fully uploaded before package creation
+ - Verify download URLs are accessible
+
+4. **Homebrew Formula Validation Fails**:
+ - Check formula syntax using `brew audit`
+ - Ensure all download URLs are valid and accessible
+
+### Debugging
+
+1. **Check Workflow Logs**:
+ - GitHub Actions logs show detailed error messages
+ - Look for failed steps in package publishing jobs
+
+2. **Test Locally**:
+ - Run packaging scripts manually with test data
+ - Verify package installation on target platforms
+
+3. **Package Manager Status**:
+ - Check package status on Chocolatey Community
+ - Verify formula syntax and platform support
+
+## Security Considerations
+
+1. **API Key Management**:
+ - Store API keys only in GitHub repository secrets
+ - Regularly rotate API keys
+ - Limit API key permissions to package publishing only
+
+2. **Package Integrity**:
+ - All packages include SHA256 checksums
+ - Binaries are built from tagged releases only
+ - Package contents are validated during build
+
+3. **Automated Publishing**:
+ - Only triggered on tagged releases (v*.*)
+ - Requires successful build and test completion
+ - Includes rollback strategies for failed publications
diff --git a/icons/icon.png b/icons/icon.png
new file mode 100644
index 0000000..b681126
Binary files /dev/null and b/icons/icon.png differ
diff --git a/icons/icon128.png b/icons/icon128.png
new file mode 100644
index 0000000..a114c30
Binary files /dev/null and b/icons/icon128.png differ
diff --git a/icons/icon32.png b/icons/icon32.png
new file mode 100644
index 0000000..b7b20e5
Binary files /dev/null and b/icons/icon32.png differ
diff --git a/icons/icon64.png b/icons/icon64.png
new file mode 100644
index 0000000..c316959
Binary files /dev/null and b/icons/icon64.png differ
diff --git a/packaging/chocolatey/dotnetapidiff.nuspec b/packaging/chocolatey/dotnetapidiff.nuspec
new file mode 100644
index 0000000..dd052c0
--- /dev/null
+++ b/packaging/chocolatey/dotnetapidiff.nuspec
@@ -0,0 +1,67 @@
+
+
+
+ dotnetapidiff
+ $version$
+ https://github.com/jbrinkman/dotnet-api-diff
+ jbrinkman
+ DotNet API Diff
+ Josh Brinkman
+ https://github.com/jbrinkman/dotnet-api-diff
+ https://cdn.statically.io/gh/jbrinkman/dotnet-api-diff/main/icons/icon128.png
+ 2025 Josh Brinkman
+ https://github.com/jbrinkman/dotnet-api-diff/blob/main/LICENSE
+ false
+ https://github.com/jbrinkman/dotnet-api-diff
+ https://github.com/jbrinkman/dotnet-api-diff/blob/main/README.md
+ https://github.com/jbrinkman/dotnet-api-diff/issues
+ dotnet api diff compare assembly compatibility breaking-changes cli tool
+ A command-line tool for comparing .NET assemblies and detecting API differences and breaking changes.
+
+ See release notes at https://github.com/jbrinkman/dotnet-api-diff/releases
+
+
+
+
+
diff --git a/packaging/chocolatey/tools/chocolateyinstall.ps1 b/packaging/chocolatey/tools/chocolateyinstall.ps1
new file mode 100644
index 0000000..9f60ff2
--- /dev/null
+++ b/packaging/chocolatey/tools/chocolateyinstall.ps1
@@ -0,0 +1,56 @@
+$ErrorActionPreference = 'Stop';
+
+$packageName = 'dotnetapidiff'
+$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
+$version = $env:ChocolateyPackageVersion
+
+# Download URLs - these will be updated by the release workflow
+$url64 = "https://github.com/jbrinkman/dotnet-api-diff/releases/download/v$version/dotnet-api-diff-win-x64.zip"
+$urlArm64 = "https://github.com/jbrinkman/dotnet-api-diff/releases/download/v$version/dotnet-api-diff-win-arm64.zip"
+
+# Checksums - these will be updated by the release workflow
+$checksum64 = '$checksum64$'
+$checksumArm64 = '$checksumArm64$'
+
+$packageArgs = @{
+ packageName = $packageName
+ unzipLocation = $toolsDir
+ fileType = 'zip'
+ url64bit = $url64
+ checksum64 = $checksum64
+ checksumType64 = 'sha256'
+}
+
+# Check if we're on ARM64 and the ARM64 version is available
+$isArm64 = $env:PROCESSOR_ARCHITECTURE -eq 'ARM64' -or $env:PROCESSOR_ARCHITEW6432 -eq 'ARM64'
+
+if ($isArm64 -and $urlArm64 -and $checksumArm64 -match '^[a-fA-F0-9]{64}$') {
+ Write-Host "Detected ARM64 architecture, using ARM64 build"
+ $packageArgs.url64bit = $urlArm64
+ $packageArgs.checksum64 = $checksumArm64
+}
+else {
+ Write-Host "Using x64 build (compatible with ARM64 via emulation)"
+}
+
+# Install the package
+Install-ChocolateyZipPackage @packageArgs
+
+# Create a shim for the executable
+$exePath = Join-Path $toolsDir "DotNetApiDiff.exe"
+if (Test-Path $exePath) {
+ # Create a shim with a user-friendly name
+ Install-ChocolateyPath $toolsDir
+
+ # Create batch file for easier command line usage
+ $batchPath = Join-Path $toolsDir "dotnetapidiff.bat"
+ $batchContent = "@echo off`r`n`"$exePath`" %*"
+ [System.IO.File]::WriteAllText($batchPath, $batchContent)
+
+ Write-Host "DotNet API Diff has been installed successfully!"
+ Write-Host "You can now use 'dotnetapidiff' from any command prompt."
+ Write-Host "Type 'dotnetapidiff --help' to get started."
+}
+else {
+ throw "Installation failed: DotNetApiDiff.exe not found in package"
+}
diff --git a/packaging/chocolatey/tools/chocolateyuninstall.ps1 b/packaging/chocolatey/tools/chocolateyuninstall.ps1
new file mode 100644
index 0000000..4652ec5
--- /dev/null
+++ b/packaging/chocolatey/tools/chocolateyuninstall.ps1
@@ -0,0 +1,15 @@
+$ErrorActionPreference = 'Stop';
+
+$packageName = 'dotnetapidiff'
+
+# Remove extracted files
+$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
+Get-ChildItem -Path $toolsDir -Include *.exe, *.dll, *.json, *.xml, *.pdb -File | ForEach-Object { Remove-Item $_.FullName -Force }
+
+# Clean up batch file if it exists
+$batchPath = Join-Path $toolsDir "dotnetapidiff.bat"
+if (Test-Path $batchPath) {
+ Remove-Item $batchPath -Force
+}
+
+Write-Host "DotNet API Diff has been uninstalled successfully!"
diff --git a/packaging/homebrew/dotnetapidiff.rb b/packaging/homebrew/dotnetapidiff.rb
new file mode 100644
index 0000000..dd8719a
--- /dev/null
+++ b/packaging/homebrew/dotnetapidiff.rb
@@ -0,0 +1,28 @@
+class Dotnetapidiff < Formula
+ desc "Command-line tool for comparing .NET assemblies and detecting API differences"
+ homepage "https://github.com/jbrinkman/dotnet-api-diff"
+ version "$version$"
+ license "MIT"
+
+ if OS.mac? && Hardware::CPU.arm?
+ url "https://github.com/jbrinkman/dotnet-api-diff/releases/download/v$version$/dotnet-api-diff-osx-arm64.tar.gz"
+ sha256 "$sha256_osx_arm64$"
+ elsif OS.mac? && Hardware::CPU.intel?
+ url "https://github.com/jbrinkman/dotnet-api-diff/releases/download/v$version$/dotnet-api-diff-osx-x64.tar.gz"
+ sha256 "$sha256_osx_x64$"
+ elsif OS.linux? && Hardware::CPU.arm64?
+ url "https://github.com/jbrinkman/dotnet-api-diff/releases/download/v$version$/dotnet-api-diff-linux-arm64.tar.gz"
+ sha256 "$sha256_linux_arm64$"
+ elsif OS.linux? && Hardware::CPU.intel?
+ url "https://github.com/jbrinkman/dotnet-api-diff/releases/download/v$version$/dotnet-api-diff-linux-x64.tar.gz"
+ sha256 "$sha256_linux_x64$"
+ end
+
+ def install
+ bin.install "DotNetApiDiff" => "dotnetapidiff"
+ end
+
+ test do
+ system "#{bin}/dotnetapidiff", "--version"
+ end
+end
diff --git a/scripts/build-chocolatey.ps1 b/scripts/build-chocolatey.ps1
new file mode 100644
index 0000000..4c7fdff
--- /dev/null
+++ b/scripts/build-chocolatey.ps1
@@ -0,0 +1,93 @@
+#!/usr/bin/env pwsh
+
+param(
+ [Parameter(Mandatory = $true)]
+ [string]$Version,
+
+ [Parameter(Mandatory = $true)]
+ [ValidatePattern('^[a-fA-F0-9]{64}$')]
+ [string]$ChecksumX64,
+
+ [Parameter(Mandatory = $true)]
+ [string]$ChecksumArm64,
+
+ [Parameter(Mandatory = $false)]
+ [string]$ApiKey,
+
+ [Parameter(Mandatory = $false)]
+ [switch]$Publish
+)
+
+$ErrorActionPreference = 'Stop'
+
+Write-Host "Building Chocolatey package for version $Version"
+
+# Paths
+$rootDir = Split-Path -Parent $PSScriptRoot
+$packagingDir = Join-Path $rootDir "packaging/chocolatey"
+$buildDir = Join-Path $rootDir "build/chocolatey"
+$nuspecPath = Join-Path $packagingDir "dotnetapidiff.nuspec"
+$installScriptPath = Join-Path $packagingDir "tools/chocolateyinstall.ps1"
+
+# Create build directory
+if (Test-Path $buildDir) {
+ Remove-Item $buildDir -Recurse -Force
+}
+New-Item -ItemType Directory -Path $buildDir -Force | Out-Null
+
+# Copy package files to build directory
+Copy-Item -Path "$packagingDir/*" -Destination $buildDir -Recurse -Force
+
+# Update version in nuspec
+$nuspecContent = Get-Content $nuspecPath -Raw
+$nuspecContent = $nuspecContent.Replace('$version$', $Version)
+$nuspecContent | Set-Content (Join-Path $buildDir "dotnetapidiff.nuspec")
+
+# Update checksums in install script
+$installScriptContent = Get-Content $installScriptPath -Raw
+$installScriptContent = $installScriptContent -replace '\$checksum64\$', $ChecksumX64
+$installScriptContent = $installScriptContent -replace '\$checksumArm64\$', $ChecksumArm64
+
+$installScriptContent | Set-Content (Join-Path $buildDir "tools/chocolateyinstall.ps1")
+
+# Build package
+Push-Location $buildDir
+try {
+ $nupkgFile = "dotnetapidiff.$Version.nupkg"
+
+ Write-Host "Creating Chocolatey package..."
+ choco pack dotnetapidiff.nuspec
+
+ if (-not (Test-Path $nupkgFile)) {
+ throw "Package creation failed - $nupkgFile not found"
+ }
+
+ Write-Host "Package created successfully: $nupkgFile"
+
+ if ($Publish) {
+ if (-not $ApiKey) {
+ throw "API key is required for publishing"
+ }
+
+ Write-Host "Publishing package to Chocolatey..."
+ choco push $nupkgFile --api-key $ApiKey
+ Write-Host "Package published successfully!"
+ }
+ else {
+ Write-Host "Package built but not published (use -Publish flag to publish)"
+ }
+
+ # Copy package to artifacts directory
+ $artifactsDir = Join-Path $rootDir "artifacts"
+ if (-not (Test-Path $artifactsDir)) {
+ New-Item -ItemType Directory -Path $artifactsDir -Force | Out-Null
+ }
+ Copy-Item $nupkgFile $artifactsDir -Force
+ Write-Host "Package copied to artifacts directory"
+
+}
+finally {
+ Pop-Location
+}
+
+Write-Host "Chocolatey packaging completed successfully!"
diff --git a/scripts/update-homebrew.sh b/scripts/update-homebrew.sh
new file mode 100755
index 0000000..2f0c493
--- /dev/null
+++ b/scripts/update-homebrew.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+set -euo pipefail
+
+# Script to update Homebrew formula with new version and checksums
+
+VERSION="${1:-}"
+SHA256_OSX_ARM64="${2:-}"
+SHA256_OSX_X64="${3:-}"
+SHA256_LINUX_ARM64="${4:-}"
+SHA256_LINUX_X64="${5:-}"
+
+if [[ -z "$VERSION" || -z "$SHA256_OSX_ARM64" || -z "$SHA256_OSX_X64" || -z "$SHA256_LINUX_ARM64" || -z "$SHA256_LINUX_X64" ]]; then
+ echo "Usage: $0 "
+ echo "Example: $0 1.0.0 abc123... def456... ghi789... jkl012..."
+ exit 1
+fi
+if [[ -z "$VERSION" || -z "$SHA256_OSX_ARM64" || -z "$SHA256_OSX_X64" || -z "$SHA256_LINUX_ARM64" || -z "$SHA256_LINUX_X64" ]]; then
+ echo "Usage: $0 "
+ echo "Example: $0 1.0.0 abc123... def456... ghi789... jkl012..."
+ exit 1
+fi
+
+# Validate SHA256 format
+for sha in "$SHA256_OSX_ARM64" "$SHA256_OSX_X64" "$SHA256_LINUX_ARM64" "$SHA256_LINUX_X64"; do
+ if [[ ! "$sha" =~ ^[a-fA-F0-9]{64}$ ]]; then
+ echo "Error: Invalid SHA256 format: $sha"
+ exit 1
+ fi
+done
+
+echo "Updating Homebrew formula for version $VERSION"
+
+# Paths
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+ROOT_DIR="$(dirname "$SCRIPT_DIR")"
+PACKAGING_DIR="$ROOT_DIR/packaging/homebrew"
+BUILD_DIR="$ROOT_DIR/build/homebrew"
+FORMULA_TEMPLATE="$PACKAGING_DIR/dotnetapidiff.rb"
+
+# Create build directory
+mkdir -p "$BUILD_DIR"
+
+# Copy and update formula
+cp "$FORMULA_TEMPLATE" "$BUILD_DIR/dotnetapidiff.rb"
+
+# Update placeholders in the formula (macOS-compatible sed)
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ # macOS sed
+ sed -i '' \
+ -e "s/\\\$version\\\$/$VERSION/g" \
+ -e "s/\\\$sha256_osx_arm64\\\$/$SHA256_OSX_ARM64/g" \
+ -e "s/\\\$sha256_osx_x64\\\$/$SHA256_OSX_X64/g" \
+ -e "s/\\\$sha256_linux_arm64\\\$/$SHA256_LINUX_ARM64/g" \
+ -e "s/\\\$sha256_linux_x64\\\$/$SHA256_LINUX_X64/g" \
+ "$BUILD_DIR/dotnetapidiff.rb"
+else
+ # GNU sed
+ sed -i \
+ -e "s/\\\$version\\\$/$VERSION/g" \
+ -e "s/\\\$sha256_osx_arm64\\\$/$SHA256_OSX_ARM64/g" \
+ -e "s/\\\$sha256_osx_x64\\\$/$SHA256_OSX_X64/g" \
+ -e "s/\\\$sha256_linux_arm64\\\$/$SHA256_LINUX_ARM64/g" \
+ -e "s/\\\$sha256_linux_x64\\\$/$SHA256_LINUX_X64/g" \
+ "$BUILD_DIR/dotnetapidiff.rb"
+fi
+
+echo "Homebrew formula updated successfully!"
+echo "Formula saved to: $BUILD_DIR/dotnetapidiff.rb"
+
+# Copy to artifacts directory
+ARTIFACTS_DIR="$ROOT_DIR/artifacts"
+mkdir -p "$ARTIFACTS_DIR"
+cp "$BUILD_DIR/dotnetapidiff.rb" "$ARTIFACTS_DIR/"
+
+echo "Formula copied to artifacts directory"
+
+# Validate the formula syntax (if brew is available)
+if command -v brew >/dev/null 2>&1; then
+ echo "Validating formula syntax..."
+ if brew audit --formula "$BUILD_DIR/dotnetapidiff.rb"; then
+ echo "Formula validation passed!"
+ else
+ echo "Warning: Formula validation failed"
+ exit 1
+ fi
+else
+ echo "Homebrew not available - skipping formula validation"
+fi
+
+echo "Homebrew formula update completed successfully!"