Create the app and handle installs
This server sends customers to Entire and accepts their receipts:saveState, loadState and saveInstallation are your own functions. AcceptReceipt checks the state, the receipt’s signature, issuer, audience, plugin, expiry and single use, and returns plugin.ErrAccessDenied when the customer canceled. Store receipt.CoreURL with the installation ID; it is a convenient Core to call later.
Set Config.Permissions to every permission you registered, including Trails if you registered trails:read or trails:write. inst.Token requests them for every covered repository, and Entire refuses that token with 400 repository_required unless it names every registered permission. Calls that act on one repository, such as inst.Checks and inst.Deployments, use a token for that repository with only the permission they need.
Two defaults matter for production. Config.Cores defaults to Entire’s production Cores, and receipts from any other issuer are refused. Receipt replay protection defaults to memory, so give Config.ReplayStore a shared store when you run more than one process.
Read the customer’s repositories
RepositoryClient returns an ordinary SDK client whose token reaches one repository, with the permissions you pass. It routes every call to the repository’s region and renews the token as it nears expiry:
inst.RepositoryToken or, for the whole installation, inst.Token.
The same client comments on trails when you add Discussions: plugin.Write to the permissions you pass.
Clone with Git
Clone throughgit-remote-entire, the Git helper that ships with the Entire CLI. A repository’s EntireCloneURL names it, and RemoteHelperEnv returns environment variables that hand the helper the installation’s token in ENTIRE_TOKEN:
RemoteHelperEnv uses the installation’s token, which reaches every repository in the installation, so run Git only where you trust it as much as your plugin. The token lasts about 45 minutes; call RemoteHelperEnv again for later fetches.
Code that speaks the Git protocol itself, such as a proxy, calls GitAuthorization instead. It returns an Authorization header value with a token narrowed to one repository and the permissions you pass, cached and renewed like RepositoryToken’s, so call it for every request:
Config.HostPolicy approves its host: it carries a credential.
Create a repository
Plugins registered withrepositories:create create repositories in the installation’s project. Add Repositories: plugin.Create to Config.Permissions, and Contents: plugin.Write if you push to them. CreateRepository mints the create token, creates the repository, and waits until it is ready:
RepositoryClient or RepositoryToken with its ID to act on it. Pass &plugin.CreateRepositoryOptions{ObjectFormat: "sha256"} for a SHA-256 repository. A name the project already has returns plugin.ErrRepositoryExists, and the daily limit returns plugin.ErrCreateLimit; the wrapped *entire.HTTPError says when to retry. If the repository is still provisioning when the wait gives up, CreateRepository returns plugin.ErrRepositoryNotReady with the new ID, so store it rather than create again. See Create a repository for the errors, the limit, and what happens on uninstall.
Report check runs
Plugins registered withchecks:write write check runs on a commit in any repository the installation covers. A write is idempotent, so retry it freely. ExternalUpdatedAt is when the state changed on your side, and Entire applies writes to a run in that order:
checks:write, and follows a repository that moved to another region.
Your plugin’s gate
Each plugin that can write checks gets its own gate on every repository it covers, keyed by its slug. Entire creates the gate the first time it evaluates a repository’s gates after the install. The gate is enabled and blocking, so your reports can stop a trail from merging:- No required names. The gate doesn’t apply until you report on the trail’s head commit. After that, every suite on the head commit must pass.
- Required names. The customer lists names, as Review and require checks describes, under the repository’s Settings then Gates. A name is a suite key, such as
ci, or a suite key and a run key, such asci / lint. A listed name with no report on the head commit waits, unless the commit was pushed before the plugin was connected. Checks that aren’t listed never block.
success, neutral, skipped and action_required conclusions don’t fail a run. Keep your suite and run keys stable, because customers name them in their gate settings.
Deployments never count toward this gate. To show the resources you deployed and links to them on the Change, report deployments with inst.Deployments.
Receive events
App.WebhookHandler verifies each delivery’s signature, skips deliveries already handled, and calls your function. Answer within seconds and queue slow work. Webhooks are experimental, and field names may change:
Config.DeliveryJWKSURL to the delivery JWKS URL Entire gives you when it registers your webhook.
Entire delivers fifteen events:
Trail events need
contents:read. See Receive trail events for when each one fires and how to decode it.
Try it on your machine
The SDK’sexamples/plugin-reader example runs the whole flow without a public server. It serves the post-install callback on https://localhost:8443/callback, opens the install link, verifies the receipt, then reads each repository with a client scoped to it.
- Make a key and print its public half with
go run ./examples/plugin-reader -key plugin-key.pem pubkey. - Ask Entire to register a test plugin with that key,
contents:readandhttps://localhost:8443/callbackas a post-install URL. - Make a certificate your browser trusts, for example with
mkcert localhost. - Run the install, and choose a test project and repository on the install page.
run.