1 name: PyPI CLI Release
2
3 on:
4 push:
5 tags:
6 - "v*.*.*"
7 workflow_dispatch:
8 inputs:
9 tag:
10 description: "Release tag (e.g. v0.3.39)"
11 required: true
12
13 permissions:
14 id-token: write
15 contents: read
16
17 env:
18 CARGO_TERM_COLOR: always
19 CLI_CLIENT_SECRET: ${{ secrets.CLI_CLIENT_SECRET }}
20
21 jobs:
22 build-wheels:
23 name: Build PyPI wheels
24 runs-on: ${{ matrix.build.OS }}
25 strategy:
26 fail-fast: false
27 matrix:
28 build:
29 - {
30 NAME: linux-x64-glibc,
31 OS: ubuntu-latest,
32 TARGET: x86_64-unknown-linux-gnu,
33 MANYLINUX: "2014",
34 }
35 - {
36 NAME: linux-arm64-glibc,
37 OS: ubuntu-24.04-arm,
38 TARGET: aarch64-unknown-linux-gnu,
39 MANYLINUX: "2014",
40 }
41 - {
42 NAME: win32-x64-msvc,
43 OS: windows-2022,
44 TARGET: x86_64-pc-windows-msvc,
45 }
46 - {
47 NAME: win32-arm64-msvc,
48 OS: windows-2022,
49 TARGET: aarch64-pc-windows-msvc,
50 }
51 - { NAME: darwin-x64, OS: macos-latest, TARGET: x86_64-apple-darwin }
52 - {
53 NAME: darwin-arm64,
54 OS: macos-latest,
55 TARGET: aarch64-apple-darwin,
56 }
57 steps:
58 - name: Checkout
59 uses: actions/checkout@v6
60 with:
61 ref: ${{ github.event.inputs.tag || github.ref }}
62
63 - name: Set the release version
64 shell: bash
65 run: |
66 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
67 release_version="${GITHUB_REF_NAME#v}"
68 else
69 release_version="${{ github.event.inputs.tag }}"
70 release_version="${release_version#v}"
71 fi
72
73 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
74
75 - name: Read Rust toolchain
76 shell: bash
77 run: |
78 rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
79 if [ -z "$rust_toolchain" ]; then
80 echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
81 exit 1
82 fi
83
84 echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
85
86 - name: Install toolkit
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: Build wheel
98 uses: PyO3/maturin-action@v1
99 with:
100 target: ${{ matrix.build.TARGET }}
101 manylinux: ${{ matrix.build.MANYLINUX || 'off' }}
102 working-directory: pypi
103 args: --release --locked --compatibility pypi --out dist
104 before-script-linux: yum install -y perl-core
105 docker-options: -e CLI_CLIENT_SECRET
106
107 - name: Upload wheel artifact
108 uses: actions/upload-artifact@v7
109 with:
110 name: wheels-${{ matrix.build.NAME }}
111 path: pypi/dist/*
112
113 build-sdist:
114 name: Build source distribution
115 runs-on: ubuntu-latest
116 steps:
117 - name: Checkout
118 uses: actions/checkout@v6
119 with:
120 ref: ${{ github.event.inputs.tag || github.ref }}
121
122 - name: Set the release version
123 shell: bash
124 run: |
125 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
126 release_version="${GITHUB_REF_NAME#v}"
127 else
128 release_version="${{ github.event.inputs.tag }}"
129 release_version="${release_version#v}"
130 fi
131
132 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
133
134 - name: Read Rust toolchain
135 shell: bash
136 run: |
137 rust_toolchain="$(sed -n 's/^channel = "\(.*\)"/\1/p' rust-toolchain.toml | head -n 1)"
138 if [ -z "$rust_toolchain" ]; then
139 echo "Failed to read Rust toolchain from rust-toolchain.toml" >&2
140 exit 1
141 fi
142
143 echo "RUST_TOOLCHAIN=${rust_toolchain}" >> "$GITHUB_ENV"
144
145 - name: Install toolkit
146 uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9
147 with:
148 toolchain: ${{ env.RUST_TOOLCHAIN }}
149
150 - name: Build sdist
151 uses: PyO3/maturin-action@v1
152 with:
153 command: sdist
154 working-directory: pypi
155 args: --out dist
156
157 - name: Upload sdist artifact
158 uses: actions/upload-artifact@v7
159 with:
160 name: sdist
161 path: pypi/dist/*
162
163 publish-pypi:
164 name: Publish to PyPI
165 runs-on: ubuntu-latest
166 needs:
167 - build-wheels
168 - build-sdist
169
170 steps:
171 - name: Checkout
172 uses: actions/checkout@v6
173 with:
174 ref: ${{ github.event.inputs.tag || github.ref }}
175
176 - name: Set the release version
177 shell: bash
178 run: |
179 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
180 release_version="${GITHUB_REF_NAME#v}"
181 else
182 release_version="${{ github.event.inputs.tag }}"
183 release_version="${release_version#v}"
184 fi
185
186 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
187
188 - name: Download distribution artifacts
189 uses: actions/download-artifact@v7
190 with:
191 pattern: "*"
192 path: dist
193 merge-multiple: true
194
195 - name: Check whether release already exists on PyPI
196 id: pypi-check
197 shell: bash
198 run: |
199 if curl -fsS "https://pypi.org/pypi/smbcloud-cli/${RELEASE_VERSION}/json" >/dev/null 2>&1; then
200 echo "smbcloud-cli ${RELEASE_VERSION} already exists on PyPI, skipping publish"
201 echo "exists=true" >> "$GITHUB_OUTPUT"
202 else
203 echo "exists=false" >> "$GITHUB_OUTPUT"
204 fi
205
206 - name: Publish distribution
207 if: steps.pypi-check.outputs.exists != 'true'
208 uses: pypa/gh-action-pypi-publish@release/v1
209 with:
210 skip-existing: true