@smbcloud / cli / commits / c8d9e2b

wip

keypair34 committed Apr 12, 2026 at 07:30 UTC c8d9e2bb4a25bf50a4e6139ed7fe86661988f44c
3 files changed +560
.github/workflows/release-sdk-gem.yml new
+208
@@ -0,0 +1,208 @@
1 +name: SDK Ruby Gem Release
2 +
3 +# Publishes the smbcloud-auth Ruby gem (sdk/gems/auth) to RubyGems.
4 +# Builds pre-compiled native gems for each supported platform, plus a source
5 +# gem as a fallback for unsupported platforms.
6 +#
7 +# Required secrets:
8 +# RUBYGEMS_API_KEY — RubyGems.org API key with push access to smbcloud-auth
9 +
10 +on:
11 + push:
12 + tags:
13 + - "v*.*.*"
14 + workflow_dispatch:
15 + inputs:
16 + tag:
17 + description: "Release tag (e.g. v0.3.35)"
18 + required: true
19 +
20 +permissions:
21 + contents: read
22 +
23 +env:
24 + CARGO_TERM_COLOR: always
25 +
26 +jobs:
27 + # ── Build native gems ──────────────────────────────────────────────────────
28 + build-gems:
29 + name: Build gem (${{ matrix.name }})
30 + runs-on: ${{ matrix.runner }}
31 + strategy:
32 + fail-fast: false
33 + matrix:
34 + include:
35 + - { name: linux-x64, runner: ubuntu-latest, platform: x86_64-linux }
36 + - { name: linux-arm64, runner: ubuntu-24.04-arm, platform: aarch64-linux }
37 + - { name: darwin-arm64, runner: macos-latest, platform: arm64-darwin }
38 + - { name: darwin-x64, runner: macos-15-intel, platform: x86_64-darwin }
39 + - { name: win-x64, runner: windows-2022, platform: x64-mingw-ucrt }
40 +
41 + steps:
42 + - name: Checkout
43 + uses: actions/checkout@v6
44 + with:
45 + ref: ${{ github.event.inputs.tag || github.ref }}
46 +
47 + - name: Read Rust toolchain
48 + shell: bash
49 + run: |
50 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
51 + if [ -z "$rust_toolchain" ]; then
52 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
53 + exit 1
54 + fi
55 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
56 +
57 + - name: Install toolkit
58 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
59 + with:
60 + toolchain: ${{ env.RUST_TOOLCHAIN }}
61 +
62 + # Scope the Rust cache to the gem's own Cargo workspace so its registry
63 + # deps are cached independently from the main workspace.
64 + - name: Setup Rust cache
65 + uses: Swatinem/rust-cache@v2
66 + with:
67 + key: sdk-gem-${{ matrix.name }}
68 + workspaces: sdk/gems/auth
69 +
70 + - name: Setup Ruby
71 + uses: ruby/setup-ruby@v1
72 + with:
73 + ruby-version: "3.4.2"
74 + bundler-cache: true
75 + working-directory: sdk/gems/auth
76 +
77 + - name: Build native gem
78 + working-directory: sdk/gems/auth
79 + shell: bash
80 + run: bundle exec rake native gem
81 +
82 + - name: Upload gem artifact
83 + uses: actions/upload-artifact@v7
84 + with:
85 + name: gem-${{ matrix.name }}
86 + path: sdk/gems/auth/pkg/*.gem
87 +
88 + # ── Build source gem (fallback for unsupported platforms) ──────────────────
89 + build-source-gem:
90 + name: Build source gem
91 + runs-on: ubuntu-latest
92 + steps:
93 + - name: Checkout
94 + uses: actions/checkout@v6
95 + with:
96 + ref: ${{ github.event.inputs.tag || github.ref }}
97 +
98 + - name: Set the release version
99 + shell: bash
100 + run: |
101 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
102 + release_version="${GITHUB_REF_NAME#v}"
103 + else
104 + release_version="${{ github.event.inputs.tag }}"
105 + release_version="${release_version#v}"
106 + fi
107 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
108 +
109 + - name: Verify gem version matches tag
110 + shell: bash
111 + run: |
112 + GEM_VERSION=$(sed -n "s/.*VERSION = '\\(.*\\)'/\\1/p" sdk/gems/auth/lib/auth/version.rb)
113 +
114 + echo "Gem version : ${GEM_VERSION}"
115 + echo "Tag version : ${RELEASE_VERSION}"
116 +
117 + if [[ "${GEM_VERSION}" != "${RELEASE_VERSION}" ]]; then
118 + echo "::error::Version mismatch — bump Auth::VERSION in sdk/gems/auth/lib/auth/version.rb before releasing."
119 + exit 1
120 + fi
121 +
122 + - name: Setup Ruby
123 + uses: ruby/setup-ruby@v1
124 + with:
125 + ruby-version: "3.4.2"
126 + bundler-cache: true
127 + working-directory: sdk/gems/auth
128 +
129 + - name: Build source gem
130 + working-directory: sdk/gems/auth
131 + run: bundle exec rake build
132 +
133 + - name: Upload source gem artifact
134 + uses: actions/upload-artifact@v7
135 + with:
136 + name: gem-source
137 + path: sdk/gems/auth/pkg/*.gem
138 +
139 + # ── Push all gems to RubyGems ──────────────────────────────────────────────
140 + push-gems:
141 + name: Push to RubyGems
142 + needs: [build-gems, build-source-gem]
143 + runs-on: ubuntu-latest
144 +
145 + steps:
146 + - name: Checkout
147 + uses: actions/checkout@v6
148 + with:
149 + ref: ${{ github.event.inputs.tag || github.ref }}
150 +
151 + - name: Set the release version
152 + shell: bash
153 + run: |
154 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
155 + release_version="${GITHUB_REF_NAME#v}"
156 + else
157 + release_version="${{ github.event.inputs.tag }}"
158 + release_version="${release_version#v}"
159 + fi
160 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
161 +
162 + - name: Check whether release already exists on RubyGems
163 + id: rubygems-check
164 + shell: bash
165 + run: |
166 + if curl -fsS \
167 + "https://rubygems.org/api/v2/rubygems/smbcloud-auth/versions/${RELEASE_VERSION}.json" \
168 + >/dev/null 2>&1; then
169 + echo "smbcloud-auth ${RELEASE_VERSION} already exists on RubyGems, skipping publish"
170 + echo "exists=true" >> "$GITHUB_OUTPUT"
171 + else
172 + echo "exists=false" >> "$GITHUB_OUTPUT"
173 + fi
174 +
175 + - name: Download all gem artifacts
176 + if: steps.rubygems-check.outputs.exists != 'true'
177 + uses: actions/download-artifact@v7
178 + with:
179 + pattern: "gem-*"
180 + path: gems
181 + merge-multiple: true
182 +
183 + - name: Setup Ruby
184 + if: steps.rubygems-check.outputs.exists != 'true'
185 + uses: ruby/setup-ruby@v1
186 + with:
187 + ruby-version: "3.4.2"
188 +
189 + - name: Configure RubyGems credentials
190 + if: steps.rubygems-check.outputs.exists != 'true'
191 + shell: bash
192 + run: |
193 + mkdir -p "${HOME}/.gem"
194 + echo ":rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}" > "${HOME}/.gem/credentials"
195 + chmod 0600 "${HOME}/.gem/credentials"
196 +
197 + # Push each .gem file individually. Platform-specific gems that are already
198 + # published (e.g. from a re-run) emit a warning and continue rather than
199 + # failing the whole job.
200 + - name: Push gems to RubyGems
201 + if: steps.rubygems-check.outputs.exists != 'true'
202 + shell: bash
203 + run: |
204 + for gem_file in gems/*.gem; do
205 + echo "Pushing $(basename "${gem_file}")…"
206 + gem push "${gem_file}" \
207 + || echo "::warning::$(basename "${gem_file}") may already exist for this version — skipping."
208 + done
.github/workflows/release-sdk-npm.yml new
+118
@@ -0,0 +1,118 @@
1 +name: SDK npm Release
2 +
3 +# Publishes @smbcloud/sdk-auth (WASM) to npm.
4 +# WASM is a single universal target — no platform matrix needed.
5 +#
6 +# Required secrets:
7 +# NPM_TOKEN — npm access token with publish rights to @smbcloud/sdk-auth
8 +
9 +on:
10 + push:
11 + tags:
12 + - "v*.*.*"
13 + workflow_dispatch:
14 + inputs:
15 + tag:
16 + description: "Release tag (e.g. v0.3.35)"
17 + required: true
18 +
19 +permissions:
20 + contents: read
21 +
22 +env:
23 + CARGO_TERM_COLOR: always
24 + CLI_CLIENT_SECRET: ${{ secrets.CLI_CLIENT_SECRET }}
25 +
26 +jobs:
27 + publish-sdk-npm:
28 + name: Publish @smbcloud/sdk-auth to npm
29 + runs-on: ubuntu-latest
30 +
31 + steps:
32 + - name: Checkout
33 + uses: actions/checkout@v6
34 + with:
35 + ref: ${{ github.event.inputs.tag || github.ref }}
36 +
37 + - name: Set the release version
38 + shell: bash
39 + run: |
40 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
41 + release_version="${GITHUB_REF_NAME#v}"
42 + else
43 + release_version="${{ github.event.inputs.tag }}"
44 + release_version="${release_version#v}"
45 + fi
46 +
47 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
48 +
49 + - name: Read Rust toolchain
50 + shell: bash
51 + run: |
52 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
53 + if [ -z "$rust_toolchain" ]; then
54 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
55 + exit 1
56 + fi
57 +
58 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
59 +
60 + - name: Install toolkit with wasm32 target
61 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
62 + with:
63 + toolchain: ${{ env.RUST_TOOLCHAIN }}
64 + targets: wasm32-unknown-unknown
65 +
66 + - name: Setup Rust cache
67 + uses: Swatinem/rust-cache@v2
68 + with:
69 + key: sdk-npm
70 +
71 + - name: Verify Cargo.toml version matches tag
72 + shell: bash
73 + run: |
74 + CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 \
75 + | jq -r '.packages[] | select(.name == "smbcloud-auth-sdk-wasm") | .version')
76 +
77 + echo "Cargo.toml version : ${CARGO_VERSION}"
78 + echo "Release tag version: ${RELEASE_VERSION}"
79 +
80 + if [[ "${CARGO_VERSION}" != "${RELEASE_VERSION}" ]]; then
81 + echo "::error::Version mismatch — bump version in crates/smbcloud-auth-sdk-wasm/Cargo.toml before releasing."
82 + exit 1
83 + fi
84 +
85 + # wasm-pack drives the wasm32 compilation and wasm-bindgen code generation.
86 + # prepare-package.mjs calls wasm-pack internally and also enforces that
87 + # sdk/npm/smbcloud-auth/package.json version matches the Cargo.toml version.
88 + - name: Install wasm-pack
89 + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
90 +
91 + - name: Install Node.js
92 + uses: actions/setup-node@v6
93 + with:
94 + node-version-file: .nvmrc
95 + registry-url: "https://registry.npmjs.org"
96 +
97 + - name: Check whether release already exists on npm
98 + id: npm-check
99 + shell: bash
100 + run: |
101 + if npm view "@smbcloud/sdk-auth@${RELEASE_VERSION}" version >/dev/null 2>&1; then
102 + echo "@smbcloud/sdk-auth@${RELEASE_VERSION} already exists on npm, skipping publish"
103 + echo "exists=true" >> "$GITHUB_OUTPUT"
104 + else
105 + echo "exists=false" >> "$GITHUB_OUTPUT"
106 + fi
107 +
108 + - name: Build and prepare package
109 + if: steps.npm-check.outputs.exists != 'true'
110 + working-directory: sdk/npm/smbcloud-auth
111 + run: node ./prepare-package.mjs
112 +
113 + - name: Publish to npm
114 + if: steps.npm-check.outputs.exists != 'true'
115 + working-directory: sdk/npm/smbcloud-auth
116 + env:
117 + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
118 + run: npm publish --access public
.github/workflows/release-sdk-pypi.yml new
+234
@@ -0,0 +1,234 @@
1 +name: SDK PyPI Release
2 +
3 +# Publishes smbcloud-sdk-auth (sdk/python) to PyPI.
4 +# Triggered automatically on semver tags or manually via workflow_dispatch.
5 +
6 +on:
7 + push:
8 + tags:
9 + - "v*.*.*"
10 + workflow_dispatch:
11 + inputs:
12 + tag:
13 + description: "Release tag (e.g. v0.3.35)"
14 + required: true
15 +
16 +permissions:
17 + id-token: write
18 + contents: read
19 +
20 +env:
21 + CARGO_TERM_COLOR: always
22 + CLI_CLIENT_SECRET: ${{ secrets.CLI_CLIENT_SECRET }}
23 +
24 +jobs:
25 + build-wheels:
26 + name: Build PyPI wheels
27 + runs-on: ${{ matrix.build.OS }}
28 + strategy:
29 + fail-fast: false
30 + matrix:
31 + build:
32 + - {
33 + NAME: linux-x64-glibc,
34 + OS: ubuntu-latest,
35 + TARGET: x86_64-unknown-linux-gnu,
36 + MANYLINUX: "2014",
37 + }
38 + - {
39 + NAME: linux-arm64-glibc,
40 + OS: ubuntu-24.04-arm,
41 + TARGET: aarch64-unknown-linux-gnu,
42 + MANYLINUX: "2014",
43 + }
44 + - {
45 + NAME: win32-x64-msvc,
46 + OS: windows-2022,
47 + TARGET: x86_64-pc-windows-msvc,
48 + }
49 + - {
50 + NAME: win32-arm64-msvc,
51 + OS: windows-2022,
52 + TARGET: aarch64-pc-windows-msvc,
53 + }
54 + - { NAME: darwin-x64, OS: macos-15-intel, TARGET: x86_64-apple-darwin }
55 + - {
56 + NAME: darwin-arm64,
57 + OS: macos-latest,
58 + TARGET: aarch64-apple-darwin,
59 + }
60 + steps:
61 + - name: Checkout
62 + uses: actions/checkout@v6
63 + with:
64 + ref: ${{ github.event.inputs.tag || github.ref }}
65 +
66 + - name: Set the release version
67 + shell: bash
68 + run: |
69 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
70 + release_version="${GITHUB_REF_NAME#v}"
71 + else
72 + release_version="${{ github.event.inputs.tag }}"
73 + release_version="${release_version#v}"
74 + fi
75 +
76 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
77 +
78 + - name: Read Rust toolchain
79 + shell: bash
80 + run: |
81 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
82 + if [ -z "$rust_toolchain" ]; then
83 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
84 + exit 1
85 + fi
86 +
87 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
88 +
89 + - name: Install toolkit
90 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
91 + with:
92 + toolchain: ${{ env.RUST_TOOLCHAIN }}
93 +
94 + - name: Install Rust target
95 + shell: bash
96 + run: |
97 + rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
98 + rustup target list --installed
99 +
100 + - name: Verify Cargo.toml version matches tag
101 + shell: bash
102 + run: |
103 + CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 \
104 + | jq -r '.packages[] | select(.name == "smbcloud-auth-sdk-py") | .version')
105 +
106 + echo "Cargo.toml version : ${CARGO_VERSION}"
107 + echo "Release tag version: ${RELEASE_VERSION}"
108 +
109 + if [[ "${CARGO_VERSION}" != "${RELEASE_VERSION}" ]]; then
110 + echo "::error::Version mismatch — bump version in crates/smbcloud-auth-sdk-py/Cargo.toml before releasing."
111 + exit 1
112 + fi
113 +
114 + - name: Setup Rust cache
115 + uses: Swatinem/rust-cache@v2
116 + with:
117 + key: sdk-pypi-${{ matrix.build.NAME }}
118 +
119 + # manylinux containers are CentOS-based and use yum; perl-core is required
120 + # by the openssl-sys vendored build to compile OpenSSL from source.
121 + - name: Build wheel
122 + uses: PyO3/maturin-action@v1
123 + with:
124 + target: ${{ matrix.build.TARGET }}
125 + manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
126 + working-directory: sdk/python
127 + args: --release --locked --compatibility pypi --out dist
128 + before-script-linux: yum install -y perl-core
129 + docker-options: -e CLI_CLIENT_SECRET
130 +
131 + - name: Upload wheel artifact
132 + uses: actions/upload-artifact@v7
133 + with:
134 + name: wheels-${{ matrix.build.NAME }}
135 + path: sdk/python/dist/*
136 +
137 + build-sdist:
138 + name: Build source distribution
139 + runs-on: ubuntu-latest
140 + steps:
141 + - name: Checkout
142 + uses: actions/checkout@v6
143 + with:
144 + ref: ${{ github.event.inputs.tag || github.ref }}
145 +
146 + - name: Set the release version
147 + shell: bash
148 + run: |
149 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
150 + release_version="${GITHUB_REF_NAME#v}"
151 + else
152 + release_version="${{ github.event.inputs.tag }}"
153 + release_version="${release_version#v}"
154 + fi
155 +
156 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
157 +
158 + - name: Read Rust toolchain
159 + shell: bash
160 + run: |
161 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
162 + if [ -z "$rust_toolchain" ]; then
163 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
164 + exit 1
165 + fi
166 +
167 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
168 +
169 + - name: Install toolkit
170 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
171 + with:
172 + toolchain: ${{ env.RUST_TOOLCHAIN }}
173 +
174 + - name: Build sdist
175 + uses: PyO3/maturin-action@v1
176 + with:
177 + command: sdist
178 + working-directory: sdk/python
179 + args: --out dist
180 +
181 + - name: Upload sdist artifact
182 + uses: actions/upload-artifact@v7
183 + with:
184 + name: sdist
185 + path: sdk/python/dist/*
186 +
187 + publish-pypi:
188 + name: Publish to PyPI
189 + runs-on: ubuntu-latest
190 + needs:
191 + - build-wheels
192 + - build-sdist
193 +
194 + steps:
195 + - name: Checkout
196 + uses: actions/checkout@v6
197 + with:
198 + ref: ${{ github.event.inputs.tag || github.ref }}
199 +
200 + - name: Set the release version
201 + shell: bash
202 + run: |
203 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
204 + release_version="${GITHUB_REF_NAME#v}"
205 + else
206 + release_version="${{ github.event.inputs.tag }}"
207 + release_version="${release_version#v}"
208 + fi
209 +
210 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
211 +
212 + - name: Download distribution artifacts
213 + uses: actions/download-artifact@v7
214 + with:
215 + pattern: "*"
216 + path: dist
217 + merge-multiple: true
218 +
219 + - name: Check whether release already exists on PyPI
220 + id: pypi-check
221 + shell: bash
222 + run: |
223 + if curl -fsS "https://pypi.org/pypi/smbcloud-sdk-auth/${RELEASE_VERSION}/json" >/dev/null 2>&1; then
224 + echo "smbcloud-sdk-auth ${RELEASE_VERSION} already exists on PyPI, skipping publish"
225 + echo "exists=true" >> "$GITHUB_OUTPUT"
226 + else
227 + echo "exists=false" >> "$GITHUB_OUTPUT"
228 + fi
229 +
230 + - name: Publish distribution
231 + if: steps.pypi-check.outputs.exists != 'true'
232 + uses: pypa/gh-action-pypi-publish@release/v1
233 + with:
234 + skip-existing: true