Skip to content

feat(pkg): add Composer (PHP) registry (#719)#1457

Open
midsonlajeanty wants to merge 2 commits into
evilmartians:masterfrom
midsonlajeanty:master
Open

feat(pkg): add Composer (PHP) registry (#719)#1457
midsonlajeanty wants to merge 2 commits into
evilmartians:masterfrom
midsonlajeanty:master

Conversation

@midsonlajeanty

Copy link
Copy Markdown

Closes #719

Context

lefthook had no way to be installed through Composer, so PHP projects couldn't manage it as a dev dependency. This adds a Composer registry that distributes the existing prebuilt binaries on Packagist as evilmartians/lefthook, letting PHP users run composer require --dev evilmartians/lefthook.

It follows the bundled-binaries model already used by the RubyGems package: all platform binaries are copied into libexec/lefthook-<os>-<arch>/, and a thin PHP launcher (bin/lefthook) detects the OS/arch at runtime and execs the matching binary, inheriting stdio and propagating the exit code.

Changes

  • Add packaging/registries/php/: composer.json, the bin/lefthook launcher, and libexec/ (binaries are git-ignored, copied in by prepare).
  • Add Registries::PHP and wire it into the Raku pipeline (the php Target enum value, Packager, and the test harness TestRegistry).
  • Add packaging tests t/05-php.rakutest covering clean / prepare / publish.
  • Run prepare/publish --target=php --dry-run for php in CI (test.yml).
  • set-version is intentionally a no-op: Composer derives the version from git tags via Packagist, so composer.json carries no version field.
  • publish only runs composer validate - Composer has no local push step.

Publishing (needs maintainer action)

Packagist reads composer.json from a repository root, but this package lives in a monorepo subdirectory, so publishing needs a dedicated mirror repo (same pattern as the AUR job):

  1. Create a dedicated repo, e.g. evilmartians/lefthook-php.
  2. Submit it on packagist.org as evilmartians/lefthook.
  3. Enable the Packagist GitHub auto-update hook on that repo.
  4. On each release, push this directory's contents (composer.json, bin/, libexec/ with prepared binaries) to the mirror and tag vX.Y.Z can be added to release.yml as a publish-composer job mirroring the AUR one (clone → copy → commit → tag → push), with a deploy key/token secret.

I'm not part of the evilmartians org, so I couldn't create the mirror repo or register the Packagist vendor left those for maintainers. The package and CI validation are fully functional as-is.

@midsonlajeanty
midsonlajeanty requested a review from mrexox as a code owner June 29, 2026 14:58
@mrexox

mrexox commented Jun 30, 2026

Copy link
Copy Markdown
Member

Awesome work! Thank you for taking care. I'm not a PHP user, so could you please give simple instructions on how to:

  • Build the package and use it locally (if possible)
  • Verify the release was successful – install the lefthook PHP package?

@midsonlajeanty

Copy link
Copy Markdown
Author

Thanks! Here are simple step-by-step instructions. I verified the local flow end-to-end (the vendor/bin/lefthook proxy correctly runs the bundled binary for the host platform).

A. Build & try it locally

You don't need Packagist for this, Composer (php package manager) can install the package straight from the local folder.

1. Build the Go binaries for all platforms (same as the release build job)

goreleaser build --snapshot --clean

2. Copy the binaries into the package's libexec/ (this is what prepare does)

raku packaging/scripts/prepare.raku --target=php

3. Create a throwaway PHP project that installs the package from the local path

mkdir /tmp/lefthook-php-test && cd /tmp/lefthook-php-test
cat > composer.json <<'JSON'
{
    "minimum-stability": "dev",
    "repositories": [
        { "type": "path", "url": "/ABSOLUTE/PATH/TO/lefthook/packaging/registries/php" }
    ],
    "require": { "evilmartians/lefthook": "@dev" }
}
JSON
composer install

4. Run it — this proxies to the bundled binary for your OS/arch

./vendor/bin/lefthook version
./vendor/bin/lefthook install   # installs the git hooks in the current project

Note: minimum-stability: dev + @dev are only needed for thislocal folder has no git tag (Composer sees it as dev-master).From Packagist with real tags, it's just composer require --dev evilmartians/lefthook.

B. Verify a real release / install from Packagist

Once the package is live on Packagist (see the "Publishing" note in the PR, it needs a dedicated mirror repo under the org, which I can't create), anyone can verify it with:

cd any-php-project
composer require --dev evilmartians/lefthook
./vendor/bin/lefthook version   # prints the version → the rig
./vendor/bin/lefthook install   # sets up git hooks

And the package page will be at https://packagist.org/packages/evilmartians/lefthook. A green install + a correct version output on any OS confirms the release works.

…ackage to a Packagist mirror and Add the publish-composer job to release.yml
@midsonlajeanty

Copy link
Copy Markdown
Author

Releasing the Composer package

The package is fully built, validated and smoke-tested in CI, but the actual publish step stays dormant until the mirror repo exists the publish-composer job is gated on the LEFTHOOK_COMPOSER_REPO variable and skipped otherwise, so merging this changes nothing until you're ready.

Why a mirror repo? Packagist reads composer.json from a repository root and syncs on git tags. This package lives in packaging/registries/php/ (a monorepo subdirectory), which Packagist can't read directly. So exactly like the AUR job release pushes the package's contents to a dedicated repo that Packagist watches.

One-time setup:

  1. Create a dedicated repo, e.g. evilmartians/lefthook-composer.
  2. Submit it on packagist.org (registers as evilmartians/lefthook, the name in composer.json) and enable the GitHub auto-update hook.
  3. Create a deploy key with push access to that repo; store its private key as the COMPOSER_SSH_KEY repository secret.
  4. Set the LEFTHOOK_COMPOSER_REPO repository variable to the mirror's SSH URL, e.g. git@github.com:evilmartians/lefthook-composer.git.

Once both are set, publish-composer activates automatically on the next tag push: it clones the mirror, copies composer.json + the launcher + the prepared binaries, then commits, tags vX.Y.Z and pushes. Packagist picks up the tag.

@mrexox

mrexox commented Jul 3, 2026

Copy link
Copy Markdown
Member

Thank you @midsonlajeanty! I'll have some time to experiment with this later next week, so I'm afraid the PR will hang for some time.

@midsonlajeanty

Copy link
Copy Markdown
Author

Thanks

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.

Prepackaged PHP Composer

2 participants