1 name: CLI Release NPM
2
3 on:
4 workflow_dispatch:
5 inputs:
6 tag:
7 description: "Release tag (e.g. v0.3.39)"
8 required: true
9
10 permissions:
11 id-token: write
12 contents: read
13
14 env:
15 CLI_CLIENT_SECRET: ${{ secrets.CLI_CLIENT_SECRET }}
16
17 jobs:
18 publish-npm-binaries:
19 name: Publish NPM packages
20 runs-on: ${{ matrix.build.OS }}
21 strategy:
22 fail-fast: false
23 matrix:
24 build:
25 - {
26 NAME: linux-x64-glibc,
27 OS: ubuntu-latest,
28 TARGET: x86_64-unknown-linux-gnu,
29 }
30 - {
31 NAME: linux-arm64-glibc,
32 OS: ubuntu-24.04-arm,
33 TARGET: aarch64-unknown-linux-gnu,
34 }
35 - {
36 NAME: win32-x64-msvc,
37 OS: windows-2022,
38 TARGET: x86_64-pc-windows-msvc,
39 }
40 - {
41 NAME: win32-arm64-msvc,
42 OS: windows-2022,
43 TARGET: aarch64-pc-windows-msvc,
44 }
45 - {
46 NAME: darwin-x64,
47 OS: macos-15-intel,
48 TARGET: x86_64-apple-darwin,
49 }
50 - {
51 NAME: darwin-arm64,
52 OS: macos-latest,
53 TARGET: aarch64-apple-darwin,
54 }
55 steps:
56 - name: Checkout
57 uses: actions/checkout@v6
58 with:
59 ref: ${{ github.event.inputs.tag || github.ref }}
60
61 - name: Set the release version
62 shell: bash
63 run: |
64 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
65 release_version="${GITHUB_REF_NAME#v}"
66 else
67 release_version="${{ github.event.inputs.tag }}"
68 release_version="${release_version#v}"
69 fi
70
71 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
72
73 - name: Read Rust toolchain
74 shell: bash
75 run: |
76 rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
77 if [ -z "$rust_toolchain" ]; then
78 echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
79 exit 1
80 fi
81
82 echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
83
84 - name: Install toolkit
85 uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
86 with:
87 toolchain: ${{ env.RUST_TOOLCHAIN }}
88
89 - name: Install Rust target
90 shell: bash
91 run: |
92 rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
93 rustup target list --installed
94
95 - name: Build
96 env:
97 GH_OAUTH_CLIENT_ID: ${{ secrets.GH_OAUTH_CLIENT_ID }}
98 GH_OAUTH_CLIENT_SECRET: ${{ secrets.GH_OAUTH_CLIENT_SECRET }}
99 GH_OAUTH_REDIRECT_URI: ${{ secrets.GH_OAUTH_REDIRECT_URI }}
100 shell: bash
101 run: |
102 cargo build --release --locked --target ${{ matrix.build.TARGET }} --package smbcloud-cli
103
104 - name: Install node
105 uses: actions/setup-node@v6
106 with:
107 node-version-file: .nvmrc
108 registry-url: "https://registry.npmjs.org"
109
110 - name: Publish to NPM
111 shell: bash
112 run: |
113 # We want to name our npm package @smbcloud/cli, but the main command is smb.
114 # This is the tricky part. All the optional dependencies should follow the naming convention.
115 # So, we will generate @smbcloud/cli-${matrix.build.TARGET}
116
117 # Move to the npm directory
118 cd npm
119 # set the binary name, this is from the rust Cargo.toml file
120 cargo_bin="smb"
121 node_pkg_prefix="cli"
122 # derive the OS and architecture from the build matrix name
123 # note: when split by a hyphen, first part is the OS and the second is the architecture
124 node_os=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f1)
125 export node_os
126 node_arch=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f2)
127 export node_arch
128 # set the version
129 export node_version="${{ env.RELEASE_VERSION }}"
130 # set the package name
131 # note: use 'windows' as OS name instead of 'win32'
132 if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
133 export node_pkg="${node_pkg_prefix}-windows-${node_arch}"
134 else
135 export node_pkg="${node_pkg_prefix}-${node_os}-${node_arch}"
136 fi
137 # create the package directory
138 mkdir -p "${node_pkg}/bin"
139 # generate package metadata
140 node ./scripts/render-platform-package.cjs "${node_pkg}" "${node_version}" "${node_os}" "${node_arch}"
141 # copy the binary into the package
142 # note: windows binaries has '.exe' extension
143 if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
144 cargo_bin="${cargo_bin}.exe"
145 fi
146 cp "../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
147 # publish the package
148 cd "${node_pkg}"
149 npm_package_name="@smbcloud/${node_pkg}"
150 if npm view "${npm_package_name}@${node_version}" version >/dev/null 2>&1; then
151 echo "${npm_package_name}@${node_version} already exists on npm, skipping publish"
152 exit 0
153 fi
154 npm publish --access public
155
156 publish-npm-base:
157 name: Publish the base NPM package
158 needs: publish-npm-binaries
159 runs-on: ubuntu-latest
160 steps:
161 - name: Checkout
162 uses: actions/checkout@v6
163 with:
164 ref: ${{ github.event.inputs.tag || github.ref }}
165
166 - name: Set the release version
167 shell: bash
168 run: |
169 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
170 release_version="${GITHUB_REF_NAME#v}"
171 else
172 release_version="${{ github.event.inputs.tag }}"
173 release_version="${release_version#v}"
174 fi
175
176 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
177
178 - name: Install node
179 uses: actions/setup-node@v6
180 with:
181 node-version-file: .nvmrc
182 registry-url: "https://registry.npmjs.org"
183
184 - name: Publish the package
185 shell: bash
186 run: |
187 cd npm/smbcloud-cli
188
189 node ../scripts/render-main-package.cjs "./package.json" "${{ env.RELEASE_VERSION }}"
190
191 npm_package_name="@smbcloud/cli"
192 npm_package_version="${{ env.RELEASE_VERSION }}"
193 if npm view "${npm_package_name}@${npm_package_version}" version >/dev/null 2>&1; then
194 echo "${npm_package_name}@${npm_package_version} already exists on npm, skipping publish"
195 exit 0
196 fi
197
198 npm install
199 npm run build
200 npm publish --access public