This document is for maintainers of official module repositories. It describes the reusable module release workflow shipped by the SDK.
- Set
module.json'sversionto the intended exact SemVer version. - Build and commit every declared
dist/asset. - Run the module's lint, tests, frontend build, and package validation.
- Merge the release change, then create an unprefixed tag that exactly matches
module.json, for example1.2.3rather thanv1.2.3.
The reusable workflow rejects a tag that does not exactly match the manifest version. Stable releases require final SemVer; insider releases require a prerelease SemVer.
An official module normally calls the tagged SDK workflow from its own tag workflow:
jobs:
release:
uses: InvoiceShelf/modules/.github/workflows/module-release.yml@3.3.0
with:
channel: stable
secrets: inheritThe workflow installs dependencies, runs Pint and PHPUnit, builds frontend assets when present, validates the package, creates a timestamp-normalized ZIP, generates and validates release-manifest.json, signs its canonical JSON, and sends it to marketplace ingest.
Configure this protected GitHub environment in every official module repository:
| Setting | Type | Purpose |
|---|---|---|
MODULE_SIGNING_SECRET_KEY_B64 |
Secret | Standard-base64 raw Ed25519 secret key. |
MODULE_MARKETPLACE_INGEST_TOKEN |
Secret | Bearer token for the module's marketplace ingest request. |
MODULE_SIGNING_KEY_ID |
Variable | Identifier of the matching public signing key. |
MODULE_MARKETPLACE_INGEST_URL |
Variable | HTTPS ingest base URL ending in /api/marketplace/v1/modules. |
The workflow appends /{slug}/releases to the ingest URL. It disables persisted checkout credentials and uses the protected token only for that request.
Generate an Ed25519 keypair with:
vendor/bin/invoiceshelf-module generate-keypair official-2026-01Put secret_key_b64 only in the environment secret. Configure public_key_b64 under the same key_id in the InvoiceShelf and marketplace public-key configuration, then discard the command output. Do not commit either key, the ingest token, or an organization-specific endpoint.
CI creates an immutable schema-v1 release-manifest.json containing the module identity/version, channel, compatibility, artifact SHA-256 and size, signing key ID, source commit, and release time. It signs canonical JSON with an Ed25519 detached signature.
The marketplace can mark a published release as yanked without re-signing it; package identity and artifact integrity remain signed. Use the SDK CLI to inspect a manifest locally:
vendor/bin/invoiceshelf-module validate-release release-manifest.json
vendor/bin/invoiceshelf-module canonicalize-release release-manifest.json > release-manifest.canonical.json