-
Notifications
You must be signed in to change notification settings - Fork 0
Establish @fairmint/canton-dev-tools with LocalNet CLI and test helpers (ENG-1635 PR1) #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
HardlyDifficult
merged 19 commits into
main
from
cursor/establish-canton-dev-tools-5279
Aug 10, 2026
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
a7ce617
Establish canton-dev-tools package with LocalNet CLI and test helpers
cursoragent c2efb4b
Apply central LocalNet pins on CLI path and scaffold DAR fixture
cursoragent bf32f24
Add CIP-56/CIP-112 Splice TestTokenV2 fixture path (no-Docker)
cursoragent 26d09fa
Document ENG-1635 SDK package-boundary audit
cursoragent a5d5a4d
Link ENG-1635 pack-guard and soft-migration PRs in audit
cursoragent b6d8a42
Implement LocalNet CIP-56/CIP-112 TestTokenV2 transfer smoke
cursoragent 37a626c
Fix localnet npm script to invoke bash CLI
cursoragent 7b37129
Fix LocalNet CIP-56 smoke party auth and Accept visibility
cursoragent 1f3ae43
Remove private SDK boundary audit from public docs
cursoragent fd65e8e
Fix Bugbot/Copilot LocalNet client and CLI issues
cursoragent bb4aa66
Keep OAuth auth for URL-only LocalNet config overrides
cursoragent 474275f
Fix Daml Numeric formatting and align LocalNet pins
cursoragent 17e0e07
Fix tip review findings for decimals and public docs
cursoragent cac1de0
Fail closed when dpm is missing for DAR fixture build
cursoragent d96ad22
Clean up quickstart temp dir on checkout failure
cursoragent e83cd9b
Add OIDC auto-publish workflow for npm on main
cursoragent 9bdb80e
Fix healthcheck set flags so errexit actually enables
cursoragent 7f6d2c1
Retry createParty through LocalNet Validator traffic 429s
cursoragent 9d83dfd
Fix OIDC publish auth and first-release changelog
cursoragent File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| build-and-test: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 15 | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22' | ||
| registry-url: 'https://registry.npmjs.org' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
|
||
| - name: Lint | ||
| run: npm run lint | ||
|
|
||
| - name: Typecheck | ||
| run: npm run typecheck | ||
|
|
||
| - name: Unit tests | ||
| run: npm run test:ci | ||
|
|
||
| - name: Build | ||
| run: npm run build | ||
|
|
||
| - name: Pack and guard artifacts | ||
| run: npm run pack:check |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| name: LocalNet Smoke | ||
|
|
||
| # LocalNet lifecycle + CIP-56 transfer smoke. Intended to become a required PR check | ||
| # once Docker image caching is finalized (TODO(ENG-1635)). | ||
| # | ||
| # Tradeoff vs nightly-only: first-run image pulls dominate wall time (~10–15m) and need | ||
| # Docker/Compose + disk on the runner. We still run on pull_request so LocalNet regressions | ||
| # block merges; keep workflow_dispatch for manual re-runs. No scheduled job — PR coverage is | ||
| # the regression gate. | ||
| # | ||
| # Uses Splice TestTokenV2 (not a Fairmint token). | ||
| # | ||
| # Docker readiness notes: | ||
| # - The ubuntu-latest runner usually has Docker available via the Actions service, but LocalNet | ||
| # also needs Compose v2, passwordless sudo for host aliases / dockerd bootstrap in constrained | ||
| # environments, and enough disk for Splice image pulls. | ||
| # - First-run image pulls dominate wall time; prefer a warmed runner cache once the shared LocalNet | ||
| # image strategy is finalized (TODO(ENG-1635)). | ||
| # - Port 3000 must be free (cn-quickstart nginx binds 127.0.0.1:3000). | ||
| # - If nginx was created without a network after a failed start, remove it before retrying: | ||
| # `docker rm -f nginx`. | ||
|
|
||
| on: | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| localnet-smoke: | ||
| runs-on: ubuntu-latest | ||
| # Image pulls + DSO bootstrap + CIP-56 transfer routinely exceed 15m on a cold runner. | ||
| timeout-minutes: 45 | ||
|
|
||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '22' | ||
| registry-url: 'https://registry.npmjs.org' | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
|
||
| - name: Fetch Splice TestTokenV2 fixture DAR | ||
| run: npm run fixture:splice-test-token-v2:fetch | ||
|
|
||
| # TODO(ENG-1635): harden GH Actions Docker provisioning / image caching for LocalNet. | ||
| # This job is best-effort until the shared runner image and cache strategy are finalized. | ||
| - name: Start LocalNet | ||
| id: localnet-start | ||
| run: | | ||
| set -euo pipefail | ||
| npm run localnet:start | ||
|
|
||
| - name: Readiness | ||
| id: localnet-readiness | ||
| run: npm run localnet:readiness | ||
|
|
||
| # Prefer a real step with clear failure when LocalNet / Docker is not ready. | ||
| # Do NOT invent a Fairmint token — uses fixtures/splice-test-token-v2 (CIP-112 capable). | ||
| - name: CIP-56 / CIP-112 transfer smoke (Splice TestTokenV2) | ||
| id: cip56-transfer | ||
| run: | | ||
| set -euo pipefail | ||
| npm run localnet:cip56-transfer | ||
|
|
||
| - name: Diagnostics on failure | ||
| if: failure() | ||
| run: npm run localnet:diagnostics | ||
|
|
||
| - name: Teardown | ||
| if: always() | ||
| run: npm run localnet:teardown |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| name: Publish to NPM | ||
|
|
||
| on: | ||
| push: | ||
| branches: | ||
| - main | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| # OIDC trusted publishing on npmjs.com: | ||
| # https://www.npmjs.com/package/@fairmint/canton-dev-tools/access (Trusted Publisher section) | ||
| # — or create the package first via "Add Trusted Publisher" on the @fairmint org. | ||
| # Provider: GitHub Actions | ||
| # Repository: Fairmint/canton-dev-tools | ||
| # Workflow filename: publish.yml | ||
| # The npm CLI auto-detects the OIDC environment and exchanges the GitHub-issued id-token | ||
| # for a short-lived registry token, so no long-lived NPM_TOKEN secret is required for publish. | ||
| # | ||
| # Required to publish: id-token: write | ||
| # Required to push the git tag back: contents: write | ||
| # | ||
| # Install may still use NODE_AUTH_TOKEN (NPM_TOKEN) to fetch private @fairmint/* peers. | ||
| # Do NOT set NODE_AUTH_TOKEN / NPM_TOKEN on the Publish step — that breaks OIDC trusted publishing. | ||
|
|
||
| jobs: | ||
| publish: | ||
| runs-on: ubuntu-latest | ||
| if: github.ref == 'refs/heads/main' | ||
| permissions: | ||
| contents: write | ||
| packages: write | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v7 | ||
| with: | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| # Trusted publishing requires Node >= 22.14.0 (npm docs) | ||
| node-version: '22.14' | ||
| registry-url: 'https://registry.npmjs.org' | ||
| package-manager-cache: false | ||
|
|
||
| - name: Upgrade npm | ||
| # Trusted publishing requires npm CLI >= 11.5.1. Pin below npm 12 until | ||
| # npm@latest no longer fails OIDC publishes with a missing sigstore module | ||
| # on hosted runners (see npm/cli#8730). | ||
| run: npm install --global npm@11.18.0 | ||
|
|
||
| - name: Install dependencies | ||
| run: npm ci | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
|
|
||
| - name: Build package | ||
| run: npm run build | ||
|
|
||
| - name: Prepack and check package artifacts | ||
| run: npm run check:package-artifacts | ||
|
|
||
| - name: Prepare release | ||
| run: npm run prepare-release | ||
|
|
||
| # setup-node's registry-url writes `//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}` | ||
| # into the runner npmrc. With NODE_AUTH_TOKEN unset on this step that expands to empty and | ||
| # npm treats classic auth as configured, skipping the OIDC Trusted Publisher exchange. | ||
| - name: Clear classic npm auth for OIDC publish | ||
| run: | | ||
| npmrc="${NPM_CONFIG_USERCONFIG:-$HOME/.npmrc}" | ||
| if [[ -f "${npmrc}" ]]; then | ||
| sed -i '/_authToken/d' "${npmrc}" | ||
| fi | ||
|
|
||
| # Publishes via npm Trusted Publisher (OIDC); do not set NODE_AUTH_TOKEN here. | ||
| # Provenance is omitted: this repository may be private, and --provenance requires | ||
| # a public source repo. OIDC trusted publishing still works without provenance. | ||
| - name: Publish to NPM | ||
| run: npm publish | ||
|
cursor[bot] marked this conversation as resolved.
|
||
|
|
||
| - name: Create and push git tag | ||
| run: | | ||
| NEW_VERSION=$(node -p "require('./package.json').version") | ||
| CHANGELOG=$(head -100 CHANGELOG.md) | ||
| git config --local user.email "action@github.com" | ||
| git config --local user.name "GitHub Action" | ||
| git tag -a "v$NEW_VERSION" -m "$CHANGELOG" | ||
| git push origin "v$NEW_VERSION" | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| node_modules/ | ||
| dist/ | ||
| coverage/ | ||
| *.tgz | ||
| .DS_Store | ||
| .env | ||
| .env.local | ||
| *.log | ||
| .npmrc | ||
| libs/ | ||
| artifacts/ | ||
| fixtures/**/.daml/ | ||
| fixtures/**/*.dar |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "singleQuote": true, | ||
| "trailingComma": "es5", | ||
| "printWidth": 100, | ||
| "semi": true | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Changelog | ||
|
|
||
| Release notes are prepended here by `npm run prepare-release` on each publish to npm. |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| # LocalNet Compatibility Pins | ||
|
|
||
| `@fairmint/canton-dev-tools` is the **central owner** of Fairmint's shared Canton LocalNet pin set. | ||
|
|
||
| Consumers should prefer this package's CLI defaults in `bin/canton-dev-tools` (kept in sync with | ||
| `package.json#config` by `pack:check`) instead of maintaining divergent pins in individual SDKs. | ||
| `npm run localnet*` delegates to the binary, which applies the four pins and oauth2 auth as | ||
| defaults while preserving caller environment overrides. | ||
|
|
||
| | Pin | Config key | Current value | | ||
| | ----------------------- | --------------------------- | ------------------------------------------ | | ||
| | cn-quickstart git ref | `localnet_quickstart_ref` | `2f4edfc17621a7dfb6d44357050c22f4b3914c89` | | ||
| | Splice image tag | `localnet_splice_version` | `0.6.14` | | ||
| | Scribe image tag | `localnet_scribe_version` | `0.6.14` | | ||
| | Canton protocol version | `localnet_protocol_version` | `35` | | ||
|
|
||
| ## Why both quickstart ref and Splice version? | ||
|
|
||
| They are **not redundant** — each owns a different layer: | ||
|
|
||
| | Pin | Owns | Why it is separate | | ||
| | ----------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| | `localnet_quickstart_ref` | CN Quickstart **compose / scripts / Daml runtime wiring** (git tree) | Locks how LocalNet is brought up (ports, modules, Keycloak, `.env` defaults). | | ||
| | `localnet_splice_version` / `localnet_scribe_version` | **Container image tags** written into Quickstart `.env` via `CANTON_LOCALNET_*` | Lets us run MainNet-aligned Splice/Scribe images on an older, known-good Quickstart tree without waiting for a Quickstart bump that already embeds that tag. | | ||
|
|
||
| Quickstart's checked-in `.env` may still say `SPLICE_VERSION=0.6.11` at the pinned ref; our CLI **overrides** that with `localnet_splice_version`. Same pattern as `@fairmint/canton-assets` LocalNet docs (same Quickstart ref + MainNet Splice `0.6.14`). | ||
|
|
||
| Do not derive one from the other in this package: consumers may need to advance images before compose, or pin compose while validating a new image. | ||
|
|
||
| ## Auth mode | ||
|
|
||
| | Mode | When to use | | ||
| | --------------- | ---------------------------------------------------------------------------- | | ||
| | `oauth2` | **Package default** for `npm run localnet*` and bare CLI / `npx` invocations | | ||
| | `shared-secret` | **Consumer CI** that signs HS256 JWTs (e.g. `@fairmint/canton-fairmint-sdk`) | | ||
|
|
||
| Override with `CANTON_LOCALNET_AUTH_MODE=shared-secret` in consumer packages. Do not change the | ||
| package default to shared-secret without coordinating Keycloak / OAuth2 LocalNet smoke coverage. | ||
|
|
||
| ## Override env vars | ||
|
|
||
| These remain supported for one-off local experiments: | ||
|
|
||
| - `CANTON_LOCALNET_QUICKSTART_REF` | ||
| - `CANTON_LOCALNET_SPLICE_VERSION` | ||
| - `CANTON_LOCALNET_SCRIBE_VERSION` | ||
| - `CANTON_LOCALNET_PROTOCOL_VERSION` | ||
| - `CANTON_LOCALNET_QUICKSTART_DIR` | ||
| - `CANTON_LOCALNET_CACHE_DIR` | ||
| - `CANTON_LOCALNET_AUTH_MODE` | ||
| - `CANTON_LOCALNET_INFRA_ONLY` | ||
|
|
||
| Changing the default pins is a breaking compatibility change for shared LocalNet CI and should be reviewed as part of ENG-1635 follow-ups. | ||
|
|
||
| SDK package-boundary ownership (what ships in publish tarballs vs CI-only fixtures) is tracked via consumer PRs under [ENG-1635](https://linear.app/fairmint/issue/ENG-1635/establish-canton-dev-tools-and-migrate-shared-canton-test). |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.