From a97528b22e3ec96611104cfce0aa96de26225037 Mon Sep 17 00:00:00 2001 From: Lann Martin Date: Wed, 12 Aug 2026 09:08:22 -0400 Subject: [PATCH] gates: publish-check (deno publish --dry-run); release: JSR publish before the GH release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fallout from the pre-3c8c0e9 release failure (run 31560192748): - publish-check: new required gate running the JSR publish checks (public-API type check, slow types, export/import analyzability, config validation) with no upload. None of these were covered by gates before — they only fired at publish time on main. Wired into `just gates`, the core CI job, and the AGENTS.md gates block (also restoring the stale examples/test-translate lines there). Needs the shim: @deltic/translator statically imports translator_shim.wasm. --allow-dirty because pre-commit trees are dirty by definition. - release.yml: publish to JSR before creating the GH release. The JSR step is the one most likely to fail, and the old order stranded a half-release behind the tag guard (GH release created, JSR versions missing, re-runs blocked). New order converges on re-run: the tag guard passes while no release exists, and deno publish skips already-published versions. The actual pre-3c8c0e9 failure was not catchable by any gate: JSR's default scope setting requires the workflow-triggering ACTOR to be a scope member, and lannbot-armed auto-merges broke it (actorNotScopeMember). Fixed scope-side (restriction disabled — publishing stays repo-linked + green-main-gated); noted in the release.yml step comment. Repaired by deleting the stranded release and re-dispatching (run 31598707134, actor=lannbot, green). --- .github/justfile | 1 + .github/workflows/release.yml | 61 ++++++++++++++++++++--------------- AGENTS.md | 2 ++ justfile | 14 +++++++- 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/.github/justfile b/.github/justfile index 107db3a..5759c50 100644 --- a/.github/justfile +++ b/.github/justfile @@ -56,6 +56,7 @@ core: @just gha::_step test-wasi-shims @just gha::_step test-ct-runner @just gha::_step test-bundle + @just gha::_step publish-check @just gha::_step examples @just gha::_step test-translate @just gha::_step conformance diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2bb3e1b..2b80896 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,6 +59,41 @@ jobs: # bundle_test.ts in the core matrix), and SHA256SUMS. run: just release-artifacts + - name: publish unstable prereleases to JSR + # Version scheme (issue #16, interim): 0.1.0-pre.g — + # correlates 1:1 with this run's `pre-` release tag. The + # `g` prefix (git-describe's convention) is load-bearing: a bare + # short hash can be all-digits-with-leading-zero, which is INVALID + # semver (numeric identifiers forbid leading zeros) and would fail + # ~0.4% of publishes at random. Hash versions are unique per commit + # (JSR refuses duplicates, making re-runs no-ops-by-failure like + # the tag guard) but deliberately NOT monotonic under semver + # ordering: unstable prereleases are pinned exactly, never ranged. + # The stamped versions are CI-working-tree-only (never committed); + # cross-package workspace deps are rewritten by `deno publish`. + # Auth: OIDC (permissions.id-token) — the @deltic packages must + # exist on jsr.io and be linked to this repository (one-time + # manual setup; see the #16 checklist). The scope's "actor must be + # a scope member" restriction is OFF: merges armed by the machine + # account make the workflow actor `lannbot`, which broke the + # publish (actorNotScopeMember) until the setting was disabled. + # Runs BEFORE the GitHub release: it is the step most likely to + # fail, and ordering it first keeps partial failures re-runnable — + # a re-run passes the tag guard (no release yet) and `deno + # publish` skips already-published versions, so it converges + # instead of stranding a release that claims unpublished JSR + # versions. + run: | + VERSION="0.1.0-pre.g${SHORT}" + echo "publishing @deltic/* ${VERSION}" + for p in runtime translator wasi-shims ct-runner; do + jq --arg v "$VERSION" '.version = $v' "$p/deno.json" > "$p/deno.json.tmp" + mv "$p/deno.json.tmp" "$p/deno.json" + done + deno publish --allow-dirty + env: + SHORT: ${{ steps.tag.outputs.short }} + - name: create prerelease run: | { @@ -88,29 +123,3 @@ jobs: env: GH_TOKEN: ${{ github.token }} TAG: ${{ steps.tag.outputs.tag }} - - - name: publish unstable prereleases to JSR - # Version scheme (issue #16, interim): 0.1.0-pre.g — - # correlates 1:1 with this run's `pre-` release tag. The - # `g` prefix (git-describe's convention) is load-bearing: a bare - # short hash can be all-digits-with-leading-zero, which is INVALID - # semver (numeric identifiers forbid leading zeros) and would fail - # ~0.4% of publishes at random. Hash versions are unique per commit - # (JSR refuses duplicates, making re-runs no-ops-by-failure like - # the tag guard) but deliberately NOT monotonic under semver - # ordering: unstable prereleases are pinned exactly, never ranged. - # The stamped versions are CI-working-tree-only (never committed); - # cross-package workspace deps are rewritten by `deno publish`. - # Auth: OIDC (permissions.id-token) — the @deltic packages must - # exist on jsr.io and be linked to this repository (one-time - # manual setup; see the #16 checklist). - run: | - VERSION="0.1.0-pre.g${SHORT}" - echo "publishing @deltic/* ${VERSION}" - for p in runtime translator wasi-shims ct-runner; do - jq --arg v "$VERSION" '.version = $v' "$p/deno.json" > "$p/deno.json.tmp" - mv "$p/deno.json.tmp" "$p/deno.json" - done - deno publish --allow-dirty - env: - SHORT: ${{ steps.tag.outputs.short }} diff --git a/AGENTS.md b/AGENTS.md index 6d29eaf..445f2d1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,6 +38,8 @@ just test-runtime # runtime check + tests (deps: shim, fixtures, corpus) just test-protocol just test-wasi-shims test-ct-runner just test-bundle # embedder-bundle release asset +just publish-check # deno publish --dry-run: the JSR publish checks, no upload +just examples test-translate # embedder examples; build-time translation CLI just conformance # official CM suite, Deno lane just sched-seeds # seeded-shuffle reruns: DELTIC_SCHED_SEED=1, =4242 (FIFO when unset) just test-ports # ports/webcrypto + ports/websocket unit suites diff --git a/justfile b/justfile index 24fd1bc..edf2f4c 100644 --- a/justfile +++ b/justfile @@ -16,7 +16,7 @@ ci: (gha::core) (gha::browser) # Includes the consumer smokes CI cannot run (they need the polymorph # checkouts; docs/consumers.md). # The full pre-commit pass (AGENTS.md "Gates"): everything. -gates: build test-rust test-protocol test-runtime test-wasi-shims test-ct-runner test-bundle examples test-translate conformance sched-seeds test-ports test-webrtc shells browsers websocket-conformance smoke-tls smoke-c0 +gates: build test-rust test-protocol test-runtime test-wasi-shims test-ct-runner test-bundle publish-check examples test-translate conformance sched-seeds test-ports test-webrtc shells browsers websocket-conformance smoke-tls smoke-c0 # Fast sanity: builds + native tests + type-checks, no suites. check: build test-rust @@ -100,6 +100,18 @@ test-ct-runner: shim fixtures test-bundle: shim deno test -A tools/release-bundle/ +# The JSR publish checks (public-API type check, slow types, export and +# import analyzability, config validation) — `deno task check` covers +# none of them, so they only fired at publish time on main before this +# gate. Needs the shim: @deltic/translator ships translator_shim.wasm +# (statically imported by shim_asset_deno.ts). Registry-side failures +# (scope auth, version conflicts) still only manifest on a real publish. +# --allow-dirty because this is a PRE-commit gate (the dirty check +# protects uploads; there is no upload here). +# JSR publish verification, no upload (`deno publish --dry-run`). +publish-check: shim + deno publish --dry-run --allow-dirty + # The harness task chains corpus generation and the shim check itself. # The official CM conformance suite, Deno lane. conformance: