Skip to content

Multi-Platform Binary Distributions (Windows, Mac, Linux, npm) & Box PHAR Builds#143

Merged
jasdeepkhalsa merged 3 commits intomasterfrom
feature/dbdiff-multi-platform-binaries
Mar 7, 2026
Merged

Multi-Platform Binary Distributions (Windows, Mac, Linux, npm) & Box PHAR Builds#143
jasdeepkhalsa merged 3 commits intomasterfrom
feature/dbdiff-multi-platform-binaries

Conversation

@jasdeepkhalsa
Copy link
Copy Markdown
Member

@jasdeepkhalsa jasdeepkhalsa commented Mar 6, 2026

feat: Multi-platform binary distribution + GHCR registry publishing + v3.0.0 prep

Overview

This PR ships DBDiff as a proper multi-platform CLI tool — pre-built self-contained binaries for 8 platforms, npm packages, GHCR registry images, a Homebrew formula updater, and a unified config file. It also raises the PHP floor to 8.1 and completely rewrites the README.


Distribution — new installation methods

Pre-built binaries (zero dependencies)

PHAR builds now with Box and static self-contained executables built with static-php-cli — PHP 8.3 micro SAPI + PHAR stitched together. No PHP, Composer, or Node required.

Platform Asset name
Linux x64 (glibc) dbdiff-linux-x64
Linux x64 (musl/Alpine) dbdiff-linux-x64-musl
Linux arm64 (glibc) dbdiff-linux-arm64
Linux arm64 (musl) dbdiff-linux-arm64-musl
macOS x64 dbdiff-darwin-x64
macOS arm64 (Apple Silicon) dbdiff-darwin-arm64
Windows x64 dbdiff-win32-x64.exe
Windows arm64 dbdiff-win32-arm64.exe

npm@dbdiff/cli meta-package with 8 optional platform packages. Installs the correct binary automatically.

Docker — new docker/Dockerfile.slim (PHP 8.3 Alpine + PHAR, ~119 MB). Published to GHCR on every release — no secrets required beyond the default GITHUB_TOKEN.

docker pull ghcr.io/dbdiff/dbdiff:latest          # GHCR (free, no secrets needed)
docker run --rm ghcr.io/dbdiff/dbdiff:latest --help

GitHub Actions

release.yml — new complete release pipeline triggered on v* tag push:

build-phar  ──┬── build-binary (matrix × 8 platforms)  ──→  publish (npm + GH Release)
              └── publish-docker (GHCR, slim + full)  [parallel]
  • build-phar — compiles dist/dbdiff.phar via Box, uploads as artifact
  • build-binary — matrix across 8 platform targets; SPC downloads sources, builds micro.sfx, stitches with PHAR
  • publish — creates GitHub Release, uploads all binaries + PHAR, publishes npm packages
  • publish-docker — pushes slim + full images to GHCR; login and push steps have continue-on-error: true with an if: always() summary step showing ✅/⏭️/❌; multi-arch build (linux/amd64 + linux/arm64) via QEMU + buildx; GHA layer caching

tests.yml — PHP matrix minimum bumped 8.08.1


PHP 8.0 dropped — minimum now 8.1

  • composer.json: require.php and config.platform.php bumped from 8.0 to 8.1
  • composer.lock: regenerated content-hash for 8.1 platform override
  • Resolves the humbug/box build-time conflict that was failing CI

Unified config file (dbdiff.yml)

Previously the diff tool only looked for .dbdiff and the migration runner only looked for dbdiff.yml. Now FSGetter.php walks a fallback chain so one file drives both modes:

.dbdiffdbdiff.yml.dbdiff.ymldbdiff.yaml

dbdiff.yml.example restructured: diff section (server1/server2/driver/type) is first-class and uncommented; migration database section follows. Fully backwards-compatible — existing .dbdiff files continue to work.


New scripts

Script Purpose
scripts/release-binaries.sh Builds all 8 platform binaries locally via Podman
scripts/test-release-podman.sh End-to-end local release smoke test
scripts/update-homebrew-formula.sh Updates Homebrew tap formula for a new version
scripts/release.sh Updated to coordinate PHAR + binary + npm + GitHub Release
box.json Box compiler config for PHAR build

README

Complete rewrite:

  • Features section with Supabase link
  • Installation table with "Available on Releases?" column and PHP requirement callout (≥ 8.1 for PHAR/Composer; bundled 8.3 for binaries/Docker/npm)
  • Unified dbdiff.yml File Examples — single file covers both diff and migration modes, with config priority table
  • Docker section with registry pull commands and image variant table
  • Platform compatibility tables for MySQL, PostgreSQL, SQLite, and Dolt

Pre-merge checklist

  • build-phar tested locally (box compile via php:8.3-cli-alpine → passes)
  • Linux x64 binary built and smoke-tested locally (--version returns DBDiff 2.0.0)
  • docker/Dockerfile.slim built locally (119 MB, --version and --help pass)
  • GHCR package visibility set to Public after first release push

