Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/rocketsarenostalgic/ran-booster-github-example/archive/refs/heads/main.zipOptional developer example; GitHub support is already bundled with Booster.
This repository shows how to package a replacement for Booster's GitHub support
as a small WordPress plugin. In this guide, a provider is the code Booster
uses to talk to a service such as GitHub. This plugin does not implement GitHub
again. It wraps the existing ran/booster-github-provider Composer library and
connects it to Booster through the public replacement contract.
Start with Choose GitHub support if you operate a site, or read the developer contract before adapting this plugin.
This example is intended for a separate WordPress test site you can discard. There is no WordPress.org listing. Until the first qualified GitHub release is published, build the repository yourself. See Releases for the dependency-update and tested-ZIP release process.
What this plugin replaces
Booster has one GitHub provider slot, identified by gh. Installing this plugin
does not add a second provider or change existing GitHub-managed packages into
another kind of package. Instead, the plugin declares a candidate with its own
plugin basename and replacement implementation ID. Booster decides which candidate
may supply the one gh slot.
Activation only makes the candidate discoverable. It does not construct the provider, read saved credentials, or approve anything. In Booster's GitHub screen, an administrator reviews the supplying plugin and explicitly approves it. Reusing compatible saved API credentials requires separate approval.
When more than one candidate is active, when the selected candidate is missing, or when an old review is stale, GitHub work pauses. Booster does not substitute another saved profile, anonymous access, a constant setting, or the bundled provider. To return to bundled GitHub, deactivate every replacement candidate, then use Booster's explicit return review.
Booster calls Plugin::create() only after approval and passes the services and
permission checks it needs. Keep the begin and complete native-update callbacks:
the first authorizes a change immediately before WordPress writes files, and the
second records its outcome. The plugin does not use a private Booster container.
Build and check a local ZIP
Use PHP 8.2–8.5, WordPress 7.0 or newer, and a compatible Booster build with Provider beta.20, Provider API 15, and the native-update checkpoints. Booster and Example must contain matching Provider, Release Updater and Updater Support files. The current qualification pairs published Booster beta.41 with genuine Release Updater beta.15 (runtime protocol 7). PHP may load either plugin's copy first; Example allows reuse only when the loaded files match its recorded qualified dependency hashes.
Development checks also require Composer 2, Python 3.10 or newer and WP-CLI
2.12.0. The quality profile is wordpress-plugin; this PHP-only plugin has no
frontend build. host-contract.json identifies the exact Core source revision
used for qualification. Check out that revision in a separate directory and
install its locked production dependencies with composer install --no-dev.
The recorded host is a published release fixture, rather than an additional runtime
version restriction on compatible Booster installations. CI downloads its release ZIP
and checks the recorded digest and provenance before installation.
git clone https://github.com/RocketsAreNostalgic/ran-booster-github-example.git
cd ran-booster-github-example
composer install --no-interaction --prefer-dist --no-progress
RAN_BOOSTER_CORE_PATH=/absolute/path/to/compatible-core composer check
composer build
python3 scripts/test-archive.py
python3 scripts/release.py archive
composer check needs a supported Booster source checkout with its dependencies.
Booster is not a production Composer dependency of this plugin. The checks use
synthetic credentials and HTTP responses, and the archive probe uses temporary
directories rather than a live site or remote repository.
The aggregate runs the shared PHP coding standard, PHPStan level 8, maintained-file
coverage and negative controls, tests, gettext parity and dependency qualification.
The host check verifies Core's revision, tracked source bytes, production lock and
matching runtime dependencies. composer i18n:pot regenerates the tracked runtime
translation catalogue; composer i18n:check checks it without changing source.
Runtime eligibility is Provider API 15 plus the native-update checkpoints used
by the Example. The exact Core commit, tree, lock and published ZIP in
host-contract.json make tests reproducible; they are not a production check for
one Core release. Shared-library hashes protect the PHP namespaces in either
load order and remain exact even when Core's public API is unchanged.
A Core-only UI change can require fresh compatibility evidence without changing or releasing the Example. Refreshing a qualification fixture changes test metadata. Adopting different bundled dependency bytes, as with updater beta.15, changes the Example package and requires its own qualified dependency update. The broader newer-Core compatibility lane discussed in issue #15 remains separate.
Use fix(deps): for production dependency updates so Release Please proposes an
Example release too. Development-only dependency updates may use chore(deps):.
Every update still needs qualification and review; see RELEASE.md.
The built ZIP is written under dist/. Do not use a source checkout without
its Composer dependencies and qualified-provider.json, the file that records
dependency hashes. Do not install the ZIP on a site you rely on.
To try it, install the ZIP on a set-aside WordPress test site. Keep Booster active and other GitHub replacement plugins inactive, then activate the Example. In Booster → GitHub, open Review GitHub provider, make the displayed approval choices (including saved-credential reuse if prompted), then choose Adopt GitHub implementation. To return to bundled GitHub, deactivate every replacement candidate and review the return in Booster.
Private workflow state and uninstall
This example passes github_example, a fixed prefix (namespace) for its local
workflow setup records and review previews, to the library. Temporary locks and
cleanup also use that namespace. Deactivation keeps the state so an administrator
can return to the same implementation later. Changing the namespace starts a
different store; it does not migrate or discover old records.
Uninstall checks the expected plugin name and resolved path, rejects symlinked development directories, and checks files against recorded hashes. It removes only this namespace's saved records, preview index, and previews. It does not delete Booster credentials, packages, history, bundled state, or remote workflows and webhooks. If ownership or cleanup is uncertain, it retains state instead. Run uninstall only on copied plugin files in a separate test site.
An empty local store does not prove that a remote repository is empty. The library still checks repository identity, workflow and path conflicts, and the result of uncertain writes before retrying. It cannot reconstruct every earlier draft setup pull request, and it does not promise that a new setup produces no additional drafts.
Transporter scope
Transporter moves supported managed-package records and explicitly chosen Booster-held credentials through an available, compatible provider. It does not install this Example at a destination or move private workflow records, previews, locks, external credentials, or remote webhook configuration.
Test an unreleased Provider candidate
The Provider package uses this plugin as its real Composer consumer in CI. Pin this repository's source, then supply the exact package commit under test; the package does not need a release or a committed dependency bump here first.
python3 scripts/prepare-provider-candidate.py \
--provider-root /path/to/provider --provider-sha FULL_PROVIDER_SHA \
--host-root /path/to/core --host-sha FULL_CORE_SHA \
--output /new/disposable/assembly
RAN_PROVIDER_CONSUMER_ASSEMBLY=/new/disposable/assembly \
RUNNER_TEMP=/private/runner/temp bash scripts/consumer-installed-smoke.sh
Inputs must be clean Git checkouts. Use the Core revision in host-contract.json.
The preparer uses Composer to install the candidate into temporary plugin and
host copies while retaining unrelated locked packages. Matching host copies
preserve the check against incompatible already-loaded dependencies. Neither
input checkout is changed. Candidate archives and their exact commit/digest
receipt are test evidence; the normal release build rejects candidate assemblies.
The installed test needs PHP, Composer, WP-CLI and a disposable database. It uses
the existing installation runner, discovers and installs the actual Example ZIP
through the updater with controlled GitHub responses, then checks activation,
explicit adoption and both plugin load orders. Its database defaults match CI;
local isolated databases can set RAN_EXAMPLE_DB_NAME, RAN_EXAMPLE_DB_USER,
RAN_EXAMPLE_DB_PASSWORD and RAN_EXAMPLE_DB_HOST.
Adapt this example
These names appear in more than one file. Change them as a set.
- Plugin and manifest. Rename
ran-booster-github-example.php, update its WordPress header, and update the adjacentran-booster-github-example.gh-replacement.jsonbasename, distinct implementation ID, credential and signing formats, and capabilities (interfaces the provider implements). Insrc/Plugin.php, update both manifest paths used bydeclare()andavailability_error(). - Runtime identity. Update
Plugin::BASENAMEand choose a distinct, stablePlugin::WORKFLOW_NAMESPACE. Keep the namespace responsible only for its own records, previews, locks, and cleanup. InPlugin::uninstall(), keep the hard-codedWP_PLUGIN_DIRdirectory and resolved main-file path aligned with the exact basename, while retaining the symlink guards. - PHP and Composer names. When changing the PHP namespace, update the
package name plus
autoload.psr-4andautoload-dev.psr-4incomposer.json; then update the main-file bootstrap,uninstall.php, test namespaces, and the namespace declarations inscripts/lint.phpandscripts/qualify-dependencies.php. - Build inputs and qualification. Update
SLUGand the fixed input names inscripts/build.py: Composer files, main file, uninstall entry point, manifest, qualification map, README, and license. After changing the lock, runphp scripts/qualify-dependencies.phpto regenerate the map, then runphp scripts/qualify-dependencies.php --checkbeforecomposer build. - Archive probe. In
scripts/test-archive.py, update the ZIP filename and root prefix, expected main filename, extracted plugin directory, and embeddedRAN\BoosterGitHubExamplenamespace. Intests/archive-uninstall.php, update the fixture-root basename and expected uninstall invocation. - Fixture tests. Update the copied main-file and manifest paths and plugin
root directory in
tests/CompositionTest.phpandtests/TransporterTest.php. Check both plugin load orders, the built archive, approval, no fallback, switching, return, and disposable uninstall.
Private workflow separation prevents accidental collisions. It does not sandbox a trusted active PHP plugin or authenticate a third-party publisher.
For public reports and contributions, follow the organization support guidance, security policy and contribution guidance.