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!"