From b2aecb71610fb35b22c0086a68e6ef8876accb77 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 12 Aug 2026 14:05:04 +0000 Subject: [PATCH 1/2] Adopt @fairmint/canton-dev-tools 0.1.7 for release tooling Bump the CDT pin and replace local prepare-release/collapse-manifest scripts with the shared CLI; LocalNet wrappers stay unchanged. Co-authored-by: hardlydiff --- .cursor/skills/localnet-testing/SKILL.md | 2 +- AGENTS.md | 4 +- README.md | 2 +- docs/package-boundary.md | 2 +- package.json | 6 +- scripts/collapse-manifest.ts | 66 ------- scripts/prepare-release.ts | 222 ----------------------- 7 files changed, 8 insertions(+), 296 deletions(-) delete mode 100644 scripts/collapse-manifest.ts delete mode 100644 scripts/prepare-release.ts diff --git a/.cursor/skills/localnet-testing/SKILL.md b/.cursor/skills/localnet-testing/SKILL.md index 86739369..a829c36d 100644 --- a/.cursor/skills/localnet-testing/SKILL.md +++ b/.cursor/skills/localnet-testing/SKILL.md @@ -3,7 +3,7 @@ Read the public [LocalNet guide](https://github.com/Fairmint/canton-node-sdk/wiki/LocalNet-testing) first. -**ENG-1635:** `@fairmint/canton-dev-tools@0.1.1+` owns LocalNet lifecycle, pins, and shared test +**ENG-1635:** `@fairmint/canton-dev-tools@0.1.7+` owns LocalNet lifecycle, pins, and shared test helpers. This repository does not ship LocalNet scripts or a `canton-localnet` binary. - Commands: `npm run localnet:*` (wired to `canton-dev-tools`) or diff --git a/AGENTS.md b/AGENTS.md index a50377a2..51df8a3f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,14 +3,14 @@ See [CLAUDE.md](CLAUDE.md), [README.md](README.md), and `.cursor/skills/localnet-testing/SKILL.md`. `package.json` (`localnet:*` scripts) is the source of truth for LocalNet commands in this repo; lifecycle is owned by -`@fairmint/canton-dev-tools@0.1.1+`. +`@fairmint/canton-dev-tools@0.1.7+`. ## LocalNet ownership (ENG-1635) **`@fairmint/canton-dev-tools` owns LocalNet** (CLI, pins, and shared test helpers). This SDK does not ship a LocalNet engine or `canton-localnet` binary. -- Install pin: `devDependency` `@fairmint/canton-dev-tools@0.1.1` (exact). +- Install pin: `devDependency` `@fairmint/canton-dev-tools@0.1.7` (exact). - Repo scripts: `npm run localnet:*` → `canton-dev-tools `. - Integration helpers: import from `@fairmint/canton-dev-tools/testing`. - Pins / auth defaults: see Dev Tools diff --git a/README.md b/README.md index 0fdfe7bf..100fee4d 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ npm run build ### LocalNet (owned by `@fairmint/canton-dev-tools`) LocalNet lifecycle and shared test helpers live in -[`@fairmint/canton-dev-tools@0.1.1`](https://www.npmjs.com/package/@fairmint/canton-dev-tools) +[`@fairmint/canton-dev-tools@0.1.7`](https://www.npmjs.com/package/@fairmint/canton-dev-tools) (see its [COMPATIBILITY.md](https://github.com/Fairmint/canton-dev-tools/blob/main/COMPATIBILITY.md)). This SDK does not publish a LocalNet CLI or `scripts/localnet-cloud.sh`. diff --git a/docs/package-boundary.md b/docs/package-boundary.md index 127d27c3..ca7b338c 100644 --- a/docs/package-boundary.md +++ b/docs/package-boundary.md @@ -13,7 +13,7 @@ repository / CI-only. Repeatable enforcement lives in `npm run check:package-art LocalNet CLI and shared integration-test helpers are **not** published here. They live in [`@fairmint/canton-dev-tools`](https://www.npmjs.com/package/@fairmint/canton-dev-tools) -(`0.1.1+`), including `scripts/localnet-cloud.sh` and `@fairmint/canton-dev-tools/testing`. +(`0.1.7+`), including `scripts/localnet-cloud.sh` and `@fairmint/canton-dev-tools/testing`. ## CI-only / must not publish diff --git a/package.json b/package.json index ff44518f..b20b9db8 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "build/src/**" ], "scripts": { - "artifacts:manifest": "mkdir -p artifacts && npm pack --dry-run --json --ignore-scripts > /tmp/npm-pack.json 2>/dev/null && jq -r '.[0].files[].path' /tmp/npm-pack.json | sort | tsx scripts/collapse-manifest.ts > artifacts/npm-manifest.txt", + "artifacts:manifest": "mkdir -p artifacts && npm pack --dry-run --json --ignore-scripts > /tmp/npm-pack.json 2>/dev/null && jq -r '.[0].files[].path' /tmp/npm-pack.json | sort | canton-dev-tools collapse-manifest > artifacts/npm-manifest.txt", "build": "npm run build:core && npm run build:lint", "build:core": "npm run generate:openapi-types && npm run build:core:generate-client-methods && npm run tsc7", "build:core:generate-client-methods": "tsx scripts/generate-all-client-methods.ts", @@ -54,7 +54,7 @@ "localnet:teardown": "canton-dev-tools teardown", "localnet:verify": "canton-dev-tools verify", "prepack": "npm run clean && npm run build:core", - "prepare-release": "tsx scripts/prepare-release.ts", + "prepare-release": "canton-dev-tools prepare-release", "prepublishOnly": "npm run prepack", "revoke-user-rights": "tsx scripts/revoke-user-rights.ts", "test": "jest", @@ -79,7 +79,7 @@ "zod": "4.4.3" }, "devDependencies": { - "@fairmint/canton-dev-tools": "0.1.1", + "@fairmint/canton-dev-tools": "0.1.7", "@types/jest": "30.0.0", "@types/node": "26.1.0", "@types/ws": "8.18.1", diff --git a/scripts/collapse-manifest.ts b/scripts/collapse-manifest.ts deleted file mode 100644 index fec8ace2..00000000 --- a/scripts/collapse-manifest.ts +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env tsx - -/** - * Collapse TypeScript manifest by removing mapping files and collapsing extensions - * - * This script reads file paths from stdin and outputs a simplified manifest that removes .d.ts.map and .js.map files - * and collapses .d.ts and .js files into single entries without extensions. - */ - -import { readFileSync } from 'fs'; - -function collapseManifest(): void { - try { - // Read all lines from stdin - const input = readFileSync(0, 'utf-8'); - - const lines = input - .trim() - .split('\n') - .filter((line) => line.length > 0); - - // Exit with error if no files found - if (lines.length === 0) { - process.exit(1); - } - - // Track files to exclude (mapping files) - const filesToExclude = new Set(); - const filesToKeep = new Set(); - const collapsedFiles = new Set(); - - // First pass: identify mapping files and their corresponding main files - for (const line of lines) { - if (line.endsWith('.d.ts.map') || line.endsWith('.js.map')) { - filesToExclude.add(line); - } else { - filesToKeep.add(line); - } - } - - // Second pass: collapse .d.ts and .js files into single entries - for (const file of filesToKeep) { - if (file.endsWith('.d.ts') || file.endsWith('.js')) { - // Remove the extension to get the base name - const baseName = file.replace(/\.(d\.ts|js)$/, ''); - collapsedFiles.add(baseName); - } else { - // Keep non-TypeScript/JavaScript files as-is - collapsedFiles.add(file); - } - } - - // Output the collapsed files in sorted order - const sortedFiles = Array.from(collapsedFiles).sort(); - - for (const file of sortedFiles) { - console.log(file); - } - } catch (_error) { - console.error('Error collapsing manifest:', _error); - process.exit(1); - } -} - -// Run the script -collapseManifest(); diff --git a/scripts/prepare-release.ts b/scripts/prepare-release.ts deleted file mode 100644 index fa86a3b1..00000000 --- a/scripts/prepare-release.ts +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env node - -/** - * Prepare Release Script - * - * Prepares a new release by incrementing version and generating changelog. - * - * Usage: npm run prepare-release - * - * Features: - * - * - Increments patch version in package.json - * - Checks both npm registry and git tags to determine next version - * - Creates changelog from commits since last tag - * - Links commits to GitHub PRs - * - Safe for local testing (no git operations) - * - Saves changelog to CHANGELOG.md - */ - -import { execSync } from 'child_process'; -import fs from 'fs'; -import path from 'path'; - -interface PackageJson { - name: string; - version: string; - [key: string]: unknown; -} - -/** Check if a git tag exists */ -function tagExists(tag: string): boolean { - try { - execSync(`git rev-parse "refs/tags/${tag}"`, { stdio: 'ignore' }); - return true; - } catch { - return false; - } -} - -/** Get the latest version from npm registry */ -function getNpmLatestVersion(packageName: string): string | null { - try { - const version = execSync(`npm view ${packageName} version 2>/dev/null`, { - encoding: 'utf8', - }).trim(); - return version || null; - } catch { - return null; - } -} - -/** Check if a version exists on npm registry */ -function npmVersionExists(packageName: string, version: string): boolean { - try { - const versions = execSync(`npm view ${packageName} versions --json 2>/dev/null`, { - encoding: 'utf8', - }); - const versionList = JSON.parse(versions) as string[]; - return versionList.includes(version); - } catch { - return false; - } -} - -/** Parse version string into components */ -function parseVersion(version: string): { major: number; minor: number; patch: number } | null { - const parts = version.split('.').map(Number); - if (parts.length !== 3 || parts.some(isNaN)) { - return null; - } - const major = parts[0]; - const minor = parts[1]; - const patch = parts[2]; - if (major === undefined || minor === undefined || patch === undefined) { - return null; - } - return { major, minor, patch }; -} - -/** Find the next available version by checking both git tags and npm registry */ -function findNextAvailableVersion(packageName: string, major: number, minor: number, startPatch: number): string { - let patch = startPatch; - let version: string; - - do { - patch++; - version = `${major}.${minor}.${patch}`; - } while (tagExists(`v${version}`) || npmVersionExists(packageName, version)); - - return version; -} - -/** Get the highest version from git tags and npm, then find next available */ -function determineNextVersion(packageName: string, currentVersion: string): string { - const current = parseVersion(currentVersion); - if (!current) { - throw new Error(`Invalid version format: ${currentVersion}`); - } - - // Get latest version from npm registry - const npmVersion = getNpmLatestVersion(packageName); - const npm = npmVersion ? parseVersion(npmVersion) : null; - - // Get latest version from git tags - let gitVersion: string | null = null; - try { - gitVersion = execSync('git describe --tags --abbrev=0 2>/dev/null', { - encoding: 'utf8', - }).trim(); - if (gitVersion.startsWith('v')) { - gitVersion = gitVersion.slice(1); - } - } catch { - gitVersion = null; - } - const git = gitVersion ? parseVersion(gitVersion) : null; - - // Determine the highest patch version among current, npm, and git - let highestPatch = current.patch; - - if (npm?.major === current.major && npm.minor === current.minor) { - highestPatch = Math.max(highestPatch, npm.patch); - } - - if (git?.major === current.major && git.minor === current.minor) { - highestPatch = Math.max(highestPatch, git.patch); - } - - console.log(`Current version: ${currentVersion}`); - console.log(`NPM latest version: ${npmVersion ?? 'not found'}`); - console.log(`Git latest tag: ${gitVersion ? `v${gitVersion}` : 'not found'}`); - console.log(`Highest patch in ${current.major}.${current.minor}.x: ${highestPatch}`); - - // Find next available version starting from the highest - return findNextAvailableVersion(packageName, current.major, current.minor, highestPatch); -} - -/** - * Prepare release by incrementing version and generating changelog This script can be run locally to test the release - * process - */ -function prepareRelease(): void { - try { - // Read package.json - const packageJsonPath: string = path.join(process.cwd(), 'package.json'); - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as PackageJson; - - const currentVersion: string = packageJson.version; - const packageName: string = packageJson.name; - - // Find next available version by checking both npm and git tags - const newVersion: string = determineNextVersion(packageName, currentVersion); - - // Update version in package.json (without git tag) - packageJson.version = newVersion; - fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`); - - // Generate changelog since last tag or main branch - let commits: string; - let lastTag: string | null = null; - try { - lastTag = execSync('git describe --tags --abbrev=0 2>/dev/null', { - encoding: 'utf8', - }).trim(); - - commits = execSync(`git log --oneline --format="%s" ${lastTag}..HEAD`, { - encoding: 'utf8', - }).trim(); - } catch { - // No previous tag, get commits ahead of main branch - - commits = execSync('git log --oneline --format="%s" main..HEAD', { - encoding: 'utf8', - }).trim(); - } - - if (!commits) { - return; - } - - // Extract PR numbers and create changelog - const commitLines: string[] = commits.split('\n').map((commit: string): string => `- ${commit}`); - - const changelog: string = commitLines.join('\n'); - - // Create detailed tag message - const _tagMessage = `Release v${newVersion}\n\nChanges:\n${changelog}`; - - console.log('Release tag prepared:', _tagMessage); - - // Save changelog to file for reference - const changelogPath: string = path.join(process.cwd(), 'CHANGELOG.md'); - - // Add previous version link if available - const previousVersionLink: string = lastTag - ? `\n[Previous version: ${lastTag}](https://github.com/Fairmint/canton-node-sdk/releases/tag/${lastTag})` - : ''; - - const changelogContent = `# Changelog for v${newVersion}\n\n${changelog}${previousVersionLink}\n\n`; - - // Prepend to existing changelog if it exists - if (fs.existsSync(changelogPath)) { - const existingChangelog: string = fs.readFileSync(changelogPath, 'utf8'); - fs.writeFileSync(changelogPath, changelogContent + existingChangelog); - } else { - fs.writeFileSync(changelogPath, changelogContent); - } - - console.log('Changelog updated successfully'); - console.log('Release preparation complete'); - } catch (_error) { - console.error('Error preparing release:', _error); - process.exit(1); - } -} - -// Run the script -if (require.main === module) { - prepareRelease(); -} - -export { prepareRelease }; From 79ed1861abf2b5ecae7751862ac0fadf6ca8533b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 12 Aug 2026 14:24:58 +0000 Subject: [PATCH 2/2] fix: map LocalNet npm scripts to CDT 0.1.7 CLI 0.1.7 dropped smoke/logs/stop/setup/status/verify aliases. Point legacy npm script names at readiness/diagnostics/teardown and update the CN-Quickstart workflow accordingly. Co-authored-by: hardlydiff --- .github/workflows/test-cn-quickstart.yml | 4 ++-- AGENTS.md | 7 ++++--- README.md | 7 +++++-- package.json | 11 ++++------- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test-cn-quickstart.yml b/.github/workflows/test-cn-quickstart.yml index aa6ff899..a0ad8e87 100644 --- a/.github/workflows/test-cn-quickstart.yml +++ b/.github/workflows/test-cn-quickstart.yml @@ -124,10 +124,10 @@ jobs: - name: Run LocalNet Smoke + Integration Tests run: | echo "Running tests..." - npm run localnet:smoke + npm run localnet:readiness npm run test:integration echo "✓ Tests passed!" - name: Show Logs on Failure if: failure() - run: npm run localnet:logs + run: npm run localnet:diagnostics diff --git a/AGENTS.md b/AGENTS.md index 51df8a3f..c483ce3d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -39,11 +39,12 @@ Prerequisites (on demand — heavy, not in the dashboard update script): git submodule update --init --recursive --depth 1 libs/cn-quickstart git submodule update --init --depth 1 libs/splice npm install -npm run localnet:start # first run ~10-15 min: image pulls + Splice DSO bootstrap -npm run localnet:smoke # Keycloak/Validator/Scan/Ledger reachability -npm run localnet:stop +npm run localnet:start # first run ~10-15 min: image pulls + Splice DSO bootstrap +npm run localnet:readiness # Keycloak/Validator/Scan/Ledger reachability (alias: smoke) +npm run localnet:teardown # alias: stop ``` + Verified ready endpoints: Ledger JSON API `http://localhost:3975/v2/version` (returned `3.5.4`), Scan `http://scan.localhost:4000/api/scan/v0/dso-party-id` (returns the DSO party id), Validator `http://localhost:3903/...` (200/401). diff --git a/README.md b/README.md index 100fee4d..86376dcc 100644 --- a/README.md +++ b/README.md @@ -54,13 +54,16 @@ This SDK does not publish a LocalNet CLI or `scripts/localnet-cloud.sh`. ```bash npm install # installs @fairmint/canton-dev-tools as an exact-pinned devDependency npm run localnet:start -npm run localnet:smoke -npm run localnet:stop +npm run localnet:readiness # alias: localnet:smoke +npm run localnet:teardown # alias: localnet:stop # Or call the Dev Tools CLI directly: npx @fairmint/canton-dev-tools start +npx @fairmint/canton-dev-tools readiness +npx @fairmint/canton-dev-tools teardown ``` + Integration helpers: ```ts diff --git a/package.json b/package.json index b20b9db8..561b44f4 100644 --- a/package.json +++ b/package.json @@ -43,16 +43,13 @@ "lint:npm": "npmPkgJsonLint . --fix", "lint:npm:check": "npmPkgJsonLint .", "localnet:diagnostics": "canton-dev-tools diagnostics", - "localnet:logs": "canton-dev-tools logs", - "localnet:quickstart": "canton-dev-tools setup", + "localnet:logs": "canton-dev-tools diagnostics", "localnet:readiness": "canton-dev-tools readiness", - "localnet:setup": "canton-dev-tools setup", - "localnet:smoke": "canton-dev-tools smoke", + "localnet:smoke": "canton-dev-tools readiness", "localnet:start": "canton-dev-tools start", - "localnet:status": "canton-dev-tools status", - "localnet:stop": "canton-dev-tools stop", + "localnet:stop": "canton-dev-tools teardown", "localnet:teardown": "canton-dev-tools teardown", - "localnet:verify": "canton-dev-tools verify", + "localnet:verify": "npm run localnet:start && npm run localnet:readiness && npm run test:localnet", "prepack": "npm run clean && npm run build:core", "prepare-release": "canton-dev-tools prepare-release", "prepublishOnly": "npm run prepack",