@smbcloud / cli / commits / 5ca2078

Add PyPI packaging and release workflow for smbcloud-cli

- Add pypi/pyproject.toml and pypi/README.md for PyPI builds - Add .github/workflows/release-pypi.yml for automated wheel/sdist build and publish - Update .gitignore for PyPI artifacts - Document pip install/uninstall in crates/cli/README.md - Expand SKILL.md to cover PyPI release flow and source of truth

Seto Elkahfi committed Mar 28, 2026 at 22:37 UTC 5ca20781039d05a88052aaea824861d235eb1100
6 files changed +367 -146
.agents/skills/smbcloud-cli-release/SKILL.md
+100 -146
@@ -1,6 +1,6 @@
1 ---
2 name: smbcloud-cli-release
3 -description: Use when building, packaging, or releasing smbCloud CLI binaries through npm or GitHub Actions CI/CD. Covers the Rust binary packages under `npm/cli-*`, the `@smbcloud/cli` wrapper package, macOS arm64 vs x64 constraints, npm 2FA publishing, and fixes to `.github/workflows/release-npm.yml`.
3 +description: Use when building, packaging, or releasing smbCloud CLI binaries through npm, PyPI, or GitHub Actions CI/CD. Covers the Rust binary release source of truth, the npm wrapper and platform packages, the PyPI `maturin` package under `pypi/`, local publishing with `uv tool install maturin`, and fixes to `.github/workflows/release-npm.yml` or `.github/workflows/release-pypi.yml`.
4 ---
5
6 # smbcloud CLI Release
@@ -8,17 +8,34 @@ description: Use when building, packaging, or releasing smbCloud CLI binaries th
8 Use this skill when work touches any part of the smbCloud CLI distribution flow:
9
10 - local npm release for `smbcloud-cli`
11 +- local PyPI release for `smbcloud-cli`
12 - GitHub Actions npm release automation
12 -- Rust binary packaging into scoped npm platform packages
13 -- release failures caused by macOS cross-compilation, missing package metadata, or npm 2FA
13 +- GitHub Actions PyPI release automation
14 +- Rust binary packaging into npm platform packages or PyPI wheels
15 +- release failures caused by macOS cross-compilation, missing package metadata, npm 2FA, or PyPI trusted publishing setup
16 +
17 +## Source of truth
18 +
19 +Use these files as the release source of truth:
20 +
21 +- Rust crate version and binary name: `crates/cli/Cargo.toml`
22 +- npm release workflow: `.github/workflows/release-npm.yml`
23 +- PyPI release workflow: `.github/workflows/release-pypi.yml`
24 +- npm platform package generator: `npm/scripts/render-platform-package.cjs`
25 +- npm wrapper package generator: `npm/scripts/render-main-package.cjs`
26 +- npm wrapper launcher: `npm/smbcloud-cli/src/index.ts`
27 +- PyPI package metadata: `pypi/pyproject.toml`
28 +- PyPI package README: `pypi/README.md`
29
30 ## Release model
31
17 -There are two npm package layers. Publish them in order.
32 +There are two public distribution channels.
33 +
34 +### 1. npm
35
19 -### 1. Platform binary packages
36 +npm has two package layers. Publish them in order.
37
21 -These packages contain the compiled Rust binary only:
38 +Platform binary packages:
39
40 - `@smbcloud/cli-darwin-arm64`
41 - `@smbcloud/cli-darwin-x64`
@@ -26,31 +43,22 @@ These packages contain the compiled Rust binary only:
43 - `@smbcloud/cli-windows-arm64`
44 - `@smbcloud/cli-windows-x64`
45
29 -Their package directories are generated under `npm/cli-*/` and should be treated as release artifacts, not source.
30 -
31 -### 2. Wrapper package
32 -
33 -The public package is:
46 +Wrapper package:
47
48 - `@smbcloud/cli`
49
37 -It contains the Node launcher in `npm/smbcloud-cli/src/index.ts` and resolves the correct platform package with `require.resolve(...)`.
38 -
50 +The wrapper package resolves the right platform package with `require.resolve(...)`.
51 Do not publish `@smbcloud/cli` before the required platform packages for that version exist.
52
41 -## Source of truth
53 +### 2. PyPI
54
43 -Use these files as the release source of truth:
55 +PyPI uses one package:
56
45 -- Rust crate version: `crates/cli/Cargo.toml`
46 -- npm release workflow: `.github/workflows/release-npm.yml`
47 -- platform package generator: `npm/scripts/render-platform-package.cjs`
48 -- wrapper package generator: `npm/scripts/render-main-package.cjs`
49 -- wrapper launcher: `npm/smbcloud-cli/src/index.ts`
57 +- `smbcloud-cli`
58
51 -Do not hand-edit generated `npm/cli-*/package.json` files unless debugging a broken release artifact.
59 +It is built from `pypi/pyproject.toml` with `maturin` and `bindings = "bin"`, so the published wheel installs the native `smb` executable directly.
60
53 -## Local release workflow
61 +## Local npm release workflow
62
63 ### Preflight
64
@@ -64,7 +72,7 @@ Build each target first:
72
73 - `cargo build --release --locked --target aarch64-apple-darwin`
74 - `cargo build --release --locked --target x86_64-apple-darwin`
67 -- or the matching Linux/Windows target in CI
75 +- or the matching Linux or Windows target in CI
76
77 ### Generate platform package
78
@@ -87,187 +95,133 @@ Example:
95 4. Run `npm run build`
96 5. Publish `@smbcloud/cli`
97
90 -## npm 2FA
98 +## Local PyPI release workflow
99
92 -Publishing may fail with `EOTP`.
100 +### Tooling
101
94 -When that happens, retry the exact `npm publish` command with:
102 +Use `uv` for local `maturin` installation in this repo.
103
96 -- `--otp=<code>`
104 +Install:
105
98 -Do not assume the first publish failed before the package upload step. Check the exit result or npm registry state before retrying repeatedly.
106 +- `uv tool install maturin`
107
100 -## Trusted publishing
108 +Upgrade later if needed:
109
102 -Prefer npm trusted publishers for CI over `NPM_TOKEN`.
103 -
104 -Official references:
105 -
106 -- https://docs.npmjs.com/trusted-publishers/
107 -- https://docs.npmjs.com/cli/v11/commands/npm-trust/
108 -
109 -### npm-side constraints
110 -
111 -Trusted publishing can only be configured for packages that already exist on npm.
110 +- `uv tool upgrade maturin`
111
113 -That means:
112 +If the shell cannot find `maturin`, use:
113
115 -- publish a package once manually if it does not exist yet
116 -- then configure trust for that package
117 -- each package can have only one trusted publisher configuration at a time
114 +- `uv tool run maturin --version`
115
119 -For `smbcloud-cli`, configure trust per package, not only for `@smbcloud/cli`.
116 +### Preflight
117
121 -Example packages:
118 +1. Confirm the crate version in `crates/cli/Cargo.toml`.
119 +2. Make sure `.env` exists with `CLI_CLIENT_SECRET=...` because the Rust build reads it at compile time.
120 +3. If publishing from a local machine, use a PyPI API token. Trusted publishing is for CI.
121
123 -- `@smbcloud/cli`
124 -- `@smbcloud/cli-darwin-arm64`
125 -- later, each additional published `@smbcloud/cli-*` package
122 +### Build and upload
123
127 -### GitHub Actions setup
124 +From `pypi/`:
125
129 -The workflow must include:
126 +- `maturin build --release --locked --compatibility pypi --out dist`
127 +- `maturin upload dist/*`
128
131 -- `permissions:`
132 -- `id-token: write`
133 -- `contents: read`
129 +Or publish in one step:
130
135 -Do not pass `NODE_AUTH_TOKEN` to `npm publish` when using trusted publishing.
131 +- `maturin publish --release --locked --compatibility pypi`
132
137 -The npm CLI detects the GitHub OIDC environment automatically and exchanges it for a short-lived publish credential.
133 +For local uploads, export `MATURIN_PYPI_TOKEN` before running `maturin upload` or `maturin publish`.
134
139 -### Rust toolchain consistency
135 +### Local publishing constraint
136
141 -When cross-compiling in CI, the Rust toolchain used for `rustup target add` must match the toolchain used by `cargo build`.
137 +A local publish normally builds only for the current platform.
138
143 -For this repo, `rust-toolchain.toml` is the source of truth.
139 +Do not claim a full PyPI release is complete from one machine unless you intentionally published only one platform or separately produced all required wheels.
140
145 -Do not duplicate the Rust version in the matrix unless the workflow intentionally tests multiple toolchains.
141 +## npm 2FA
142
147 -If the workflow installs a target for one toolchain but Cargo builds with another, CI can fail with:
143 +Publishing may fail with `EOTP`.
144
149 -- `error[E0463]: can't find crate for core`
150 -- note that the target may not be installed
145 +When that happens, retry the exact `npm publish` command with:
146
152 -This can happen even when `rustup target add <target>` already ran successfully.
147 +- `--otp=<code>`
148
154 -### dtolnay action behavior
149 +Do not assume the first publish failed before the package upload step. Check the exit result or npm registry state before retrying repeatedly.
150
156 -For the pinned `dtolnay/rust-toolchain` revision used in this repo, do not assume the action will infer the toolchain from `rust-toolchain.toml` without input.
151 +## Trusted publishing
152
158 -A workflow can fail with:
153 +### npm
154
160 -- `'toolchain' is a required input`
155 +Prefer npm trusted publishers for CI over `NPM_TOKEN`.
156
162 -Preferred pattern in this repo:
157 +Official references:
158
164 -- read `channel = "..."` from `rust-toolchain.toml`
165 -- write it to `RUST_TOOLCHAIN` in `GITHUB_ENV`
166 -- pass `toolchain: ${{ env.RUST_TOOLCHAIN }}` to `dtolnay/rust-toolchain`
167 -- run `rustup target add <target> --toolchain ${{ env.RUST_TOOLCHAIN }}`
168 -- run `cargo build --target <target>` after the action sets that toolchain active
159 +- https://docs.npmjs.com/trusted-publishers/
160 +- https://docs.npmjs.com/cli/v11/commands/npm-trust/
161
170 -This keeps `rust-toolchain.toml` as the only Rust version source while avoiding implicit action behavior.
162 +Trusted publishing can only be configured for packages that already exist on npm.
163 +That means new package names still need one manual publish before trust can be configured.
164
172 -### Trusted publisher command
165 +### PyPI
166
174 -For this repo, the trust relationship should point at:
167 +Use trusted publishing in GitHub Actions through `pypa/gh-action-pypi-publish@release/v1`.
168 +Do not use trusted publishing as the default local-machine publish path.
169
176 -- repository: `smbcloudXYZ/smbcloud-cli`
177 -- workflow file: `release-npm.yml`
170 +## CI/CD workflow rules
171
179 -Example:
172 +### Shared rules
173
181 -- `npm trust github @smbcloud/cli --repo smbcloudXYZ/smbcloud-cli --file release-npm.yml --yes`
182 -- `npm trust github @smbcloud/cli-darwin-arm64 --repo smbcloudXYZ/smbcloud-cli --file release-npm.yml --yes`
174 +For both release workflows:
175
184 -These commands may require npm 2FA and support `--otp=<code>`.
176 +- `runs-on` must use `matrix.build.OS` when the matrix uses upper-case keys
177 +- derive `RELEASE_VERSION` from the git tag when `GITHUB_REF_TYPE=tag`
178 +- for `workflow_dispatch`, fall back to the version in `crates/cli/Cargo.toml`
179 +- read the Rust toolchain from `rust-toolchain.toml`
180 +- pass that exact toolchain into `dtolnay/rust-toolchain`
181 +- run `rustup target add <target> --toolchain ${{ env.RUST_TOOLCHAIN }}` before cross-target builds
182
186 -### Migration guidance
183 +### npm workflow
184
188 -Recommended order:
185 +The npm workflow lives in `.github/workflows/release-npm.yml`.
186
190 -1. enable trusted publishing for existing packages
191 -2. verify a CI publish works through OIDC
192 -3. then remove or stop using `NPM_TOKEN`
193 -4. after the migration is proven, tighten npm package publishing access if desired
187 +Important rules:
188
195 -Do not remove the manual publish path for brand-new package names, because npm trust cannot be configured before the first publish.
189 +- avoid `envsubst` for package generation across runners
190 +- use the Node generator scripts instead
191 +- use `npm install` and `npm run build` for the wrapper package job
192
197 -## CI/CD workflow rules
193 +### PyPI workflow
194
199 -The release workflow lives in `.github/workflows/release-npm.yml`.
195 +The PyPI workflow lives in `.github/workflows/release-pypi.yml`.
196
197 Important rules:
198
203 -- `runs-on` must use `matrix.build.OS`, not `matrix.build.os`
204 -- derive `RELEASE_VERSION` from the git tag when `GITHUB_REF_TYPE=tag`
205 -- for `workflow_dispatch`, fall back to the version in `crates/cli/Cargo.toml`
206 -- avoid `envsubst` for package generation across runners
207 -- use the Node generator scripts instead
208 -- use `npm install` and `npm run build` for the wrapper package job
199 +- build wheels with `PyO3/maturin-action@v1`
200 +- use `working-directory: pypi`
201 +- pass `target: ${{ matrix.build.TARGET }}`
202 +- use `manylinux: ${{ matrix.build.MANYLINUX || 'off' }}`
203 +- build the sdist in a separate job
204 +- publish only after wheel and sdist artifacts are downloaded into one directory
205 +
206 +## Rust toolchain consistency
207
210 -### Package generation
208 +When cross-compiling in CI, the Rust toolchain used for `rustup target add` must match the toolchain used by `cargo build` or `maturin`.
209
212 -Prefer deterministic Node scripts over shell templating.
210 +For this repo, `rust-toolchain.toml` is the only Rust version source of truth.
211
214 -Reasons:
212 +If the workflow installs a target for one toolchain but builds with another, CI can fail with:
213
216 -- `envsubst` is not guaranteed across macOS and Windows runners
217 -- package metadata must stay identical between local release and CI
218 -- the generated wrapper package must point optional dependencies at the exact release version
214 +- `error[E0463]: can't find crate for core`
215
216 ## macOS cross-build constraint
217
218 On an Apple Silicon host, `x86_64-apple-darwin` may fail due to `openssl-sys` if only arm64 Homebrew OpenSSL exists under `/opt/homebrew`.
219
224 -Typical symptom:
225 -
226 -- `openssl-sys` cannot find an `x86_64-apple-darwin` OpenSSL
227 -
220 If that happens:
221
222 - do not claim the x64 package is releasable from that machine
223 - either build on an Intel Mac
232 -- or use a Rosetta/x86 Homebrew toolchain with Intel OpenSSL under `/usr/local/opt/openssl@3`
224 +- or use a Rosetta or x86 Homebrew toolchain with Intel OpenSSL under `/usr/local/opt/openssl@3`
225 - or publish only the arm64 platform package and explicitly avoid calling the release complete
226
227 Do not publish `@smbcloud/cli` for a version unless you accept that missing platform packages for that version can break installs on those platforms.
236 -
237 -## Generated artifacts
238 -
239 -Generated platform package directories should be git-ignored:
240 -
241 -- `/npm/cli-*/`
242 -
243 -These are build artifacts and should not be committed.
244 -
245 -## Validation
246 -
247 -Use the smallest checks that match the change.
248 -
249 -### Local
250 -
251 -- `npm whoami`
252 -- `cargo build --release --locked --target <target>`
253 -- `node npm/scripts/render-platform-package.cjs ...`
254 -- `node npm/scripts/render-main-package.cjs ...`
255 -- `npm install`
256 -- `npm run build`
257 -
258 -### CI/CD edits
259 -
260 -After changing the workflow:
261 -
262 -- inspect `.github/workflows/release-npm.yml`
263 -- verify the package generators still output the expected names and versions
264 -- confirm `@smbcloud/cli` optional dependencies match the platform package names exactly
265 -
266 -## Common mistakes
267 -
268 -- publishing `@smbcloud/cli` before the matching platform packages exist
269 -- assuming `workflow_dispatch` has a tag-derived version
270 -- relying on `envsubst` in a cross-platform GitHub Actions workflow
271 -- forgetting that Windows binaries need `.exe`
272 -- treating generated `npm/cli-*` directories as source files
273 -- trying to cross-build macOS x64 on Apple Silicon without an Intel OpenSSL toolchain
.github/workflows/release-pypi.yml new
+194
@@ -0,0 +1,194 @@
1 +name: PyPI Release
2 +
3 +on:
4 + push:
5 + tags:
6 + - "v*.*.*"
7 + workflow_dispatch:
8 +
9 +permissions:
10 + id-token: write
11 + contents: read
12 +
13 +env:
14 + CARGO_TERM_COLOR: always
15 + SMB_CLIENT_ID: ${{ secrets.SMB_CLIENT_ID }}
16 + SMB_CLIENT_SECRET: ${{ secrets.SMB_CLIENT_SECRET }}
17 + SMB_API_HOST: ${{ secrets.SMB_API_HOST }}
18 + SMB_API_PROTOCOL: ${{ secrets.SMB_API_PROTOCOL }}
19 + GH_OAUTH_CLIENT_ID: ${{ secrets.GH_OAUTH_CLIENT_ID }}
20 + GH_OAUTH_CLIENT_SECRET: ${{ secrets.GH_OAUTH_CLIENT_SECRET }}
21 + GH_OAUTH_REDIRECT_HOST: ${{ secrets.GH_OAUTH_REDIRECT_HOST }}
22 + GH_OAUTH_REDIRECT_PORT: ${{ secrets.GH_OAUTH_REDIRECT_PORT }}
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 + # Cannot cross-compile for now
39 + #- {
40 + # NAME: linux-arm64-glibc,
41 + # OS: ubuntu-latest,
42 + # TOOLCHAIN: stable,
43 + # TARGET: aarch64-unknown-linux-gnu,
44 + # }
45 + - {
46 + NAME: win32-x64-msvc,
47 + OS: windows-2022,
48 + TARGET: x86_64-pc-windows-msvc,
49 + }
50 + - {
51 + NAME: win32-arm64-msvc,
52 + OS: windows-2022,
53 + TARGET: aarch64-pc-windows-msvc,
54 + }
55 + - {
56 + NAME: darwin-x64,
57 + OS: macos-latest,
58 + TARGET: x86_64-apple-darwin,
59 + }
60 + - {
61 + NAME: darwin-arm64,
62 + OS: macos-latest,
63 + TARGET: aarch64-apple-darwin,
64 + }
65 + steps:
66 + - name: Checkout
67 + uses: actions/checkout@v6
68 +
69 + - name: Set the release version
70 + shell: bash
71 + run: |
72 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
73 + release_version="${GITHUB_REF_NAME#v}"
74 + else
75 + release_version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/cli/Cargo.toml | head -n 1)"
76 + fi
77 +
78 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
79 +
80 + - name: Read Rust toolchain
81 + shell: bash
82 + run: |
83 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
84 + if [ -z "$rust_toolchain" ]; then
85 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
86 + exit 1
87 + fi
88 +
89 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
90 +
91 + - name: Install toolkit
92 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
93 + with:
94 + toolchain: ${{ env.RUST_TOOLCHAIN }}
95 +
96 + - name: Install Rust target
97 + shell: bash
98 + run: |
99 + rustup target add ${{ matrix.build.TARGET }} --toolchain ${{ env.RUST_TOOLCHAIN }}
100 + rustup target list --installed
101 +
102 + - name: Create .env file
103 + run: |
104 + touch .env
105 + echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
106 + cat .env
107 +
108 + - name: Build wheel
109 + uses: PyO3/maturin-action@v1
110 + with:
111 + target: ${{ matrix.build.TARGET }}
112 + manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
113 + working-directory: pypi
114 + args: --release --locked --compatibility pypi --out dist
115 +
116 + - name: Upload wheel artifact
117 + uses: actions/upload-artifact@v4
118 + with:
119 + name: wheels-${{ matrix.build.NAME }}
120 + path: pypi/dist/*
121 +
122 + build-sdist:
123 + name: Build source distribution
124 + runs-on: ubuntu-latest
125 + steps:
126 + - name: Checkout
127 + uses: actions/checkout@v6
128 +
129 + - name: Set the release version
130 + shell: bash
131 + run: |
132 + if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
133 + release_version="${GITHUB_REF_NAME#v}"
134 + else
135 + release_version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/cli/Cargo.toml | head -n 1)"
136 + fi
137 +
138 + echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
139 +
140 + - name: Read Rust toolchain
141 + shell: bash
142 + run: |
143 + rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
144 + if [ -z "$rust_toolchain" ]; then
145 + echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
146 + exit 1
147 + fi
148 +
149 + echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
150 +
151 + - name: Install toolkit
152 + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
153 + with:
154 + toolchain: ${{ env.RUST_TOOLCHAIN }}
155 +
156 + - name: Create .env file
157 + run: |
158 + touch .env
159 + echo CLI_CLIENT_SECRET=${{ secrets.CLI_CLIENT_SECRET }} >> .env
160 + cat .env
161 +
162 + - name: Build sdist
163 + uses: PyO3/maturin-action@v1
164 + with:
165 + command: sdist
166 + working-directory: pypi
167 + args: --out dist
168 +
169 + - name: Upload sdist artifact
170 + uses: actions/upload-artifact@v4
171 + with:
172 + name: sdist
173 + path: pypi/dist/*
174 +
175 + publish-pypi:
176 + name: Publish to PyPI
177 + runs-on: ubuntu-latest
178 + needs:
179 + - build-wheels
180 + - build-sdist
181 +
182 + steps:
183 + - name: Checkout
184 + uses: actions/checkout@v6
185 +
186 + - name: Download distribution artifacts
187 + uses: actions/download-artifact@v4
188 + with:
189 + pattern: "*"
190 + path: dist
191 + merge-multiple: true
192 +
193 + - name: Publish distribution
194 + uses: pypa/gh-action-pypi-publish@release/v1
.gitignore
+3
@@ -9,3 +9,6 @@
9 .env
10 # Generated npm release artifacts
11 /npm/cli-*/
12 +# Generated PyPI release artifacts
13 +/pypi/dist/
14 +/pypi/.venv/
crates/cli/README.md
+9
@@ -25,6 +25,12 @@ brew install cli
25 npm i -g @smbcloud/cli
26 ```
27
28 +### With PyPI
29 +
30 +```bash
31 +pip install smbcloud-cli
32 +```
33 +
34 ## Update
35
36 Simply rerun the installation command.
@@ -42,6 +48,9 @@ npm uninstall -g @smbcloud/cli
48 # With Homebrew
49 brew untap smbcloud/tap
50 brew uninstall smbcloud/tap/cli
51 +
52 +# With pip
53 +pip uninstall smbcloud-cli
54 ```
55
56 ## Usage:
pypi/README.md new
+23
@@ -0,0 +1,23 @@
1 +# smbcloud-cli
2 +
3 +Python distribution for the `smb` command line interface used to access
4 +[smbcloud](https://smbcloud.xyz/).
5 +
6 +## Installation
7 +
8 +```bash
9 +pip install smbcloud-cli
10 +```
11 +
12 +This package installs the native `smb` executable for the current platform.
13 +
14 +## Usage
15 +
16 +```bash
17 +smb --help
18 +```
19 +
20 +## Project
21 +
22 +- Repository: https://github.com/smbcloudXYZ/smbcloud-cli
23 +- Documentation: https://docs.smbcloud.xyz/cli
pypi/pyproject.toml new
+38
@@ -0,0 +1,38 @@
1 +[build-system]
2 +requires = ["maturin>=1.7,<2.0"]
3 +build-backend = "maturin"
4 +
5 +[project]
6 +name = "smbcloud-cli"
7 +description = "smbCloud command line interface."
8 +readme = "README.md"
9 +requires-python = ">=3.8"
10 +dynamic = ["version"]
11 +license = { text = "Apache-2.0" }
12 +authors = [{ name = "Seto Elkahfi", email = "hej@setoelkahfi.se" }]
13 +keywords = ["cli", "cloud", "smbcloud", "web2", "web3"]
14 +classifiers = [
15 + "Development Status :: 4 - Beta",
16 + "Environment :: Console",
17 + "Intended Audience :: Developers",
18 + "License :: OSI Approved :: Apache Software License",
19 + "Operating System :: MacOS",
20 + "Operating System :: Microsoft :: Windows",
21 + "Operating System :: POSIX :: Linux",
22 + "Programming Language :: Python :: 3",
23 + "Programming Language :: Rust",
24 + "Topic :: Software Development :: Build Tools",
25 + "Topic :: System :: Systems Administration",
26 + "Topic :: Utilities",
27 +]
28 +
29 +[project.urls]
30 +Homepage = "https://smbcloud.xyz/"
31 +Documentation = "https://docs.smbcloud.xyz/cli"
32 +Repository = "https://github.com/smbcloudXYZ/smbcloud-cli"
33 +Issues = "https://github.com/smbcloudXYZ/smbcloud-cli/issues"
34 +
35 +[tool.maturin]
36 +manifest-path = "../crates/cli/Cargo.toml"
37 +bindings = "bin"
38 +strip = true