Skip to content

Build paid plugins individually with each owner's GitHub token#404

Merged
simonhamp merged 1 commit into
mainfrom
fix/satis-per-plugin-owner-tokens
Jun 27, 2026
Merged

Build paid plugins individually with each owner's GitHub token#404
simonhamp merged 1 commit into
mainfrom
fix/satis-per-plugin-owner-tokens

Conversation

@simonhamp

Copy link
Copy Markdown
Member

Problem

A full Satis rebuild (php artisan satis:build with no --plugin) sent every paid plugin in a single request using one shared GitHub token. A satis build can only authenticate to github.com as one identity, but paid plugins live in private repos across different owners/orgs — so one token can't clone them all and the rest fall back to unauthenticated requests, hitting GitHub's 60/hour rate limit. Combined with satis's --skip-errors, the build "succeeded" with most repos skipped and authoritatively overwrote packages.json with a near-empty index.

(Per-plugin syncs via SyncPluginReleases already used the owner's token, so only the full-rebuild path was affected.)

Changes

  • buildAll() now builds each approved paid plugin individually, using its owner's GitHub token (resolved via ResolvesGitHubToken). Each is a partial, merging build on the satis side, so a single failure can never overwrite the published index with an incomplete set. Returns a per-plugin summary (plugins_count, failed, results).
  • Refactor ResolvesGitHubToken to expose resolveGitHubTokenFor(Plugin) (the existing getGitHubToken() delegates to it, behaviour unchanged); SatisService now uses the trait.
  • Add SatisService::buildForPlugin() — resolve owner token + build one plugin. The satis:build --plugin path now uses it too (previously it sent no token).
  • satis:build command reports per-plugin dispatch results.
  • Test updated: buildAll now sends one partial build per paid plugin (full_build === false), asserted via Http::assertSentCount(1).

Note

This is the root-cause fix; the companion guard in plugins.nativephp.com (NativePHP/plugins.nativephp.com#7) refuses to publish an incomplete full build as defense-in-depth. Paid plugins whose owner has not connected GitHub still fall back to config('services.github.token') (GITHUB_TOKEN), which is currently unset and not in .env.example — worth setting. The long-term fix is the GitHub App (in progress separately).

Testing

php artisan test tests/Feature/SatisSync/SatisSyncTest.php tests/Feature/Jobs/SyncPluginReleasesTest.php → 11 passed. php -l and Pint clean on changed files.

🤖 Generated with Claude Code

A full Satis rebuild (satis:build with no --plugin) sent every paid plugin in
one request with a single shared GitHub token. A satis build can only
authenticate to github.com as one identity, but paid plugins live in private
repos across different owners/orgs, so one token can't clone them all — the rest
fall back to unauthenticated requests and hit the 60/hour rate limit. With
satis's --skip-errors that produced a near-empty, authoritative rebuild that
wiped packages.json.

buildAll() now iterates and builds each approved paid plugin individually using
its owner's GitHub token (resolved via ResolvesGitHubToken). These are partial,
merging builds on the satis side, so a single failure never overwrites the
published index with an incomplete set.

- Refactor ResolvesGitHubToken to expose resolveGitHubTokenFor(Plugin); SatisService uses it.
- Add SatisService::buildForPlugin(); the satis:build --plugin path now uses the owner's token too.
- Update the command to report per-plugin dispatch results; update the buildAll test (per-plugin partial builds, full_build === false).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@simonhamp simonhamp merged commit 6ad7075 into main Jun 27, 2026
2 checks passed
@simonhamp simonhamp deleted the fix/satis-per-plugin-owner-tokens branch June 27, 2026 17:44
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