@smbcloud / cli / commits / 633e60a

Automate NPM package metadata generation in release workflow

Replace envsubst templating with Node scripts for package.json and README.md. Set release version using tag or Cargo.toml. Switch to npm for install/build.

Seto Elkahfi committed Mar 28, 2026 at 19:24 UTC 633e60aa40645195b9547d9d7f8ff70d205f5980
3 files changed +152 -14
.github/workflows/release-npm.yml
+22 -14
@@ -19,7 +19,7 @@ env:
19 jobs:
20 publish-npm-binaries:
21 name: Publish NPM packages
22 - runs-on: ${{ matrix.build.os }}
22 + runs-on: ${{ matrix.build.OS }}
23 strategy:
24 fail-fast: false
25 matrix:
@@ -67,7 +67,14 @@ jobs:
67
68 - name: Set the release version
69 shell: bash
70 - run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV
70 + run: |
71 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
72 + release_version="${GITHUB_REF_NAME#v}"
73 + else
74 + release_version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/cli/Cargo.toml | head -n 1)"
75 + fi
76 +
77 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
78
79 - name: Install toolkit
80 uses: dtolnay/rust-toolchain@master
@@ -125,10 +132,8 @@ jobs:
132 fi
133 # create the package directory
134 mkdir -p "${node_pkg}/bin"
128 - # generate package.json from the template
129 - envsubst < package.json.tmpl > "${node_pkg}/package.json"
130 - # generate readme.md from the template
131 - envsubst < README.md.tmpl > "${node_pkg}/README.md"
135 + # generate package metadata
136 + node ./scripts/render-platform-package.cjs "${node_pkg}" "${node_version}" "${node_os}" "${node_arch}"
137 # copy the binary into the package
138 # note: windows binaries has '.exe' extension
139 if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
@@ -151,7 +156,14 @@ jobs:
156
157 - name: Set the release version
158 shell: bash
154 - run: echo "RELEASE_VERSION=${GITHUB_REF:11}" >> $GITHUB_ENV
159 + run: |
160 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
161 + release_version="${GITHUB_REF_NAME#v}"
162 + else
163 + release_version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/cli/Cargo.toml | head -n 1)"
164 + fi
165 +
166 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
167
168 - name: Install node
169 uses: actions/setup-node@v6
@@ -164,14 +176,10 @@ jobs:
176 run: |
177 cd npm/smbcloud-cli
178
167 - # set the version
168 - export release_version="${{ env.RELEASE_VERSION }}"
169 -
170 - # use the tag version
171 - envsubst < ../package-main.json.tmpl > "./package.json"
179 + node ../scripts/render-main-package.cjs "./package.json" "${{ env.RELEASE_VERSION }}"
180
173 - yarn install # requires optional dependencies to be present in the registry
174 - yarn build
181 + npm install
182 + npm run build
183 npm publish --access public
184 env:
185 NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
npm/scripts/render-main-package.cjs new
+78
@@ -0,0 +1,78 @@
1 +#!/usr/bin/env node
2 +
3 +const fs = require("fs");
4 +const path = require("path");
5 +
6 +const [outputPath, version] = process.argv.slice(2);
7 +
8 +if (!outputPath || !version) {
9 + throw new Error("Usage: render-main-package.cjs <output-path> <version>");
10 +}
11 +
12 +const packageJson = {
13 + name: "@smbcloud/cli",
14 + version,
15 + keywords: [
16 + "smbcloud",
17 + "cli",
18 + "smb",
19 + "pndk",
20 + "smbcloud-cli",
21 + "cloud",
22 + "smbcloud",
23 + "developer",
24 + "tools",
25 + "web3",
26 + "web3js",
27 + "web3.js",
28 + "web3js",
29 + "bitcoin",
30 + "btc",
31 + "ethereum",
32 + "solana",
33 + "eth",
34 + "sol",
35 + "blockchain",
36 + "smart-contracts",
37 + "dapps",
38 + "dapp",
39 + "dapp-tools",
40 + "dapp-tool",
41 + "dapp-toolkit",
42 + "dapp-toolkit-cli",
43 + ],
44 + bin: {
45 + smb: "lib/index.js",
46 + },
47 + files: ["lib", "README.md"],
48 + description: "A CLI for accessing the smbCloud platform.",
49 + license: "Apache-2.0",
50 + repository: {
51 + type: "git",
52 + url: "git+https://github.com/smbcloudXYZ/smbcloud-cli.git",
53 + },
54 + scripts: {
55 + typecheck: "tsc --noEmit",
56 + lint: "eslint .",
57 + "lint:fix": "eslint . --fix",
58 + build: "tsc",
59 + dev: "npm run build && node lib/index.js",
60 + },
61 + devDependencies: {
62 + "@types/node": "^18.15.11",
63 + "@typescript-eslint/eslint-plugin": "^5.48.0",
64 + "@typescript-eslint/parser": "^5.48.0",
65 + eslint: "^8.31.0",
66 + typescript: "^5.0.0",
67 + },
68 + optionalDependencies: {
69 + "@smbcloud/cli-darwin-arm64": version,
70 + "@smbcloud/cli-darwin-x64": version,
71 + "@smbcloud/cli-linux-x64": version,
72 + "@smbcloud/cli-windows-arm64": version,
73 + "@smbcloud/cli-windows-x64": version,
74 + },
75 +};
76 +
77 +fs.writeFileSync(path.resolve(outputPath), `${JSON.stringify(packageJson, null, 2)}
78 +`);
npm/scripts/render-platform-package.cjs new
+52
@@ -0,0 +1,52 @@
1 +#!/usr/bin/env node
2 +
3 +const fs = require("fs");
4 +const path = require("path");
5 +
6 +const [packageName, version, operatingSystem, architecture] = process.argv.slice(2);
7 +
8 +if (!packageName || !version || !operatingSystem || !architecture) {
9 + throw new Error(
10 + "Usage: render-platform-package.cjs <package-name> <version> <os> <arch>"
11 + );
12 +}
13 +
14 +const packageDirectory = path.resolve(__dirname, "..", packageName);
15 +
16 +fs.mkdirSync(packageDirectory, { recursive: true });
17 +
18 +const packageJson = {
19 + name: `@smbcloud/${packageName}`,
20 + version,
21 + description: "Platform binary for the smbCloud CLI.",
22 + license: "Apache-2.0",
23 + repository: {
24 + type: "git",
25 + url: "git+https://github.com/smbcloudXYZ/smbcloud-cli.git",
26 + },
27 + keywords: [
28 + packageName,
29 + "cli",
30 + "binary",
31 + "node",
32 + "nodejs",
33 + "npm",
34 + "package",
35 + "smbcloud",
36 + ],
37 + os: [operatingSystem],
38 + cpu: [architecture],
39 + files: ["bin"],
40 +};
41 +
42 +const readme = `# ${packageName}
43 +
44 +Not meant to be used directly. Please see [@smbcloud/cli](https://www.npmjs.com/package/@smbcloud/cli).
45 +`;
46 +
47 +fs.writeFileSync(
48 + path.join(packageDirectory, "package.json"),
49 + `${JSON.stringify(packageJson, null, 2)}
50 +`
51 +);
52 +fs.writeFileSync(path.join(packageDirectory, "README.md"), readme);