Skip to content

Feature: Distribute swiftpkg through an official Homebrew tap #3

Description

@jordancalhoun

Summary

Publish swiftpkg through an official codecarton/homebrew-tap so macOS users can install and upgrade it with Homebrew:

brew install codecarton/tap/swiftpkg
brew upgrade swiftpkg

Prerequisite

This work depends on #2. Do not publish a Homebrew cask or advertise Homebrew distribution until official releases are Developer ID-signed and notarized.

Recommended distribution model

Use a third-party tap, not homebrew/core:

  • swiftpkg is macOS-only and relies on Apple packaging tools.
  • The project is a Swift implementation of munki-pkg, so core acceptance is additionally less certain for a fork/reimplementation.
  • An official tap is fully under project control and lets users install the CLI immediately.

Ship a versioned, immutable Universal 2 tarball containing the executable rather than install the existing .pkg through Homebrew. A formula should place the binary in Homebrew bin, not run an installer that writes directly to /usr/local/bin.

Release artifact changes

Extend scripts/release.sh after the Universal binary is verified and before checksum generation:

TARBALL="$DIST/swiftpkg-$VERSION-universal.tar.gz"
tar -C "$WORK/products" -czf "$TARBALL" swiftpkg

(cd "$DIST" && shasum -a 256 \
  "$(basename "$PKG")" \
  "$(basename "$TARBALL")" > SHA256SUMS)

Also include $TARBALL when creating or uploading the GitHub Release:

gh release upload "v$VERSION" "$PKG" "$TARBALL" "$DIST/SHA256SUMS" \
  --clobber --repo "$GITHUB_REPOSITORY"

The release should remain immutable: every formula version must point to a stable tag URL and checksum.

Tap setup

Create a public repository named codecarton/homebrew-tap. Add Formula/swiftpkg.rb:

class Swiftpkg < Formula
  desc "Build macOS installer packages from project directories"
  homepage "https://github.com/codecarton/swiftpkg"
  url "https://github.com/codecarton/swiftpkg/releases/download/v0.2.0/swiftpkg-0.2.0-universal.tar.gz"
  sha256 "REPLACE_WITH_RELEASE_TARBALL_SHA256"
  license "GPL-3.0-or-later"

  depends_on macos: :ventura

  def install
    bin.install "swiftpkg"
  end

  test do
    assert_match version.to_s, shell_output("#{bin}/swiftpkg --version")
  end
end

Validate every update before merge:

brew install --build-from-source codecarton/tap/swiftpkg
brew test codecarton/tap/swiftpkg
brew audit --strict codecarton/tap/swiftpkg

Automation pattern

Keep the formula in the tap and update it through a pull request for each signed release. Do not directly overwrite the tap default branch from the release job.

  1. The signed release workflow publishes the tarball and SHA256SUMS.
  2. It sends a repository dispatch to codecarton/homebrew-tap with the release version, immutable tarball URL, and SHA-256.
  3. A workflow in the tap renders the formula, runs brew audit and brew test, then opens a PR using a narrowly-scoped tap-repository token or GitHub App installation token.
  4. Merge the verified PR; users receive updates through normal brew update and brew upgrade.

Example dispatch from the release workflow:

- name: Request Homebrew formula bump
  env:
    GH_TOKEN: ${{ secrets.HOMEBREW_TAP_DISPATCH_TOKEN }}
  run: |
    gh api --method POST repos/codecarton/homebrew-tap/dispatches \
      -f event_type=swiftpkg-release \
      -f client_payload[version]="$VERSION" \
      -f client_payload[sha256]="$(awk "/swiftpkg-$VERSION-universal.tar.gz/ { print \$1 }" dist/SHA256SUMS)"

Example tap workflow trigger and formula rendering step:

on:
  repository_dispatch:
    types: [swiftpkg-release]

jobs:
  bump-swiftpkg:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v5
      - name: Update formula
        env:
          VERSION: ${{ github.event.client_payload.version }}
          SHA256: ${{ github.event.client_payload.sha256 }}
        run: |
          sed -i.bak -E "s|releases/download/v[^"]+/swiftpkg-[^"]+|releases/download/v${VERSION}/swiftpkg-${VERSION}-universal.tar.gz|" Formula/swiftpkg.rb
          sed -i.bak -E "s|sha256 \"[0-9a-f]+\"|sha256 \"${SHA256}\"|" Formula/swiftpkg.rb
      - run: brew audit --strict --formula Formula/swiftpkg.rb
      - run: brew install --build-from-source --formula Formula/swiftpkg.rb
      - uses: peter-evans/create-pull-request@v7
        with:
          title: "swiftpkg ${VERSION}"
          branch: "automation/swiftpkg-${VERSION}"

The exact rendering mechanism may be a small Ruby script instead of sed; use whichever keeps updates deterministic and tested. Keep credentials limited to writing pull requests in codecarton/homebrew-tap, never the main project repository.

Documentation

After the first formula is published, add the Homebrew install and upgrade commands to the main README. Keep the direct signed-installer option documented for Mac management deployments.

Acceptance criteria

  • codecarton/homebrew-tap exposes a verified swiftpkg formula.
  • brew install codecarton/tap/swiftpkg installs the executable into the Homebrew prefix and swiftpkg --version reports the formula version.
  • Tagged signed releases upload a checksummed Universal 2 tarball.
  • Each release creates a tested formula-bump pull request in the tap.
  • The README provides accurate install, upgrade, and uninstall commands.
  • No Homebrew workflow installs an unsigned or unnotarized release artifact.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions