Skip to content

Conversation

@jbrinkman
Copy link
Owner

@jbrinkman jbrinkman commented Aug 1, 2025

Overview

This PR implements GitHub Issue #44 by adding comprehensive package manager support to the DotNet API Diff release workflow. Users can now install the tool easily via Chocolatey (Windows) or Homebrew (macOS/Linux).

🎯 Features Implemented

Chocolatey Support (Windows)

  • ✅ Complete .nuspec package specification with rich metadata
  • ✅ PowerShell installation script with ARM64 fallback support
  • ✅ PowerShell uninstallation script with cleanup
  • ✅ User-friendly dotnetapidiff command wrapper
  • ✅ Automated publishing to Chocolatey Community via GitHub Actions

Homebrew Support (macOS/Linux)

  • ✅ Cross-platform formula with automatic architecture detection
  • ✅ Support for macOS and Linux on both Intel and ARM64
  • ✅ Automated formula generation with correct checksums and URLs
  • ✅ SHA256 verification for package integrity

Release Workflow Enhancements

  • ✅ Added checksum calculation step for all release assets
  • ✅ Chocolatey publishing job with Windows runner
  • ✅ Homebrew formula generation job with artifact upload
  • ✅ Conditional execution only on tagged releases (v*.*)
  • ✅ Proper error handling and rollback strategies

🛠️ Developer Tools

Build Scripts

  • scripts/build-chocolatey.ps1: PowerShell script for local package testing and publishing
  • scripts/update-homebrew.sh: Cross-platform shell script for formula generation

Documentation

  • Updated README.md with package manager installation instructions
  • Added docs/package-manager-setup.md comprehensive guide for maintainers
  • Updated .gitignore for build and artifact directories

🚀 User Experience

After merging and the next release, users can install via:

Windows (Chocolatey):

choco install dotnetapidiff

macOS/Linux (Homebrew):

brew install dotnetapidiff

🔧 Technical Details

Package Structure

Chocolatey:

dotnetapidiff/
├── tools/
│   ├── chocolateyinstall.ps1    # Smart installer with ARM64 fallback
│   ├── chocolateyuninstall.ps1  # Clean uninstaller
│   └── dotnetapidiff.bat        # Command wrapper
└── dotnetapidiff.nuspec         # Package metadata

Homebrew:

  • Platform-aware formula with automatic binary selection
  • Support for all architectures: macOS Intel/ARM64, Linux Intel/ARM64
  • Direct installation to bin/dotnetapidiff

Workflow Architecture

  1. Build Job: Creates release assets and calculates checksums
  2. Chocolatey Job: Downloads Windows assets, builds package, publishes to Chocolatey
  3. Homebrew Job: Downloads all Unix assets, generates formula, uploads as artifact

Security & Reliability

  • ✅ SHA256 checksum verification for all packages
  • ✅ Secure API key management via GitHub secrets
  • ✅ ARM64 fallback for Windows installations
  • ✅ Platform detection and automatic binary selection
  • ✅ Comprehensive error handling and logging

🧪 Testing

Local Testing Scripts

# Test Chocolatey package locally
.\scripts\build-chocolatey.ps1 -Version "1.0.0" -ChecksumX64 "abc..." -ChecksumArm64 "def..."
# Test Homebrew formula generation
./scripts/update-homebrew.sh "1.0.0" "sha1" "sha2" "sha3" "sha4"

Package Verification

  • Chocolatey package structure validation
  • Homebrew formula syntax validation (when brew is available)
  • Binary functionality testing

📋 Setup Requirements

For automated publishing, the following repository secret is required:

  • CHOCOLATEY_API_KEY: API key for publishing to Chocolatey Community

See docs/package-manager-setup.md for detailed setup instructions.

📊 Impact

This enhancement significantly improves the user experience by:

  • Reducing installation friction for end users
  • Providing automatic updates through package managers
  • Supporting all major platforms and architectures
  • Maintaining security through checksum verification
  • Following package manager best practices

🔗 Related

Closes #44

📸 Files Changed

  • .github/workflows/release.yml - Enhanced release workflow
  • README.md - Updated installation documentation
  • packaging/chocolatey/ - Complete Chocolatey package structure
  • packaging/homebrew/ - Homebrew formula template
  • scripts/ - Build and deployment scripts
  • docs/package-manager-setup.md - Maintainer documentation
  • .gitignore - Added build directories

Ready for Review 🎉

This PR is ready for review and testing. The implementation follows package manager best practices and includes comprehensive documentation for both users and maintainers.

Summary by CodeRabbit

  • New Features

    • Added automated publishing of releases to Chocolatey (Windows) and Homebrew (macOS/Linux) package managers for simplified installation.
    • Included platform-specific installation instructions for Chocolatey and Homebrew in the README.
    • Provided a comprehensive setup guide for package manager publishing workflows.
  • Chores

    • Enhanced release workflow to compute and expose SHA256 checksums for all platform-specific release archives.
    • Added scripts and configuration files to build, publish, install, and uninstall Chocolatey and Homebrew packages.
    • Updated .gitignore to exclude build and artifacts directories.

Implements GitHub Issue #44 - Add package manager integration to release workflow

## Chocolatey Support (Windows)
- Created .nuspec package specification with comprehensive metadata
- PowerShell installation/uninstallation scripts with ARM64 fallback
- Automated package building and publishing via GitHub Actions
- User-friendly 'dotnetapidiff' command wrapper

## Homebrew Support (macOS/Linux)
- Cross-platform formula with automatic architecture detection
- Support for macOS and Linux on both Intel and ARM64
- Automated formula generation with checksums and URLs
- SHA256 verification for package integrity

## Release Workflow Enhancements
- Added checksum calculation step for all release assets
- Chocolatey publishing job with Windows runner
- Homebrew formula generation job with artifact upload
- Conditional execution only on tagged releases

## Developer Tools
- build-chocolatey.ps1: Script for local package testing and publishing
- update-homebrew.sh: Cross-platform formula generation script
- Comprehensive documentation for maintainer setup

## Documentation Updates
- Updated README.md with package manager installation instructions
- Added package-manager-setup.md guide for maintainers
- Updated .gitignore for build and artifact directories

Users can now install via:
- Windows: choco install dotnetapidiff
- macOS/Linux: brew install dotnetapidiff

