Skip to content

feat: Homebrew formula and Ubuntu/Debian packages with a signed APT repository - #30

Merged
pungoyal merged 4 commits into
mainfrom
worktree-bridge-cse_0186Vxqz1hSzQAwGFwNuypze
Sep 21, 2026
Merged

pungoyal merged 4 commits into
mainfrom
worktree-bridge-cse_0186Vxqz1hSzQAwGFwNuypze

Conversation

@pungoyal

Copy link
Copy Markdown
Owner

What and why

Adds two new ways to install dotsync, each kept up to date by its package manager:

  • Homebrew (macOS and Linux): brew install pungoyal/tap/dotsync. I used a formula rather than a cask. Casks are meant for macOS apps, and they quarantine what they download, so Gatekeeper would block our binary because it isn't notarized. Formulae also work on Linux. GoReleaser has deprecated its brews section, so packaging/homebrew/formula.sh generates the formula from the release's checksums.txt instead. The release workflow then pushes it to the tap named in vars.HOMEBREW_TAP.
  • Ubuntu/Debian: GoReleaser now also builds a .deb (amd64 and arm64). It's checksummed, attested and covered by an SBOM, the same as the archives. The docs workflow builds a signed APT repository from the latest release, served at https://pungoyal.github.io/dotsync/apt/. Before building it, it checks each package's checksum and build provenance. The docs describe a deb822 source that uses Signed-By.

What else changed to make the packages work:

  • Detecting packaged installs (internal/dotsync/packaged.go):
    • dotsync update no longer replaces a binary that Homebrew or apt owns. It tells you the package manager's command instead.
    • The background agent now runs the package's stable path ($(brew --prefix)/bin/dotsync or /usr/bin/dotsync) instead of a copy in ~/.local/bin, so upgrades reach it.
    • doctor warns about a leftover copy in ~/.local/bin.
    • Detection uses dpkg-query, not dpkg's internal database.
  • A dotsync(1) man page, generated from the command table and each command's flags, so it can't drift from dotsync help. The man page ships in the archives, the .deb and the formula.
  • The .deb passes lintian with no warnings, even at pedantic level:
    • it has a Debian changelog built from CHANGELOG.md
    • it includes a copyright file
    • it has a lintian override for the statically linked Go binary
    • it depends on git (>= 1:2.20)
  • Reproducible builds: snapshot versions are now X.Y.Z~snapshot.<commit>, a Debian "native" version like a real release's, so CI lints exactly what a release produces.

Setup needed from a maintainer (both optional; without them releases still ship the .debs)

  1. Create pungoyal/homebrew-tap and set the variable HOMEBREW_TAP=pungoyal/homebrew-tap. Then either install the release GitHub App on the tap, or add secrets.HOMEBREW_TAP_TOKEN.
  2. Generate the APT signing key and store it as secrets.APT_SIGNING_KEY. CONTRIBUTING.md has the steps. The key doesn't expire, on purpose: an expired APT key breaks apt update for every user.

How was this tested?

  • unit tests: TestPackagedAt, TestUpdateDefersToPackageManager, TestManPage
  • docs in website/src/content/docs/ updated (installation, commands, files, uninstall, verifying releases); the site builds with all links valid
  • this change cannot lose a local modification without a backup, or resolve a conflict silently

Checked locally:

  • .deb: lintian at >=pedantic with --fail-on warning passes. Installing and removing with apt works on Ubuntu 22.04 and 24.04 and Debian 12 and 13.
  • APT repository: after adding the signed repository, apt install works, and a wrong key is refused.
  • Formula, with real Homebrew on Linux:
    • brew install works
    • brew test passes; it runs a full init → add → push round trip
    • brew audit --strict and brew style are clean
    • dotsync update defers to brew upgrade
  • goreleaser check, golangci-lint, shellcheck and actionlint all pass.

CI now repeats these checks on every PR: new deb and homebrew (macOS and Linux) jobs, both required by ci ok.

🤖 Generated with Claude Code

pungoyal and others added 3 commits September 21, 2026 13:53
…epository

- GoReleaser builds a lintian-clean .deb (amd64, arm64) with a dotsync(1) man page,
  a Debian changelog and SBOMs; packages are checksummed and attested like the archives.
- The release workflow publishes a Homebrew formula (prebuilt, checksum-pinned archives)
  to the tap in vars.HOMEBREW_TAP, and the docs workflow serves a signed APT repository
  at /apt/ built from the latest release, after verifying checksums and provenance.
- dotsync detects Homebrew and apt installs: `update` defers to the package manager,
  the background agent runs the package's stable path, and doctor flags a stale
  ~/.local/bin copy.
- CI lints the .deb, installs it with apt from a throwaway signed repository on Ubuntu
  22.04/24.04 and Debian 12/13, and installs, tests and audits the formula with Homebrew
  on macOS and Linux.
- The man page is generated from the command table, so it can't drift from `help`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Resolves conflicts with the docs redesign by re-applying the Homebrew/apt
additions to the new pages, and switches the man page to flagSetHook so it
lists flags exactly like the generated docs reference.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…cOS)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pungoyal
pungoyal marked this pull request as ready for review September 21, 2026 14:32
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@pungoyal
pungoyal merged commit 050b843 into main Sep 21, 2026
22 checks passed
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.

1 participant