Repository navigation
fix(ci): refresh pub.dev OIDC token per package publish - #24
Conversation
Mint a fresh GitHub Actions ID token immediately before each train package upload so long inter-package waits cannot expire the JWT. Add bounded retry with exponential backoff to the hosted consumer gate for pub.dev indexing lag. Co-authored-by: Anton Malofeev <anton@xsoulspace.dev>
Stop overriding runner-injected ACTIONS_ID_TOKEN_* in pub_publish.yml; mask minted tokens in GITHUB_ACTIONS; add test_publish_packages_oidc.sh. Co-authored-by: Anton Malofeev <anton@xsoulspace.dev>
Arenukvern
left a comment
There was a problem hiding this comment.
Flutter Mcp Toolkit steward: approve at ddbf2569. I'm posting this as a comment because GitHub treats the shared account as the author. It's the same fix as mcp_flutter #162, and the ordering is right.
refresh_pub_oidc_tokenruns inside the loop, after the skip-if-published check and right beforedart pub publish --force. Becausewait_for_hosted_versionends the previous iteration, every package gets a token that is only a few seconds old, however long the train runs.local response tokenis declared before the assignments, so a curl--failor a parse failure still exits underset -einstead of being swallowed bylocal.- The token is masked before it's exported, and
dart pub token addgets it through--env-var, so it never appears on a command line.python3is on ubuntu runners, so that's fine. - Good catch on
${{ env.ACTIONS_ID_TOKEN_REQUEST_URL }}. That would have blanked the real runner values. The contract test guarding it is the right kind of regression net.
One non-blocking follow-up: the hosted-consumer retry wraps pub get, analyze and run together, so a real analyzer or runtime regression keeps retrying for 10 minutes before it goes red. Retrying only while dart pub get fails to resolve, and failing analyze/run on the first error, would keep the indexing-lag cover and give real breakage a fast signal.
The PR currently shows mergeable_state: unstable, so please merge pinned to this SHA only once its checks are green.
Fake curl mints OIDC tokens; fake dart records pub token add before each publish; add coverage for missing OIDC env on --publish. Co-authored-by: Anton Malofeev <anton@xsoulspace.dev>
Arenukvern
left a comment
There was a problem hiding this comment.
Flutter Mcp Toolkit steward: approve at 02da4e85, as long as CI is green at this SHA. I'm posting this as a comment because GitHub treats the shared account as the author. I compared ddbf2569...02da4e85. It's one commit, and the only file touched is test/release_train_test.dart, so the script and workflow I approved are unchanged.
The fixture fix is the right one. It gives the test fake OIDC env so the guard can stay as it is. The ordering helper also rejects a publish that has no refresh right before it: the line after each oidc| has to be that package's publish --force. Together with the exact dartPackages lists, a skipped package can't sneak in a refresh, and a published package can't miss one.
Two non-blocking hardening ideas for the follow-up:
- The fake
curlanswers any call whose arguments containid-token, so if the script gotaudience=https://pub.devor thebearerheader wrong, the test would still pass, and only a real publish would catch it. Asserting that the logged OIDC call contains both of those would close that gap. dartPackagesnow keeps only lines containingpub publish, so an unexpected extradartcall in publish mode would no longer show up. Asserting the full log shape, which is onlyoidc|andpublish --forcelines, would put that strictness back.
Right now test, linux-desktop-dev and android-real-smoke are still running, and the other checks are green or skipped.
Summary
The
pub_publishjob uploads ~12 train packages in one job.dart-lang/setup-dartmints pub.dev OIDC once at job start; after ~9 minutes of propagation waits the JWT expires (Invalid JWT token: invalid timestampson the last package in the v7.0.2 run).This PR:
ACTIONS_ID_TOKEN_REQUEST_URLwithaudience=https://pub.devimmediately before eachdart pub publish(after any inter-package propagation wait for the previous package).dart pub token add https://pub.dev --env-var PUB_TOKEN.::add-mask::whenGITHUB_ACTIONS=true.--publishruns without OIDC env (no change to--dry-run).envforACTIONS_ID_TOKEN_*(those expressions are empty in the workflowenvcontext and would overwrite runner-injected values).check_package_consumer.sh --hostedstep with exponential backoff (15s start, 60s cap, 600s total) for pub.dev indexing lag.tool/contracts/test_publish_packages_oidc.sh(wired intocheck_contracts.sh).test/release_train_test.dartfixtures (fake OIDC env + curl/dart) so publish integration tests match the guard.No version/manifest changes; no publishing.
Files changed
tool/release/publish_packages.sh— per-package OIDC refresh + maskingtool/ci/check_package_consumer.sh— hosted-mode retry loop.github/workflows/pub_publish.yml— hosted consumer timeout only on verify steptool/contracts/test_publish_packages_oidc.sh— OIDC/publish wiring contractstool/contracts/check_contracts.sh— runs OIDC contract testtest/release_train_test.dart— OIDC-aware publish train fixture + testVerification
bash -nOIDC contract test
--publishwithout OIDC (expect exit 1)dart pub get --no-example+ dry-runContract gates
actionlint
Dart tests
Type of change
fix:)Checklist
check_contracts.shrun locally (includes OIDC contract)release_train_test.dart+ rootdart testgreen