Closes #44
@jbrinkman jbrinkman requested a review from Copilot August 1, 2025 19:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds comprehensive package manager support to the DotNet API Diff project, implementing automatic publishing to Chocolatey (Windows) and Homebrew (macOS/Linux) package managers. The implementation includes packaging configurations, build scripts, workflow automation, and comprehensive documentation.

  • Complete Chocolatey package structure with PowerShell installation/uninstallation scripts and automated publishing
  • Homebrew formula template with cross-platform support and automatic architecture detection
  • Enhanced GitHub Actions release workflow with checksum calculation and package publishing jobs

Reviewed Changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
.github/workflows/release.yml Enhanced workflow with checksum calculation and package publishing jobs
scripts/build-chocolatey.ps1 PowerShell script for building and publishing Chocolatey packages
scripts/update-homebrew.sh Shell script for generating Homebrew formulas with checksums
packaging/chocolatey/dotnetapidiff.nuspec Chocolatey package specification with metadata
packaging/chocolatey/tools/chocolateyinstall.ps1 Installation script with ARM64 fallback support
packaging/chocolatey/tools/chocolateyuninstall.ps1 Uninstallation script with cleanup
packaging/homebrew/dotnetapidiff.rb Homebrew formula template with platform detection
docs/package-manager-setup.md Comprehensive setup guide for maintainers
README.md Updated installation instructions with package manager options

@jbrinkman
Copy link
Owner Author

@coderabbitai full review

- Add blank lines around lists in package-manager-setup.md
- Add blank lines around fenced code blocks
- Specify language for fenced code blocks (text for directory structure)
- Add blank lines around fenced code blocks in README.md

Resolves all MD031, MD032, and MD040 violations for consistent Markdown formatting.
@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Caution

Review failed

The head commit changed during the review from d75d81c to 36c73e8.

Walkthrough

This update introduces automated packaging and publishing for Chocolatey (Windows) and Homebrew (macOS/Linux) into the release workflow. It adds new workflow jobs, packaging scripts, metadata files, and documentation to support package creation, checksum calculation, and publishing. The README and supporting docs now include installation and setup instructions for these package managers.

Changes

