ci(release): publish to pub.dev via OIDC trusted publishing#20
Open
hakimjonas wants to merge 2 commits into
Open
ci(release): publish to pub.dev via OIDC trusted publishing#20hakimjonas wants to merge 2 commits into
hakimjonas wants to merge 2 commits into
Conversation
pub.dev was published BY HAND — release.yml had no publish step — so 0.13.0 shipped to GitHub/brew/scoop/MCP while pub.dev stayed at 0.12.0 until caught days later. Automate it. - New publish-pub-dev job: dart pub publish --force, authenticated by OIDC (id-token: write), mirroring the publish-mcp pattern. No stored credentials. - Gated on !contains(ref_name, '-') like the other publish jobs, and needs: release for ordering. - Regenerates _version.dart / _skill.dart before publishing as a safety belt (they're tracked + kept in sync by CI, but regenerating guarantees the published constant matches the tag regardless). One-time setup required on pub.dev (Admin → Automated publishing) before this works; until enabled the job fails in isolation without affecting the rest of the release. Documented inline.
Adversarial review of the first cut (hand-rolled setup-dart + `dart pub publish --force`) found it correct on auth but reinventing what Dart's official reusable workflow does — which the docs strongly encourage and which already includes a dry-run before the irreversible publish. Replace the custom job with a call to `dart-lang/setup-dart/.github/workflows/publish.yml@v1`: - The reusable workflow runs `dart pub publish --dry-run` before `-f`, so validation/resolution failures surface before the irrevocable step (pub.dev versions are immutable). - setup-dart provisions the OIDC token; caller passes `id-token: write` (verified: caller must grant it, reusable workflow can't escalate). - Dropped the redundant gen_version/gen_skill steps — those files are tracked and kept current by the generated-files CI check; the committed tree is what publishes. - Fixed the misleading "same mechanism as publish-mcp" comment (MCP registry OIDC is a different integration than pub.dev's). Verified: @v1 resolves (tag 65eb853, same ref the official docs use); job-level uses/if/needs/permissions is the legal reusable-workflow shape; no `with:` or `secrets: inherit` needed (inputs optional, OIDC not secrets). One-time pub.dev publisher setup still required before it runs; fails in isolation until then.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Item 1b of the 0.14.0 cycle. Hardened after an adversarial review (see below).
Why
release.ymlhad nodart pub publishstep — pub.dev publishing was manual, which is why 0.13.0 shipped to GitHub/brew/scoop/MCP but pub.dev stayed at 0.12.0 until caught. Automate it so it can't slip again.What
Adds a
publish-pub-devjob that calls Dart's official reusable workflowdart-lang/setup-dart/.github/workflows/publish.yml@v1, gated on non-prerelease tags,needs: release.Adversarial review (what changed from the first cut)
The first version hand-rolled
setup-dart+dart pub publish --force. Review against the pub.dev automated-publishing docs and the canonical reusable workflow found:id-token: writeis the right, sufficient permission — verified the caller must grant it and a reusable workflow can't escalate).dart pub publish --dry-runbefore the irreversible-f— important because pub.dev versions are immutable.gen_version/gen_skillsteps — those files are tracked and kept current by thegenerated-files-in-syncCI check; the committed tree is what publishes.Verified:
@v1resolves (tag65eb853, the same ref the docs use); job-leveluses/if/needs/permissionsis the legal reusable-workflow shape; nowith:orsecrets: inheritneeded.One-time setup required before this works
pub.dev → lambe → Admin → Automated publishing → Enable, repo
hakimjonas/lambe, tag patternv{{version}}. pubspecversionmust match the tag. Until enabled, the job fails in isolation — the rest of the release is unaffected (needs: releaseis ordering only).Publish gate
No required-reviewer
environment:added — solo maintainer, tag trigger + branch protection suffice. The reusable workflow accepts anenvironment:input, so this is a one-line add later if collaborators join.Workflow-only change — no lib/CLI code touched.