1 name: NuGet 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 contents: read
15
16 env:
17 CARGO_TERM_COLOR: always
18 CLI_CLIENT_SECRET: ${{ secrets.CLI_CLIENT_SECRET }}
19 DOTNET_VERSION: 8.0.x
20 NUGET_PACKAGE_ID: SmbCloud.Cli
21
22 jobs:
23 build-native-binaries:
24 name: Build native binary (${{ matrix.build.NAME }})
25 runs-on: ${{ matrix.build.OS }}
26 strategy:
27 fail-fast: false
28 matrix:
29 build:
30 - {
31 NAME: linux-x64,
32 OS: ubuntu-latest,
33 TARGET: x86_64-unknown-linux-gnu,
34 }
35 - {
36 NAME: linux-arm64,
37 OS: ubuntu-24.04-arm,
38 TARGET: aarch64-unknown-linux-gnu,
39 }
40 - {
41 NAME: windows-x64,
42 OS: windows-2022,
43 TARGET: x86_64-pc-windows-msvc,
44 }
45 - {
46 NAME: windows-arm64,
47 OS: windows-2022,
48 TARGET: aarch64-pc-windows-msvc,
49 }
50 - {
51 NAME: darwin-x64,
52 OS: macos-15-intel,
53 TARGET: x86_64-apple-darwin,
54 }
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 targets: ${{ matrix.build.TARGET }}
94
95 - name: Setup Rust cache
96 uses: Swatinem/rust-cache@v2
97 with:
98 key: nuget-${{ matrix.build.TARGET }}
99
100 - name: Build
101 env:
102 GH_OAUTH_CLIENT_ID: ${{ secrets.GH_OAUTH_CLIENT_ID }}
103 GH_OAUTH_CLIENT_SECRET: ${{ secrets.GH_OAUTH_CLIENT_SECRET }}
104 GH_OAUTH_REDIRECT_URI: ${{ secrets.GH_OAUTH_REDIRECT_URI }}
105 shell: bash
106 run: cargo build --release --locked --target ${{ matrix.build.TARGET }} --package smbcloud-cli
107
108 - name: Prepare artifact
109 shell: bash
110 run: |
111 executable_name="smb"
112 if [[ "${{ matrix.build.OS }}" == "windows-2022" ]]; then
113 executable_name="smb.exe"
114 fi
115
116 mkdir -p "nuget-artifacts/native/${{ matrix.build.NAME }}"
117 cp "target/${{ matrix.build.TARGET }}/release/${executable_name}" "nuget-artifacts/native/${{ matrix.build.NAME }}/${executable_name}"
118
119 - name: Upload native artifact
120 uses: actions/upload-artifact@v7
121 with:
122 name: nuget-native-${{ matrix.build.NAME }}
123 path: nuget-artifacts/native
124
125 pack-nuget:
126 name: Pack NuGet .NET tool
127 runs-on: ubuntu-latest
128 needs: build-native-binaries
129 steps:
130 - name: Checkout
131 uses: actions/checkout@v6
132 with:
133 ref: ${{ github.event.inputs.tag || github.ref }}
134
135 - name: Set the release version
136 shell: bash
137 run: |
138 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
139 release_version="${GITHUB_REF_NAME#v}"
140 else
141 release_version="${{ github.event.inputs.tag }}"
142 release_version="${release_version#v}"
143 fi
144
145 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
146
147 - name: Download native artifacts
148 uses: actions/download-artifact@v7
149 with:
150 pattern: nuget-native-*
151 path: nuget/smbcloud-cli/native
152 merge-multiple: true
153
154 - name: Setup .NET SDK
155 uses: actions/setup-dotnet@v4
156 with:
157 dotnet-version: ${{ env.DOTNET_VERSION }}
158
159 - name: Pack .NET tool
160 shell: bash
161 run: |
162 dotnet pack nuget/smbcloud-cli/SmbCloud.Cli.csproj \
163 --configuration Release \
164 --output nuget/dist \
165 -p:PackageVersion=${RELEASE_VERSION}
166
167 - name: Upload package artifact
168 uses: actions/upload-artifact@v7
169 with:
170 name: nuget-package
171 path: nuget/dist/*.nupkg
172
173 smoke-test:
174 name: Smoke test (${{ matrix.os }})
175 runs-on: ${{ matrix.os }}
176 needs: pack-nuget
177 strategy:
178 fail-fast: false
179 matrix:
180 os:
181 - ubuntu-latest
182 - windows-2022
183 - macos-latest
184 steps:
185 - name: Checkout
186 uses: actions/checkout@v6
187 with:
188 ref: ${{ github.event.inputs.tag || github.ref }}
189
190 - name: Set the release version
191 shell: bash
192 run: |
193 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
194 release_version="${GITHUB_REF_NAME#v}"
195 else
196 release_version="${{ github.event.inputs.tag }}"
197 release_version="${release_version#v}"
198 fi
199
200 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
201
202 - name: Download package artifact
203 uses: actions/download-artifact@v7
204 with:
205 name: nuget-package
206 path: nuget/dist
207
208 - name: Setup .NET SDK
209 uses: actions/setup-dotnet@v4
210 with:
211 dotnet-version: ${{ env.DOTNET_VERSION }}
212
213 - name: Install tool from local package
214 shell: pwsh
215 run: |
216 $packageSource = (Resolve-Path "nuget/dist").Path
217 @"
218 <?xml version="1.0" encoding="utf-8"?>
219 <configuration>
220 <packageSources>
221 <clear />
222 <add key="local" value="$packageSource" />
223 </packageSources>
224 </configuration>
225 "@ | Set-Content -Path "nuget/NuGet.Config"
226
227 dotnet tool install `
228 --tool-path ".tool" `
229 --configfile "nuget/NuGet.Config" `
230 --version "$env:RELEASE_VERSION" `
231 "$env:NUGET_PACKAGE_ID"
232
233 - name: Run smb --version
234 shell: pwsh
235 run: |
236 $toolPath = if ($IsWindows) { ".\.tool\smb.exe" } else { "./.tool/smb" }
237 & $toolPath --version
238
239 publish-nuget:
240 name: Publish to NuGet
241 runs-on: ubuntu-latest
242 needs: smoke-test
243 steps:
244 - name: Checkout
245 uses: actions/checkout@v6
246 with:
247 ref: ${{ github.event.inputs.tag || github.ref }}
248
249 - name: Set the release version
250 shell: bash
251 run: |
252 if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
253 release_version="${GITHUB_REF_NAME#v}"
254 else
255 release_version="${{ github.event.inputs.tag }}"
256 release_version="${release_version#v}"
257 fi
258
259 echo "RELEASE_VERSION=${release_version}" >> "$GITHUB_ENV"
260
261 - name: Download package artifact
262 uses: actions/download-artifact@v7
263 with:
264 name: nuget-package
265 path: nuget/dist
266
267 - name: Setup .NET SDK
268 uses: actions/setup-dotnet@v4
269 with:
270 dotnet-version: ${{ env.DOTNET_VERSION }}
271
272 - name: Check whether release already exists on NuGet
273 id: nuget-check
274 shell: bash
275 run: |
276 package_index_url="https://api.nuget.org/v3-flatcontainer/smbcloud.cli/index.json"
277 if curl -fsS "${package_index_url}" | grep -F "\"${RELEASE_VERSION}\"" >/dev/null; then
278 echo "${NUGET_PACKAGE_ID} ${RELEASE_VERSION} already exists on NuGet, skipping publish"
279 echo "exists=true" >> "$GITHUB_OUTPUT"
280 else
281 echo "exists=false" >> "$GITHUB_OUTPUT"
282 fi
283
284 - name: Publish package
285 if: steps.nuget-check.outputs.exists != 'true'
286 env:
287 NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
288 shell: bash
289 run: |
290 dotnet nuget push nuget/dist/*.nupkg \
291 --api-key "${NUGET_API_KEY}" \
292 --source https://api.nuget.org/v3/index.json \
293 --skip-duplicate