Cohort / File(s) Change Summary
Release Workflow & Automation
.github/workflows/release.yml, scripts/build-chocolatey.ps1, scripts/update-homebrew.sh
Enhanced release workflow to automate SHA256 checksum calculation, add Chocolatey and Homebrew packaging jobs, and invoke scripts for package creation and publishing.
Chocolatey Packaging
packaging/chocolatey/dotnetapidiff.nuspec, packaging/chocolatey/tools/chocolateyinstall.ps1, packaging/chocolatey/tools/chocolateyuninstall.ps1
Added Chocolatey package specification and install/uninstall scripts to enable automated packaging and installation on Windows.
Homebrew Packaging
packaging/homebrew/dotnetapidiff.rb
Added a Homebrew formula for cross-platform (macOS/Linux) installation of the tool, with architecture and OS detection.
Documentation
docs/package-manager-setup.md, README.md
Added detailed setup guide for package manager automation and updated README with Chocolatey and Homebrew installation instructions.
Build Artifacts & Ignore Rules
.gitignore
Updated .gitignore to exclude build and artifacts directories related to package creation.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant GitHub as GitHub Actions
    participant Choco as Chocolatey
    participant Brew as Homebrew

    Dev->>GitHub: Push tag "vX.Y.Z"
    GitHub->>GitHub: Run build job (calculate checksums)
    GitHub->>GitHub: Run chocolatey job (if Windows)
    GitHub->>Choco: Publish Chocolatey package
    GitHub->>GitHub: Run homebrew job (if macOS/Linux)
    GitHub->>Brew: Update Homebrew formula and upload artifact
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Chocolatey Integration: Package spec, API key setup, workflow step, install/uninstall/test, docs (#44)
Homebrew Integration: Formula, automation, multi-OS test, tap support, docs (#44)
GitHub Workflow Updates: Modify workflow, conditional steps, error handling, verification, docs (#44)
Version Synchronization: Ensure package matches release version (#44)
Installation Instructions: Update README.md with package manager commands (#44)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes detected.

Poem

A rabbit hopped with glee today,
For Homebrew and Choco pave the way!
With checksums tall and scripts anew,
The workflow’s magic—what a view!
Now installs are swift, releases neat,
Package carrots—what a treat!
🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/chocolatey-homebrew-packaging

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This update introduces automated packaging and publishing for Chocolatey (Windows) and Homebrew (macOS/Linux) into the release workflow. It adds new workflow jobs, installation scripts, package specifications, and documentation. The README is updated with package manager installation instructions, and new scripts automate package creation, checksum handling, and formula updates.

Changes

Cohort / File(s) Change Summary
Release Workflow Automation
.github/workflows/release.yml
Adds jobs for automated Chocolatey and Homebrew packaging and publishing, including checksum calculation, artifact handling, and conditional triggers on version tags.
Chocolatey Packaging
packaging/chocolatey/dotnetapidiff.nuspec,
packaging/chocolatey/tools/chocolateyinstall.ps1,
packaging/chocolatey/tools/chocolateyuninstall.ps1,
scripts/build-chocolatey.ps1
Introduces Chocolatey package specification, installation and uninstallation scripts, and a build/publish automation script for Windows releases. Handles architecture detection, checksum validation, and batch wrapper creation.
Homebrew Packaging
packaging/homebrew/dotnetapidiff.rb,
scripts/update-homebrew.sh
Adds a Homebrew formula and an update script to automate version and checksum updates for macOS/Linux releases. Handles platform/architecture selection and formula validation.
Documentation
docs/package-manager-setup.md
New documentation detailing setup, workflow, testing, troubleshooting, and security for Chocolatey and Homebrew package publishing.
User-Facing Instructions
README.md
Updates installation instructions to include Chocolatey and Homebrew usage, separating package manager and script-based installation methods.
Git Ignore Update
.gitignore
Adds build/ and artifacts/ directories to the ignore list to exclude build outputs from version control.

Sequence Diagram(s)

sequenceDiagram
    participant Developer
    participant GitHub Actions
    participant Chocolatey
    participant Homebrew

    Developer->>GitHub Actions: Pushes release tag
    GitHub Actions->>GitHub Actions: Build platform-specific archives
    GitHub Actions->>GitHub Actions: Calculate SHA256 checksums
    GitHub Actions->>Chocolatey: Build and publish Chocolatey package (Windows)
    GitHub Actions->>Homebrew: Update and upload Homebrew formula (macOS/Linux)
    GitHub Actions->>GitHub Actions: Upload artifacts (packages/formula)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Chocolatey integration: package spec, API key, workflow step, test, documentation (#44)
Homebrew integration: formula, automation, testing, documentation (#44)
GitHub workflow: modify release workflow, conditional packaging, error handling, verification, documentation (#44)
Version synchronization between packages and GitHub releases (#44)
Installation instructions updated in README (#44)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Poem

A hop, a skip, a chocolatey leap,
Homebrew and Windows, no more install weep!
With checksums and scripts, release flows anew,
Docs and instructions, all clear for the crew.
From burrow to brew, this rabbit’s delight—
Package managers ready, just install and take flight!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/chocolatey-homebrew-packaging

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (5)
packaging/homebrew/dotnetapidiff.rb (1)

13-13: Fix ARM64 architecture detection.

The condition Hardware::CPU.arm? matches both 32-bit ARM and 64-bit ARM64 architectures, which could result in incorrect package selection for ARM64 systems.

Apply this diff to use specific ARM64 detection:

-  elsif OS.linux? && Hardware::CPU.arm?
+  elsif OS.linux? && Hardware::CPU.arm64?
packaging/chocolatey/tools/chocolateyuninstall.ps1 (1)

5-6: Incorrect uninstall method for extracted package files.

Uninstall-ChocolateyZipPackage is intended for packages installed with Install-ChocolateyZipPackage where the package maintains the zip archive. Since the install script extracts files to the tools directory, you should manually remove the extracted files instead.

Apply this diff to fix the uninstall approach:

-# Remove the shim
-Uninstall-ChocolateyZipPackage $packageName -zipFileName "*.zip"
+# 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 }
packaging/chocolatey/tools/chocolateyinstall.ps1 (1)

27-27: Fix the checksum placeholder validation logic.

The condition $checksumArm64 -ne '$checksumArm64$' will always evaluate to $true when the placeholder is properly replaced during the build process. This check should verify that the placeholder has been replaced with a valid SHA256 hash.

Apply this fix to properly validate the checksum:

-if ($isArm64 -and $urlArm64 -and $checksumArm64 -ne '$checksumArm64$') {
+if ($isArm64 -and $urlArm64 -and $checksumArm64 -match '^[a-fA-F0-9]{64}$') {
scripts/build-chocolatey.ps1 (1)

40-49: Consider more robust template substitution.

The simple string replacement approach could potentially cause issues if the placeholder text appears in unexpected contexts within the files.

For more robust substitution, consider using XML manipulation for the nuspec file:

# Replace only the value inside the <version> tag that is exactly $version$
-$nuspecContent = $nuspecContent.Replace('$version$', $Version)
+$nuspecContent = $nuspecContent -replace '(<version>)\$version\$(</version>)', "`$1$Version`$2"

However, the current approach should work fine given the controlled template format used in this project.

.github/workflows/release.yml (1)

95-116: Eliminate redundant asset downloads by using build job outputs.

The workflow downloads and calculates checksums for release assets twice - once in the build job (lines 55-63) and again in both packaging jobs. This creates unnecessary API calls and downloads.

Use the checksums already calculated in the build job:

-      - name: Get release assets and checksums
-        id: release_info
-        shell: pwsh
-        run: |
-          $version = "${{ github.ref }}" -replace 'refs/tags/v', ''
-          $release = Invoke-RestMethod -Uri "https://api.github.com/repos/${{ github.repository }}/releases/tags/v$version"
-
-          # Get checksums from release assets or calculate them
-          $winX64Asset = $release.assets | Where-Object { $_.name -eq "dotnet-api-diff-win-x64.zip" }
-          $winArm64Asset = $release.assets | Where-Object { $_.name -eq "dotnet-api-diff-win-arm64.zip" }
-
-          # Download assets and calculate checksums
-          Invoke-WebRequest -Uri $winX64Asset.browser_download_url -OutFile "win-x64.zip"
-          Invoke-WebRequest -Uri $winArm64Asset.browser_download_url -OutFile "win-arm64.zip"
-
-          $checksumX64 = (Get-FileHash "win-x64.zip" -Algorithm SHA256).Hash.ToLower()
-          $checksumArm64 = (Get-FileHash "win-arm64.zip" -Algorithm SHA256).Hash.ToLower()
-
-          echo "version=$version" >> $env:GITHUB_OUTPUT
-          echo "checksum_x64=$checksumX64" >> $env:GITHUB_OUTPUT
-          echo "checksum_arm64=$checksumArm64" >> $env:GITHUB_OUTPUT

      - name: Build and publish Chocolatey package
        shell: pwsh
        env:
          CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
        run: |
-          .\scripts\build-chocolatey.ps1 -Version "${{ steps.release_info.outputs.version }}" -ChecksumX64 "${{ steps.release_info.outputs.checksum_x64 }}" -ChecksumArm64 "${{ steps.release_info.outputs.checksum_arm64 }}" -ApiKey "$env:CHOCOLATEY_API_KEY" -Publish
+          $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
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0616b3d and 8ad9c4c.

📒 Files selected for processing (10)
  • .github/workflows/release.yml (2 hunks)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • docs/package-manager-setup.md (1 hunks)
  • packaging/chocolatey/dotnetapidiff.nuspec (1 hunks)
  • packaging/chocolatey/tools/chocolateyinstall.ps1 (1 hunks)
  • packaging/chocolatey/tools/chocolateyuninstall.ps1 (1 hunks)
  • packaging/homebrew/dotnetapidiff.rb (1 hunks)
  • scripts/build-chocolatey.ps1 (1 hunks)
  • scripts/update-homebrew.sh (1 hunks)
🧰 Additional context used
🪛 Brakeman (7.0.2)
packaging/homebrew/dotnetapidiff.rb

[medium] 26-26: Possible command injection
Type: Command Injection
Confidence: Medium
More info: https://brakemanscanner.org/docs/warning_types/command_injection/

(Command Injection)

🪛 actionlint (1.7.7)
.github/workflows/release.yml

57-57: shellcheck reported issue in this script: SC2129:style:1:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:1:83: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:2:87: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:3:90: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:4:94: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:5:86: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:6:90: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:7:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:8:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:9:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:10:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2129:style:17:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:17:28: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:18:46: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:19:42: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:20:50: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:21:46: Double quote to prevent globbing and word splitting

(shellcheck)


162-162: the runner of "actions/upload-artifact@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (16)
.gitignore (1)

98-99: LGTM! Appropriate build artifact exclusions.

The addition of build/ and artifacts/ directories to .gitignore correctly excludes package build artifacts from version control, aligning with the new Chocolatey and Homebrew packaging workflows.

packaging/homebrew/dotnetapidiff.rb (2)

26-26: Static analysis false positive - command injection warning.

The static analysis tool flagged a potential command injection, but this is a false positive. The code uses #{bin}/dotnetapidiff where #{bin} resolves to Homebrew's secure bin directory path, and --version is a string literal, not user input.


1-28: Well-structured Homebrew formula with good practices.

The formula follows Homebrew conventions with appropriate metadata, platform-specific conditionals, and proper installation/testing procedures. The templating approach with placeholders allows for automated updates during the release workflow.

README.md (2)

90-103: Excellent documentation for new package manager support.

The addition of package manager installation instructions is well-structured and user-friendly. The commands correctly reference the package names defined in the packaging specifications, and positioning package managers as the recommended installation method aligns with user expectations.


104-104: Good restructuring of installation options.

Renaming the previous section to "Quick Install Script (Linux/macOS)" maintains clarity while distinguishing it from the new package manager options. This provides users with multiple installation paths based on their preferences.

packaging/chocolatey/tools/chocolateyuninstall.ps1 (2)

8-13: Good manual cleanup of batch wrapper.

The manual cleanup of the batch file is appropriate and handles the case where the install script creates a command wrapper. The path construction and conditional removal are implemented correctly.


1-1: Proper error handling and user feedback.

Setting $ErrorActionPreference = 'Stop' ensures the script fails fast on errors, and the success message provides good user feedback. These are Chocolatey scripting best practices.

Also applies to: 15-15

packaging/chocolatey/dotnetapidiff.nuspec (1)

1-67: Comprehensive and well-structured Chocolatey package specification.

The nuspec file follows Chocolatey best practices with:

  • Complete metadata including all recommended fields
  • Detailed description with features, use cases, and usage examples
  • Consistent GitHub repository references
  • Appropriate file inclusion pattern for the tools directory
  • Professional presentation suitable for the Chocolatey community gallery
packaging/chocolatey/tools/chocolateyinstall.ps1 (2)

1-6: LGTM! Well-structured installation script.

The script demonstrates good practices:

  • Proper error handling with $ErrorActionPreference = 'Stop'
  • Clear variable organization and parameter setup for Chocolatey
  • Comprehensive post-installation validation and user-friendly command wrapper creation
  • Informative user messaging

Also applies to: 15-23, 36-56


24-34: Good ARM64 detection and fallback logic.

The architecture detection logic properly handles both PROCESSOR_ARCHITECTURE and PROCESSOR_ARCHITEW6432 environment variables, with appropriate fallback to x64 builds that work via emulation on ARM64 systems.

scripts/update-homebrew.sh (3)

1-17: Excellent parameter validation and error handling.

The script demonstrates best practices with:

  • Strict error handling using set -euo pipefail
  • Comprehensive parameter validation with clear usage instructions
  • Proper exit codes for error conditions

34-53: Well-handled cross-platform sed compatibility.

The OS-specific handling for macOS vs GNU sed is necessary and correctly implemented. The placeholder substitution logic properly escapes the dollar signs to match the template format.


65-76: Good formula validation approach.

The conditional brew audit validation provides good quality assurance when Homebrew is available, while gracefully skipping when not present. This ensures the generated formula follows Homebrew standards.

scripts/build-chocolatey.ps1 (1)

1-22: Well-structured build and publishing script.

The script demonstrates excellent practices:

  • Comprehensive parameter validation with mandatory/optional parameters
  • Clean build directory management
  • Secure API key handling through environment variables
  • Proper error handling and resource cleanup with try/finally
  • Artifact management for CI/CD integration

Also applies to: 24-38, 51-91

docs/package-manager-setup.md (1)

1-199: Comprehensive and well-structured documentation.

This documentation excellently covers all aspects of the package manager setup:

Strengths:

  • Clear prerequisites and setup instructions for both package managers
  • Detailed workflow explanations that align with the implementation
  • Practical testing and troubleshooting guidance
  • Important security considerations for API key management
  • Both automated and manual procedures covered

Minor suggestions:

  • Consider adding version compatibility information
  • Could benefit from expected timeline information for Chocolatey package approval
.github/workflows/release.yml (1)

77-80: Well-structured conditional job execution.

The conditional execution using if: startsWith(github.ref, 'refs/tags/v') properly ensures packaging jobs only run on tagged releases, which is the correct approach for automated package publishing.

Also applies to: 124-127

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (9)
packaging/chocolatey/dotnetapidiff.nuspec (1)

11-11: Missing icon.png referenced by nuspec's <iconUrl>.

The dotnetapidiff.nuspec specifies an iconUrl pointing to icon.png on the main branch, but no icon.png file exists in the repository. You should either add the icon file at the expected path or update the URL to reference an existing image.

packaging/chocolatey/tools/chocolateyuninstall.ps1 (1)

5-6: Incorrect usage of Uninstall-ChocolateyZipPackage function.

The Uninstall-ChocolateyZipPackage function is for packages installed using Install-ChocolateyZipPackage, but since the install script extracts files to the tools directory, you should manually remove the extracted files instead.

Consider this approach:

-# Remove the shim
-Uninstall-ChocolateyZipPackage $packageName -zipFileName "*.zip"
+# 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 }
packaging/homebrew/dotnetapidiff.rb (1)

13-13: Use more specific ARM64 detection.

The condition Hardware::CPU.arm? will match both ARM and ARM64 architectures. For ARM64 specifically, use Hardware::CPU.arm64? for more precise detection.

-  elsif OS.linux? && Hardware::CPU.arm?
+  elsif OS.linux? && Hardware::CPU.arm64?
scripts/build-chocolatey.ps1 (1)

40-49: Improve template substitution robustness

Using simple string replacement for template substitution can be error-prone if the placeholder appears in unexpected contexts or if the replacement values contain special characters.

Consider using more robust templating or ensuring the placeholders are unique enough to avoid accidental replacements:

# Update version in nuspec
$nuspecContent = Get-Content $nuspecPath -Raw
-$nuspecContent = $nuspecContent.Replace('$version$', $Version)
+$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 = $installScriptContent -replace '\$checksum64\$', $ChecksumX64
+$installScriptContent = $installScriptContent -replace '\$checksumArm64\$', $ChecksumArm64
packaging/chocolatey/tools/chocolateyinstall.ps1 (1)

24-34: Fix checksum validation logic

The condition $checksumArm64 -ne '$checksumArm64$' will always be true when the checksum is properly substituted during build. This check should verify if the checksum has been replaced from the placeholder.

Apply this fix to properly validate the checksum format:

-if ($isArm64 -and $urlArm64 -and $checksumArm64 -ne '$checksumArm64$') {
+if ($isArm64 -and $urlArm64 -and $checksumArm64 -match '^[a-fA-F0-9]{64}$') {
.github/workflows/release.yml (4)

10-12: Add job outputs to share checksums with packaging jobs

The build job calculates checksums but doesn't expose them as outputs for other jobs to use.

Add outputs to the build job:

  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

95-122: Eliminate redundant asset downloads in Chocolatey job

The workflow downloads release assets twice - once in the build job and again in the Chocolatey job. Use outputs from the build job instead.

Replace the entire step with a simplified version using build job outputs:

-      - name: Get release assets and checksums
-        id: release_info
+      - name: Set version from tag
+        id: version
         shell: pwsh
         run: |
           $version = "${{ github.ref }}" -replace 'refs/tags/v', ''
-          $release = Invoke-RestMethod -Uri "https://api.github.com/repos/${{ github.repository }}/releases/tags/v$version"
-
-          # Get checksums from release assets or calculate them
-          $winX64Asset = $release.assets | Where-Object { $_.name -eq "dotnet-api-diff-win-x64.zip" }
-          $winArm64Asset = $release.assets | Where-Object { $_.name -eq "dotnet-api-diff-win-arm64.zip" }
-
-          # Download assets and calculate checksums
-          Invoke-WebRequest -Uri $winX64Asset.browser_download_url -OutFile "win-x64.zip"
-          Invoke-WebRequest -Uri $winArm64Asset.browser_download_url -OutFile "win-arm64.zip"
-
-          $checksumX64 = (Get-FileHash "win-x64.zip" -Algorithm SHA256).Hash.ToLower()
-          $checksumArm64 = (Get-FileHash "win-arm64.zip" -Algorithm SHA256).Hash.ToLower()
-
           echo "version=$version" >> $env:GITHUB_OUTPUT
-          echo "checksum_x64=$checksumX64" >> $env:GITHUB_OUTPUT
-          echo "checksum_arm64=$checksumArm64" >> $env:GITHUB_OUTPUT

       - name: Build and publish Chocolatey package
         shell: pwsh
         env:
           CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
         run: |
-          .\scripts\build-chocolatey.ps1 -Version "${{ steps.release_info.outputs.version }}" -ChecksumX64 "${{ steps.release_info.outputs.checksum_x64 }}" -ChecksumArm64 "${{ steps.release_info.outputs.checksum_arm64 }}" -ApiKey "$env:CHOCOLATEY_API_KEY" -Publish
+          .\scripts\build-chocolatey.ps1 -Version "${{ steps.version.outputs.version }}" -ChecksumX64 "${{ needs.build.outputs.win_x64_sha256 }}" -ChecksumArm64 "${{ needs.build.outputs.win_arm64_sha256 }}" -ApiKey "$env:CHOCOLATEY_API_KEY" -Publish

132-159: Eliminate redundant asset downloads in Homebrew job and fix shell quoting

The Homebrew job also downloads assets unnecessarily and has shell quoting issues flagged by static analysis.

Use build job outputs and fix quoting:

       - name: Get release assets and checksums
         id: release_info
         run: |
           VERSION=${GITHUB_REF#refs/tags/v}
-
-          # Get release information
-          RELEASE_JSON=$(curl -s "https://api.github.com/repos/${{ github.repository }}/releases/tags/v$VERSION")
-
-          # Download assets and calculate checksums
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-osx-arm64.tar.gz") | .browser_download_url') -O osx-arm64.tar.gz
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-osx-x64.tar.gz") | .browser_download_url') -O osx-x64.tar.gz
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-linux-arm64.tar.gz") | .browser_download_url') -O linux-arm64.tar.gz
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-linux-x64.tar.gz") | .browser_download_url') -O linux-x64.tar.gz
-
-          OSX_ARM64_SHA256=$(sha256sum osx-arm64.tar.gz | cut -d' ' -f1)
-          OSX_X64_SHA256=$(sha256sum osx-x64.tar.gz | cut -d' ' -f1)
-          LINUX_ARM64_SHA256=$(sha256sum linux-arm64.tar.gz | cut -d' ' -f1)
-          LINUX_X64_SHA256=$(sha256sum linux-x64.tar.gz | cut -d' ' -f1)
-
-          echo "version=$VERSION" >> $GITHUB_OUTPUT
-          echo "osx_arm64_sha256=$OSX_ARM64_SHA256" >> $GITHUB_OUTPUT
-          echo "osx_x64_sha256=$OSX_X64_SHA256" >> $GITHUB_OUTPUT
-          echo "linux_arm64_sha256=$LINUX_ARM64_SHA256" >> $GITHUB_OUTPUT
-          echo "linux_x64_sha256=$LINUX_X64_SHA256" >> $GITHUB_OUTPUT
+          echo "version=$VERSION" >> "$GITHUB_OUTPUT"

       - name: Update Homebrew formula
         run: |
-          ./scripts/update-homebrew.sh "${{ steps.release_info.outputs.version }}" "${{ steps.release_info.outputs.osx_arm64_sha256 }}" "${{ steps.release_info.outputs.osx_x64_sha256 }}" "${{ steps.release_info.outputs.linux_arm64_sha256 }}" "${{ steps.release_info.outputs.linux_x64_sha256 }}"
+          ./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 }}"

162-162: Update to latest upload-artifact action version

The actions/upload-artifact@v3 action version is outdated and may not work on current GitHub Actions runners.

Update to the latest version:

-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0616b3d and 9b73cca.

⛔ Files ignored due to path filters (4)
  • icons/icon.png is excluded by !**/*.png
  • icons/icon128.png is excluded by !**/*.png
  • icons/icon32.png is excluded by !**/*.png
  • icons/icon64.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • .github/workflows/release.yml (2 hunks)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • docs/package-manager-setup.md (1 hunks)
  • packaging/chocolatey/dotnetapidiff.nuspec (1 hunks)
  • packaging/chocolatey/tools/chocolateyinstall.ps1 (1 hunks)
  • packaging/chocolatey/tools/chocolateyuninstall.ps1 (1 hunks)
  • packaging/homebrew/dotnetapidiff.rb (1 hunks)
  • scripts/build-chocolatey.ps1 (1 hunks)
  • scripts/update-homebrew.sh (1 hunks)
🧰 Additional context used
🪛 Brakeman (7.0.2)
packaging/homebrew/dotnetapidiff.rb

[medium] 26-26: Possible command injection
Type: Command Injection
Confidence: Medium
More info: https://brakemanscanner.org/docs/warning_types/command_injection/

(Command Injection)

🪛 actionlint (1.7.7)
.github/workflows/release.yml

57-57: shellcheck reported issue in this script: SC2129:style:1:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:1:83: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:2:87: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:3:90: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:4:94: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:5:86: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:6:90: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:7:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:8:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:9:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:10:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2129:style:17:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:17:28: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:18:46: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:19:42: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:20:50: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:21:46: Double quote to prevent globbing and word splitting

(shellcheck)


162-162: the runner of "actions/upload-artifact@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (14)
.gitignore (1)

97-99: LGTM!

The addition of build/ and artifacts/ directories to the gitignore is appropriate for the new packaging workflow. These directories will store temporary build outputs and packaging artifacts that shouldn't be committed to the repository.

packaging/chocolatey/dotnetapidiff.nuspec (1)

1-67: Well-structured Chocolatey package specification.

The nuspec file is comprehensive and follows Chocolatey packaging best practices. The metadata is complete, description is detailed and informative, and the file specifications are correct for including the tools directory.

README.md (1)

90-104: Excellent addition of package manager installation instructions.

The new section provides clear, user-friendly installation commands for both Chocolatey and Homebrew. The placement and formatting are consistent with the existing documentation structure, making it easy for users to discover these recommended installation methods.

packaging/chocolatey/tools/chocolateyuninstall.ps1 (1)

8-13: Good cleanup of batch file.

The logic to remove the batch file wrapper is correct and handles the case where the file might not exist.

packaging/homebrew/dotnetapidiff.rb (2)

25-27: Standard Homebrew test pattern - static analysis false positive.

The static analysis tool flagged this as potential command injection, but this is a false positive. This follows the standard Homebrew formula testing pattern using system with properly quoted arguments.


1-28: Well-structured Homebrew formula.

The formula follows Homebrew conventions correctly with appropriate metadata, platform detection, installation logic, and testing. The placeholder variables will be replaced during the automated build process.

scripts/build-chocolatey.ps1 (2)

1-18: LGTM: Well-structured parameter definitions

The parameter definitions are clear and follow PowerShell best practices with proper mandatory/optional designations.


52-89: LGTM: Robust package building with proper error handling

The script includes proper error handling, package validation, conditional publishing logic, and artifact management. The try/finally block ensures proper cleanup.

scripts/update-homebrew.sh (3)

1-17: LGTM: Excellent error handling and parameter validation

The script uses proper bash error handling with set -euo pipefail and includes comprehensive parameter validation with helpful usage examples.


34-53: LGTM: Platform-aware sed usage

The script correctly handles the differences between macOS and GNU sed for in-place editing, which is essential for cross-platform compatibility.


65-76: LGTM: Conditional validation with proper error handling

The optional brew validation is well-implemented, only running when brew is available and properly exiting on validation failure.

packaging/chocolatey/tools/chocolateyinstall.ps1 (2)

1-22: LGTM: Standard Chocolatey installation setup

The script follows Chocolatey conventions with proper error handling, package arguments, and checksum configuration.


36-56: LGTM: Proper post-installation setup

The script correctly creates the executable shim, adds to PATH, creates a user-friendly batch wrapper, and validates the installation with appropriate error handling.

docs/package-manager-setup.md (1)

1-200: LGTM: Comprehensive and well-structured documentation

This documentation provides excellent coverage of the package manager setup workflow, including:

  • Clear prerequisites and setup instructions
  • Detailed workflow explanations for both Chocolatey and Homebrew
  • Practical testing and troubleshooting sections
  • Important security considerations
  • Manual testing commands for maintainers

The guide will be invaluable for both users and maintainers.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (9)
packaging/chocolatey/tools/chocolateyuninstall.ps1 (1)

5-6: Fix incorrect uninstall function usage.

The Uninstall-ChocolateyZipPackage function is intended for packages that automatically create shims. Based on the install script pattern, you should manually remove the extracted files instead.

Apply this fix to properly clean up extracted files:

-# Remove the shim
-Uninstall-ChocolateyZipPackage $packageName -zipFileName "*.zip"
+# Remove extracted files
+$extractedFiles = @('DotNetApiDiff.exe', 'DotNetApiDiff.dll', 'DotNetApiDiff.runtimeconfig.json', '*.pdb')
+foreach ($pattern in $extractedFiles) {
+    Get-ChildItem -Path $toolsDir -Filter $pattern -File | Remove-Item -Force -ErrorAction SilentlyContinue
+}
packaging/homebrew/dotnetapidiff.rb (1)

13-13: Fix ARM architecture detection for Linux.

The condition Hardware::CPU.arm? matches both ARM and ARM64 architectures. For ARM64 specifically on Linux, use the more precise condition.

Apply this fix:

-  elsif OS.linux? && Hardware::CPU.arm?
+  elsif OS.linux? && Hardware::CPU.arm64?
packaging/chocolatey/dotnetapidiff.nuspec (1)

11-11: Missing icon file referenced in iconUrl.

The iconUrl points to icon.png in the main branch, but this file doesn't exist in the repository. This will result in a broken image link in the Chocolatey package listing.

#!/bin/bash
# Verify if icon.png exists in the repository
if [ -f "icon.png" ]; then
    echo "✓ icon.png exists"
    ls -la icon.png
else
    echo "✗ icon.png missing - add the file or update the iconUrl to point to an existing image"
fi
scripts/build-chocolatey.ps1 (1)

42-42: Use more robust template substitution.

Simple string replacement can be error-prone if placeholders appear in unexpected contexts.

Apply the previously suggested regex-based approach:

-$nuspecContent = $nuspecContent.Replace('$version$', $Version)
+$nuspecContent = $nuspecContent -replace '(<version>)\$version\$(</version>)', "`$1$Version`$2"
packaging/chocolatey/tools/chocolateyinstall.ps1 (1)

27-27: Fix the checksum placeholder validation.

The condition will always be true when the checksum is properly substituted. The check should verify if the placeholder has been replaced.

Apply the previously suggested fix:

-if ($isArm64 -and $urlArm64 -and $checksumArm64 -ne '$checksumArm64$') {
+if ($isArm64 -and $urlArm64 -and $checksumArm64 -match '^[a-fA-F0-9]{64}$') {
.github/workflows/release.yml (4)

55-63: Add job outputs and fix shell quoting issues.

The build job calculates checksums but doesn't expose them as outputs, and has shell quoting issues flagged by static analysis.

Add outputs to the build job and fix quoting:

  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

      - name: Calculate checksums
        id: checksums
        run: |
-          echo "win_x64_sha256=$(sha256sum dotnet-api-diff-win-x64.zip | cut -d' ' -f1)" >> $GITHUB_OUTPUT
-          echo "win_arm64_sha256=$(sha256sum dotnet-api-diff-win-arm64.zip | cut -d' ' -f1)" >> $GITHUB_OUTPUT
-          echo "linux_x64_sha256=$(sha256sum dotnet-api-diff-linux-x64.tar.gz | cut -d' ' -f1)" >> $GITHUB_OUTPUT
-          echo "linux_arm64_sha256=$(sha256sum dotnet-api-diff-linux-arm64.tar.gz | cut -d' ' -f1)" >> $GITHUB_OUTPUT
-          echo "osx_x64_sha256=$(sha256sum dotnet-api-diff-osx-x64.tar.gz | cut -d' ' -f1)" >> $GITHUB_OUTPUT
-          echo "osx_arm64_sha256=$(sha256sum dotnet-api-diff-osx-arm64.tar.gz | cut -d' ' -f1)" >> $GITHUB_OUTPUT
+          {
+            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"

95-122: Eliminate redundant asset downloads.

The Chocolatey job downloads and calculates checksums that were already computed in the build job.

Use build job outputs instead:

-      - name: Get release assets and checksums
-        id: release_info
-        shell: pwsh
-        run: |
-          $version = "${{ github.ref }}" -replace 'refs/tags/v', ''
-          $release = Invoke-RestMethod -Uri "https://api.github.com/repos/${{ github.repository }}/releases/tags/v$version"
-
-          # Get checksums from release assets or calculate them
-          $winX64Asset = $release.assets | Where-Object { $_.name -eq "dotnet-api-diff-win-x64.zip" }
-          $winArm64Asset = $release.assets | Where-Object { $_.name -eq "dotnet-api-diff-win-arm64.zip" }
-
-          # Download assets and calculate checksums
-          Invoke-WebRequest -Uri $winX64Asset.browser_download_url -OutFile "win-x64.zip"
-          Invoke-WebRequest -Uri $winArm64Asset.browser_download_url -OutFile "win-arm64.zip"
-
-          $checksumX64 = (Get-FileHash "win-x64.zip" -Algorithm SHA256).Hash.ToLower()
-          $checksumArm64 = (Get-FileHash "win-arm64.zip" -Algorithm SHA256).Hash.ToLower()
-
-          echo "version=$version" >> $env:GITHUB_OUTPUT
-          echo "checksum_x64=$checksumX64" >> $env:GITHUB_OUTPUT
-          echo "checksum_arm64=$checksumArm64" >> $env:GITHUB_OUTPUT

      - name: Build and publish Chocolatey package
        shell: pwsh
        env:
          CHOCOLATEY_API_KEY: ${{ secrets.CHOCOLATEY_API_KEY }}
        run: |
-          .\scripts\build-chocolatey.ps1 -Version "${{ steps.release_info.outputs.version }}" -ChecksumX64 "${{ steps.release_info.outputs.checksum_x64 }}" -ChecksumArm64 "${{ steps.release_info.outputs.checksum_arm64 }}" -ApiKey "$env:CHOCOLATEY_API_KEY" -Publish
+          $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

132-159: Apply similar optimization to Homebrew job and fix shell quoting.

The Homebrew job also downloads assets unnecessarily and has shell quoting issues.

Use build job outputs and fix quoting:

      - name: Get release assets and checksums
        id: release_info
        run: |
          VERSION=${GITHUB_REF#refs/tags/v}
-
-          # Get release information
-          RELEASE_JSON=$(curl -s "https://api.github.com/repos/${{ github.repository }}/releases/tags/v$VERSION")
-
-          # Download assets and calculate checksums
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-osx-arm64.tar.gz") | .browser_download_url') -O osx-arm64.tar.gz
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-osx-x64.tar.gz") | .browser_download_url') -O osx-x64.tar.gz
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-linux-arm64.tar.gz") | .browser_download_url') -O linux-arm64.tar.gz
-          wget -q $(echo "$RELEASE_JSON" | jq -r '.assets[] | select(.name=="dotnet-api-diff-linux-x64.tar.gz") | .browser_download_url') -O linux-x64.tar.gz
-
-          OSX_ARM64_SHA256=$(sha256sum osx-arm64.tar.gz | cut -d' ' -f1)
-          OSX_X64_SHA256=$(sha256sum osx-x64.tar.gz | cut -d' ' -f1)
-          LINUX_ARM64_SHA256=$(sha256sum linux-arm64.tar.gz | cut -d' ' -f1)
-          LINUX_X64_SHA256=$(sha256sum linux-x64.tar.gz | cut -d' ' -f1)
-
-          echo "version=$VERSION" >> $GITHUB_OUTPUT
-          echo "osx_arm64_sha256=$OSX_ARM64_SHA256" >> $GITHUB_OUTPUT
-          echo "osx_x64_sha256=$OSX_X64_SHA256" >> $GITHUB_OUTPUT
-          echo "linux_arm64_sha256=$LINUX_ARM64_SHA256" >> $GITHUB_OUTPUT
-          echo "linux_x64_sha256=$LINUX_X64_SHA256" >> $GITHUB_OUTPUT
+          echo "version=$VERSION" >> "$GITHUB_OUTPUT"

      - name: Update Homebrew formula
        run: |
-          ./scripts/update-homebrew.sh "${{ steps.release_info.outputs.version }}" "${{ steps.release_info.outputs.osx_arm64_sha256 }}" "${{ steps.release_info.outputs.osx_x64_sha256 }}" "${{ steps.release_info.outputs.linux_arm64_sha256 }}" "${{ steps.release_info.outputs.linux_x64_sha256 }}"
+          ./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 }}"

162-162: Update to latest upload-artifact action version.

The actions/upload-artifact@v3 is outdated and may not work on current runners.

-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0616b3d and 9b73cca.

⛔ Files ignored due to path filters (4)
  • icons/icon.png is excluded by !**/*.png
  • icons/icon128.png is excluded by !**/*.png
  • icons/icon32.png is excluded by !**/*.png
  • icons/icon64.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • .github/workflows/release.yml (2 hunks)
  • .gitignore (1 hunks)
  • README.md (1 hunks)
  • docs/package-manager-setup.md (1 hunks)
  • packaging/chocolatey/dotnetapidiff.nuspec (1 hunks)
  • packaging/chocolatey/tools/chocolateyinstall.ps1 (1 hunks)
  • packaging/chocolatey/tools/chocolateyuninstall.ps1 (1 hunks)
  • packaging/homebrew/dotnetapidiff.rb (1 hunks)
  • scripts/build-chocolatey.ps1 (1 hunks)
  • scripts/update-homebrew.sh (1 hunks)
🧰 Additional context used
🪛 Brakeman (7.0.2)
packaging/homebrew/dotnetapidiff.rb

[medium] 26-26: Possible command injection
Type: Command Injection
Confidence: Medium
More info: https://brakemanscanner.org/docs/warning_types/command_injection/

(Command Injection)

🪛 actionlint (1.7.7)
.github/workflows/release.yml

57-57: shellcheck reported issue in this script: SC2129:style:1:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:1:83: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:2:87: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:3:90: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:4:94: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:5:86: Double quote to prevent globbing and word splitting

(shellcheck)


57-57: shellcheck reported issue in this script: SC2086:info:6:90: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:7:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:8:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:9:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2046:warning:10:9: Quote this to prevent word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2129:style:17:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:17:28: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:18:46: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:19:42: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:20:50: Double quote to prevent globbing and word splitting

(shellcheck)


134-134: shellcheck reported issue in this script: SC2086:info:21:46: Double quote to prevent globbing and word splitting

(shellcheck)


162-162: the runner of "actions/upload-artifact@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

🔇 Additional comments (15)
.gitignore (1)

97-99: LGTM! Proper exclusion of build artifacts.

The addition of build/ and artifacts/ directories with clear commenting is appropriate for the new packaging workflow. This prevents accidental commit of build outputs from the Chocolatey and Homebrew packaging scripts.

README.md (1)

90-103: LGTM! Clear installation instructions for new package managers.

The addition of package manager installation instructions is well-structured and provides clear, platform-specific guidance. The commands align with the package specifications defined in the Chocolatey and Homebrew packaging files.

packaging/chocolatey/tools/chocolateyuninstall.ps1 (1)

8-13: LGTM! Proper batch file cleanup.

The manual cleanup of the batch file wrapper is implemented correctly with proper existence checking and error handling.

packaging/homebrew/dotnetapidiff.rb (2)

25-27: Static analysis false positive - test block is secure.

The static analysis tool flagged potential command injection, but this is a false positive. The test uses system() with a fixed binary path from #{bin} and a literal --version argument, which is safe.


1-28: Well-structured Homebrew formula with proper platform detection.

The formula correctly handles multiple OS/architecture combinations and follows Homebrew conventions. The installation and test methods are implemented appropriately.

packaging/chocolatey/dotnetapidiff.nuspec (1)

1-67: Well-structured Chocolatey package specification.

The nuspec file contains comprehensive metadata, detailed description, and proper file inclusion patterns. The package structure follows Chocolatey best practices.

scripts/build-chocolatey.ps1 (1)

65-73: LGTM! Well-structured publishing logic.

The conditional publishing with proper API key validation and informative messages is well implemented.

scripts/update-homebrew.sh (3)

3-3: LGTM! Excellent error handling setup.

The set -euo pipefail provides robust error handling for the script.


35-53: LGTM! Platform-specific sed handling is well implemented.

The conditional logic for macOS vs GNU sed differences ensures cross-platform compatibility.


66-76: Good optional validation approach.

The conditional brew validation with appropriate fallback messaging is well designed.

packaging/chocolatey/tools/chocolateyinstall.ps1 (3)

25-25: LGTM! Comprehensive ARM64 detection.

The architecture detection handles both PROCESSOR_ARCHITECTURE and PROCESSOR_ARCHITEW6432 variables correctly.


45-48: Good batch wrapper implementation.

The batch file creation provides a user-friendly command-line interface for the tool.


54-56: Excellent error handling for missing executable.

The validation ensures installation integrity by checking for the expected executable.

docs/package-manager-setup.md (2)

1-200: Excellent comprehensive documentation.

This documentation thoroughly covers all aspects of package manager setup, including prerequisites, workflows, testing, troubleshooting, and security considerations. The structure is logical and the instructions are clear and actionable.


184-199: Strong security considerations section.

The security guidelines cover API key management, package integrity, and automated publishing controls effectively.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

Note

Unit test generation is an Early Access feature. Expect some limitations and changes as we gather feedback and continue to improve it.


Generating unit tests... This may take up to 20 minutes.

- Fix Chocolatey uninstall script to properly remove extracted files
- Fix ARM64 checksum validation logic with regex pattern matching
- Fix Homebrew ARM architecture detection to use arm64 specifically
- Optimize GitHub Actions workflow to eliminate redundant downloads
- Update upload-artifact action to v4 for compatibility
- Remove non-existent iconUrl from Chocolatey package spec

Addresses automated code review feedback for PR #47
- Add iconUrl pointing to icons/icon128.png via Statically.io CDN
- Provides proper icon display for Chocolatey package
- Addresses missing icon issue from code review feedback
@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

UTG Post-Process Complete

No new issues were detected in the generated code and all check runs have completed. The unit test generation process has completed successfully.

@coderabbitai
Copy link

coderabbitai bot commented Aug 4, 2025

Creating a PR to put the unit tests in...

The changes have been created in this pull request: View PR

@jbrinkman jbrinkman merged commit 2bf1940 into main Aug 4, 2025
8 checks passed
jbrinkman added a commit that referenced this pull request Aug 4, 2025
- Fix Chocolatey uninstall script to properly remove extracted files
- Fix ARM64 checksum validation logic with regex pattern matching
- Fix Homebrew ARM architecture detection to use arm64 specifically
- Optimize GitHub Actions workflow to eliminate redundant downloads
- Update upload-artifact action to v4 for compatibility
- Remove non-existent iconUrl from Chocolatey package spec

Addresses automated code review feedback for PR #47
@jbrinkman jbrinkman deleted the feature/chocolatey-homebrew-packaging branch August 4, 2025 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Chocolatey and Homebrew packaging to release workflow

2 participants