Add full distribution pipeline: Box-compiled PHAR → static PHP micro SAPI
binary (via static-php-cli) → npm packages per platform → GitHub Release assets.

PHAR build
- Add box.json (humbug/box config): GZ compression, check-requirements disabled
  so the micro SAPI binary passes Box's PHP_SAPI guard
- Add humbug/box ^3.0 as a dev dependency (v3 required by platform.php: 8.0)
- Remove scripts/build — the old hand-rolled Phar::buildFromDirectory script,
  superseded entirely by box.json + vendor/bin/box compile

npm packages
- Add packages/@dbdiff/cli/                — root shim package (bin/dbdiff.js)
  - musl detection via /proc/version + ldd fallback
  - resolves the correct platform binary via require.resolve at runtime
  - 8 optionalDependencies covering all supported platforms
- Add packages/@dbdiff/cli-{linux,darwin,win32}-{x64,arm64}[-musl]/
  - Correct os/cpu/libc fields for npm's conditional install
  - linux musl variants declare libc: ["musl"]

Static binary pipeline (static-php-cli / SPC)
- Extensions: phar,pdo_mysql,pdo_pgsql,pdo_sqlite,openssl,zlib,mbstring,
              dom,libxml,tokenizer,ctype,json,iconv
- Libraries:  libiconv,libxml2,ncurses,libedit,postgresql,sqlite
- Build mode: --build-micro → buildroot/bin/micro.sfx (stitch: cat micro.sfx phar)
- SPC produces a musl-linked static binary on Linux regardless of host libc,
  so linux-x64 and linux-x64-musl ship the same binary

Scripts
- Add scripts/release-binaries.sh   — local Podman-based builder for all 4 Linux
  targets; arm64 via --platform linux/arm64 (QEMU); musl variants are copies
- Add scripts/test-release-podman.sh — distro smoke-test suite (9 images:
  Ubuntu 20/22/24, Debian 11/12, AlmaLinux 9, Alpine 3.19/3.20/3.21)
- Add scripts/update-homebrew-formula.sh — downloads release assets, computes
  SHA256, stamps version + hashes into homebrew-dbdiff/Formula/dbdiff.rb
- Update scripts/release.sh — aligned to new Box-based PHAR build and updated
  post-release instructions referencing the GA workflow
- Remove scripts/spc-build-alpine.sh — unused reference script (superseded by
  the inline SPC steps in release-binaries.sh and release.yml)

GitHub Actions (.github/workflows/release.yml)
- Fully rewritten workflow: build-phar → build-binary (8-target matrix) → publish
- Binary matrix: native ubuntu runners for linux x64/arm64; macOS runners for
  darwin; Windows runners for win32; musl copies via Alpine container
- Publish job: stamps version into all package.json files, copies binaries,
  publishes to npm with provenance, creates/updates GitHub Release
- Idempotent for re-runs against an already-tagged release:
  - git tag step skipped if tag already exists on origin
  - npm publish steps check registry before publishing (skip if present)
  - softprops/action-gh-release updates release in-place (make_latest: true)

.gitignore
- Ignore built artefacts: dist/, packages/@dbdiff/*/dbdiff,
  packages/@dbdiff/*/dbdiff.exe, packages/@dbdiff/*/node_modules/
…ME overhaul

Distribution
- Add docker/Dockerfile.slim: PHP 8.3 Alpine + PHAR, ~119 MB, locally tested
- Add publish-docker GHA job: pushes slim + full images to Docker Hub and GHCR
  on every release; each login/push step is independent (continue-on-error) so a
  missing Docker Hub secret never blocks GHCR, with an always-runs summary step
- Fix .dockerignore: add exception for dist/dbdiff.phar so Dockerfile.slim can COPY it

PHP minimum floor -> 8.1
- composer.json: require.php and config.platform.php bumped from 8.0 to 8.1
- composer.lock: regenerated content-hash for 8.1 platform override
- .github/workflows/tests.yml: PHP matrix minimum 8.0 -> 8.1

Config file unification
- src/Params/FSGetter.php: auto-detect chain .dbdiff -> dbdiff.yml -> .dbdiff.yml
  -> dbdiff.yaml (backwards-compatible; legacy .dbdiff still works)
- dbdiff.yml.example: restructured so diff section (server1/server2/driver/type)
  is first-class and uncommented; migration section follows; single file covers both modes

README
- Full rewrite: new Installation table with "Available on Releases?" column,
  PHP requirement callout (8.1 for PHAR/Composer; bundled 8.3 for binaries/Docker/npm),
  unified dbdiff.yml File Examples with config priority table, Docker registry
  pull commands and image variant table, Supabase link in Features
Changes:
- release.yml: remove Docker Hub login + push steps; GHCR-only publish
- release.yml: simplify login report and summary steps
- README.md: Docker section updated to GHCR-only pull commands and variant table
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Mar 7, 2026

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