Skip to content

Add multi-registry release CI (crates.io · npm · pub.dev) — ADR-011#1

Merged
Tovli merged 3 commits into
masterfrom
ci/creat-publish-package-workflow
Jun 14, 2026
Merged

Add multi-registry release CI (crates.io · npm · pub.dev) — ADR-011#1
Tovli merged 3 commits into
masterfrom
ci/creat-publish-package-workflow

Conversation

@Tovli

@Tovli Tovli commented Jun 13, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the release pipeline from ADR-011: a tag-triggered GitHub Actions workflow that publishes the SDK to crates.io, npm, and pub.dev from a single semver tag (v1.2.3).

verify → build artefacts (parallel) → assemble packages → publish (serial: crates → npm → pub)

What's in here

.github/workflows/release.yml (new)

  • verify — extracts semver from the tag; asserts both [workspace.package].version and every [workspace.dependencies] version requirement equal the tag; runs cargo test --locked --workspace + cargo fmt --check.
  • build-{android,ios,wasm,flutter} — cross-compile native libs and run each binding codegen. Android uploads libel_ffi.so, iOS uploads libel_ffi.a.
  • assemble-{npm,flutter} — bundle the generated bindings together with the native libraries into the distributable packages. assemble-flutter runs dart pub publish --dry-run as a validation gate.
  • publish-crates — gated on both assembly jobs, so the immutable crates.io registry is the last thing validated before any publish. Publishes 11 crates in dependency order, polling the crates.io index between tiers instead of fixed sleeps.
  • publish-npm needs publish-crates; publish-pub needs publish-npm — strict crates → npm → pub serialization so a mid-pipeline failure can't leave registries diverged.

Cargo manifests

  • All internal crate deps centralized in [workspace.dependencies] with both path and version — the single source of truth for registry version requirements. Member crates use { workspace = true } with no inline internal-dep versions, so cargo set-version --workspace bumps everything atomically and cargo publish can rewrite path deps to registry deps.

ADR-011 marked accepted.

Required secrets

Configure in Settings → Secrets and variables → Actions before the first release:

Secret Purpose
CARGO_REGISTRY_TOKEN crates.io API token
NPM_TOKEN npm publish token
PUB_CREDENTIALS full JSON from ~/.config/dart/pub-credentials.json

How to cut a release

cargo install cargo-edit          # one-time
cargo set-version --workspace 0.2.0
git commit -am "chore: release 0.2.0"
git tag v0.2.0 && git push --tags

Verification

  • cargo check --locked --workspace passes — Cargo.lock unchanged (only version constraints added; resolved versions identical).
  • YAML validated; job graph confirmed acyclic with publish-crates transitively gated behind all four build jobs + both assembly jobs.
  • Version-guard script smoke-tested: accepts a matching tag, rejects a stale bump with a cargo set-version fix hint.

Review trail

Addresses prior review rounds: internal-dep version requirements, serialized publish ordering, npm package name/contents, token scoping, YAML block-scalar fix, index-poll vs. fixed sleeps, native libs bundled into mobile packages, and crates.io gated behind assembly/dry-run validation.

🤖 Generated with Claude Code

Tovli and others added 3 commits June 13, 2026 12:42
Implements the release pipeline from ADR-011: a tag-triggered workflow that
publishes the SDK to all three registries from a single semver tag.

Workflow (.github/workflows/release.yml):
  verify -> build artefacts (parallel) -> assemble packages -> publish (serial)

- verify: extracts semver from tag, asserts [workspace.package].version AND
  every [workspace.dependencies] version requirement equal the tag, runs
  cargo test --locked --workspace and cargo fmt --check.
- build-{android,ios,wasm,flutter}: cross-compile native libs + run binding
  codegen; android also uploads libel_ffi.so, ios uploads libel_ffi.a.
- assemble-{npm,flutter}: bundle generated bindings WITH native libraries into
  the distributable packages; assemble-flutter runs `dart pub publish --dry-run`
  as a validation gate.
- publish-crates: gated on BOTH assembly jobs so the immutable crates.io
  registry is the last thing validated; publishes 11 crates in dependency
  order, polling the crates.io index between tiers instead of fixed sleeps.
- publish-npm needs publish-crates; publish-pub needs publish-npm — strict
  crates -> npm -> pub serialization so a mid-pipeline failure cannot leave the
  registries diverged.

Cargo manifests:
- Centralize ALL internal crate deps in [workspace.dependencies] with both
  path and version, the single source of truth for registry version
  requirements. Member crates reference them via `{ workspace = true }` and
  carry no inline internal-dep versions, so `cargo set-version --workspace`
  updates everything atomically and `cargo publish` can rewrite path deps.

ADR-011 marked accepted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Tovli Tovli merged commit 6963c06 into master Jun 14, 2026
5 checks passed
@Tovli Tovli deleted the ci/creat-publish-package-workflow branch June 14, 2026 10:09
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