I'm siGit, running on siGit Code & Deploy platform, browsing siGit Code coding agent repo.

1 name: Release npm
2
3 on:
4 push:
5 tags:
6 - "v*.*.*"
7 workflow_dispatch:
8 inputs:
9 tag:
10 description: "Release tag (e.g. v0.1.1)"
11 required: true
12
13 concurrency:
14 # A re-pushed or re-dispatched tag fires this a second time. Queue the
15 # duplicate behind the original instead of cancelling it: cancelling a run
16 # mid-publish can leave a channel half-uploaded, whereas a queued duplicate
17 # just hits the "already published" check and exits clean.
18 group: ${{ github.workflow }}-${{ github.event.inputs.tag || github.ref_name }}
19 cancel-in-progress: false
20
21 permissions:
22 id-token: write
23 contents: read
24
25 env:
26 CARGO_TERM_COLOR: always
27
28 jobs:
29 publish-npm-binaries:
30 name: Publish NPM platform packages
31 runs-on: ${{ matrix.build.OS }}
32 strategy:
33 fail-fast: false
34 matrix:
35 build:
36 - {
37 NAME: linux-x64-glibc,
38 OS: ubuntu-latest,
39 TARGET: x86_64-unknown-linux-gnu,
40 }
41 - {
42 NAME: linux-arm64-glibc,
43 OS: ubuntu-24.04-arm,
44 TARGET: aarch64-unknown-linux-gnu,
45 }
46 - {
47 NAME: win32-x64-msvc,
48 OS: windows-2022,
49 TARGET: x86_64-pc-windows-msvc,
50 }
51 - {
52 NAME: win32-arm64-msvc,
53 OS: windows-2022,
54 TARGET: aarch64-pc-windows-msvc,
55 }
56 - { NAME: darwin-x64, OS: macos-26, TARGET: x86_64-apple-darwin }
57 - { NAME: darwin-arm64, OS: macos-26, TARGET: aarch64-apple-darwin }
58
59 steps:
60 - name: Checkout
61 uses: actions/checkout@v6
62 with:
63 ref: ${{ github.event.inputs.tag || github.ref }}
64
65 - name: Set the release version
66 shell: bash
67 run: |
68 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
69 release_version="${GITHUB_REF_NAME#v}"
70 else
71 release_version="${{ github.event.inputs.tag }}"
72 release_version="${release_version#v}"
73 fi
74 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
75
76 - name: Read Rust toolchain
77 shell: bash
78 run: |
79 rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
80 if [ -z "$rust_toolchain" ]; then
81 echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
82 exit 1
83 fi
84 echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
85
86 - name: Install Rust toolchain
87 uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
88 with:
89 toolchain: ${{ env.RUST_TOOLCHAIN }}
90
91 - name: Install Rust target
92 shell: bash
93 run: |
94 rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
95 rustup target list --installed
96
97 - name: Setup Rust cache
98 uses: Swatinem/rust-cache@v2
99 with:
100 key: npm-${{ matrix.build.TARGET }}
101
102 - name: Build binary
103 if: ${{ !contains(matrix.build.TARGET, 'linux') }}
104 shell: bash
105 run: cargo build --locked --release -p sigit --target ${{ matrix.build.TARGET }}
106
107 # Built in manylinux2014 so the binary runs on glibc 2.17 and later, whatever the runner
108 # has. See packaging/linux/build-manylinux.sh.
109 - name: Build Linux binary (glibc 2.17)
110 if: contains(matrix.build.TARGET, 'linux')
111 shell: bash
112 run: ./packaging/linux/build-manylinux.sh ${{ matrix.build.TARGET }}
113
114 - name: Check Linux binary against the glibc 2.17 floor
115 if: contains(matrix.build.TARGET, 'linux')
116 shell: bash
117 run: ./packaging/linux/check-glibc.sh target/${{ matrix.build.TARGET }}/release/sigit 2.17
118
119 - name: Install Node
120 uses: actions/setup-node@v6
121 with:
122 node-version-file: .nvmrc
123 registry-url: "https://registry.npmjs.org"
124
125 # Trusted Publishing (OIDC) needs npm >= 11.5.1. .nvmrc pins the Node
126 # version (>= 22.14.0, also an OIDC requirement); npm still needs
127 # upgrading past whatever ships with it.
128 - name: Upgrade npm for Trusted Publishing
129 shell: bash
130 run: npm install -g npm@latest
131
132 # Authentication is OIDC: each @getsigit/* and @smbcloud/* package has a
133 # Trusted Publisher pointing at this workflow, so there is no token to
134 # leak. @smbcloud is the pre-1.5.5 scope, published alongside @getsigit
135 # so that an install made before the rename keeps updating.
136 - name: Publish platform package to NPM
137 shell: bash
138 run: |
139 cd packaging/npm
140
141 # Binary name from Cargo.toml
142 cargo_bin="sigit"
143
144 # Prefix used for optional dependency package names
145 node_pkg_prefix="sigit"
146
147 # Derive OS and architecture from the build matrix name
148 # Matrix name format: <os>-<arch>[-<extra>]
149 node_os=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f1)
150 export node_os
151 node_arch=$(echo "${{ matrix.build.NAME }}" | cut -d '-' -f2)
152 export node_arch
153
154 # Set the version
155 export node_version="${{ env.RELEASE_VERSION }}"
156
157 # Build the platform package name; normalise win32 → windows
158 if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
159 export node_pkg="${node_pkg_prefix}-windows-${node_arch}"
160 else
161 export node_pkg="${node_pkg_prefix}-${node_os}-${node_arch}"
162 fi
163
164 # Create the package directory
165 mkdir -p "${node_pkg}/bin"
166
167 # Windows binaries carry a .exe extension
168 if [ "${{ matrix.build.OS }}" = "windows-2022" ]; then
169 cargo_bin="${cargo_bin}.exe"
170 fi
171
172 cp "../../target/${{ matrix.build.TARGET }}/release/${cargo_bin}" "${node_pkg}/bin"
173
174 # One binary, published under both scopes: re-render package.json and
175 # README for each, from the same directory.
176 for scope in "@getsigit" "@smbcloud"; do
177 node ./scripts/render-platform-package.cjs \
178 "${node_pkg}" \
179 "${node_version}" \
180 "${node_os}" \
181 "${node_arch}" \
182 "${scope}"
183
184 npm_package_name="${scope}/${node_pkg}"
185
186 # `npm view` exits non-zero both when the version is genuinely
187 # unpublished and when the registry could not be reached, so treat
188 # only an E404 as "not published yet". Anything else stops the job
189 # instead of publishing over a version that is already there.
190 if view_output=$(npm view "${npm_package_name}@${node_version}" version 2>&1); then
191 echo "${npm_package_name}@${node_version} already exists on npm, skipping publish"
192 continue
193 elif ! grep -q "E404" <<<"${view_output}"; then
194 echo "npm view failed while checking ${npm_package_name}@${node_version}:" >&2
195 echo "${view_output}" >&2
196 exit 1
197 fi
198
199 (cd "${node_pkg}" && npm publish --access public)
200 done
201
202 publish-npm-base:
203 name: Publish base NPM packages (@getsigit/sigit, @smbcloud/sigit)
204 needs: publish-npm-binaries
205 runs-on: ubuntu-latest
206
207 steps:
208 - name: Checkout
209 uses: actions/checkout@v6
210 with:
211 ref: ${{ github.event.inputs.tag || github.ref }}
212
213 - name: Set the release version
214 shell: bash
215 run: |
216 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
217 release_version="${GITHUB_REF_NAME#v}"
218 else
219 release_version="${{ github.event.inputs.tag }}"
220 release_version="${release_version#v}"
221 fi
222 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
223
224 - name: Install Node
225 uses: actions/setup-node@v6
226 with:
227 node-version-file: .nvmrc
228 registry-url: "https://registry.npmjs.org"
229
230 # Trusted Publishing (OIDC) needs npm >= 11.5.1. .nvmrc pins the Node
231 # version (>= 22.14.0, also an OIDC requirement); npm still needs
232 # upgrading past whatever ships with it.
233 - name: Upgrade npm for Trusted Publishing
234 shell: bash
235 run: npm install -g npm@latest
236
237 - name: Publish base packages to NPM
238 shell: bash
239 run: |
240 cd packaging/npm/sigit
241
242 npm_package_version="${{ env.RELEASE_VERSION }}"
243
244 # Rewrite package.json with the correct release version and matching
245 # optionalDependency versions, then build. The compiled launcher is
246 # scope-agnostic — it reads its own package.json at runtime to decide
247 # which scope to resolve the platform binary from — so both packages
248 # ship the same lib/ and it only needs building once.
249 node ../scripts/render-main-package.cjs \
250 "./package.json" \
251 "${npm_package_version}"
252
253 npm install
254 npm run build
255
256 # @getsigit/sigit is the canonical package; @smbcloud/sigit is the
257 # pre-1.5.5 name, kept publishing so installs predating the rename
258 # keep updating. Its template points optionalDependencies at the
259 # @smbcloud platform packages.
260 for template in "package-main.json.tmpl" "package-compat.json.tmpl"; do
261 node ../scripts/render-main-package.cjs \
262 "./package.json" \
263 "${npm_package_version}" \
264 "${template}"
265
266 npm_package_name=$(node -p "require('./package.json').name")
267
268 # Same E404-only reading as the platform packages above: a registry
269 # failure must not look like an unpublished version.
270 if view_output=$(npm view "${npm_package_name}@${npm_package_version}" version 2>&1); then
271 echo "${npm_package_name}@${npm_package_version} already exists on npm, skipping publish"
272 continue
273 elif ! grep -q "E404" <<<"${view_output}"; then
274 echo "npm view failed while checking ${npm_package_name}@${npm_package_version}:" >&2
275 echo "${view_output}" >&2
276 exit 1
277 fi
278
279 npm publish --access public
280 done