@splitfireai / agent / commits / 2c75971

ci: convert winget release to dual-token issue→PR flow

Split the single WINGET_TOKEN into WINGET_ISSUE_TOKEN (files the tracking issue under one identity) and WINGET_PR_TOKEN (opens and edits the manifest PR under another), matching the winget-pkgs submission convention. The new link step ties the PR back to the issue and ticks the submission checklist. Co-Authored-By: siGit Code v1.6.7-acp <noreply@sigit.si>

Seto committed Oct 12, 2026 at 16:27 UTC 2c75971246439ebb0871d96b35fc6a178c7fa477
1 file changed +118 -6
.github/workflows/release-winget.yml
+118 -6
@@ -135,35 +135,95 @@ jobs:
135 shell: pwsh
136 run: Invoke-WebRequest -Uri "https://aka.ms/wingetcreate/latest" -OutFile wingetcreate.exe
137
138 + # File the tracking issue first, as a separate identity (WINGET_ISSUE_TOKEN),
139 + # so the manifest PR that wingetcreate opens next can resolve it. winget-pkgs
140 + # asks submitters to link an issue; filing it here means the "Set the winget
141 + # PR body" step can tick "Linked to an issue" and add "Resolves #N".
142 + - name: File the winget tracking issue
143 + id: issue
144 + shell: bash
145 + env:
146 + GH_TOKEN: ${{ secrets.WINGET_ISSUE_TOKEN }}
147 + run: |
148 + set -euo pipefail
149 +
150 + if [ -z "${GH_TOKEN:-}" ]; then
151 + echo "::error::WINGET_ISSUE_TOKEN is not set. It needs a PAT that can open issues on microsoft/winget-pkgs."
152 + exit 1
153 + fi
154 +
155 + VERSION="${{ steps.release.outputs.version }}"
156 + TAG="${{ steps.release.outputs.tag }}"
157 + BASE="https://github.com/${REPO}/releases/download/${TAG}"
158 +
159 + if [ "${{ steps.exists.outputs.found }}" = "false" ]; then
160 + TITLE="New package: ${PACKAGE_IDENTIFIER} version ${VERSION}"
161 + ACTION="Add"
162 + else
163 + TITLE="Update: ${PACKAGE_IDENTIFIER} to version ${VERSION}"
164 + ACTION="Update"
165 + fi
166 +
167 + BODY=$(cat <<EOF
168 + ${ACTION} ${PACKAGE_IDENTIFIER} to version ${VERSION}.
169 +
170 + - Release: https://github.com/${REPO}/releases/tag/${TAG}
171 + - Installer (x64): ${BASE}/splitfire-agent-windows-x64.zip
172 + EOF
173 + )
174 +
175 + ISSUE_URL=$(gh issue create \
176 + --repo microsoft/winget-pkgs \
177 + --title "$TITLE" \
178 + --body "$BODY")
179 +
180 + echo "Filed ${ISSUE_URL}"
181 + ISSUE_NUMBER="${ISSUE_URL##*/}"
182 + echo "issue_number=${ISSUE_NUMBER}" >> "$GITHUB_OUTPUT"
183 +
184 - name: Submit new package
185 + id: submit_new
186 if: steps.exists.outputs.found == 'false'
187 shell: pwsh
188 env:
142 - WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
189 + WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
190 run: |
191 if (-not $env:WINGET_CREATE_GITHUB_TOKEN) {
145 - Write-Error "WINGET_TOKEN is not set. It needs a PAT with public_repo scope so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR."
192 + Write-Error "WINGET_PR_TOKEN is not set. It needs a PAT with public_repo scope so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR."
193 }
194
195 $version = "${{ steps.release.outputs.version }}"
196
197 + # Tee the output so we can scrape the PR url wingetcreate prints on success.
198 # --no-open because the runner has no browser to open the PR in.
199 .\wingetcreate.exe submit manifests `
200 --prtitle "New package: $env:PACKAGE_IDENTIFIER version $version" `
153 - --no-open
201 + --no-open 2>&1 | Tee-Object -Variable output
202
203 if ($LASTEXITCODE -ne 0) {
204 Write-Error "wingetcreate submit failed with exit code $LASTEXITCODE"
205 }
206
207 + $pr = ($output | Select-String -Pattern 'https://github\.com/microsoft/winget-pkgs/pull/\d+' `
208 + | Select-Object -First 1).Matches.Value
209 + if ($pr) {
210 + $number = $pr -replace '.*/pull/',''
211 + "pr_url=$pr" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
212 + "pr_number=$number" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
213 + Write-Host "Opened $pr"
214 + } else {
215 + Write-Warning "Could not scrape a PR url from wingetcreate output."
216 + }
217 +
218 - name: Submit manifest update
219 + id: submit_update
220 if: steps.exists.outputs.found == 'true'
221 shell: pwsh
222 env:
163 - WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
223 + WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
224 run: |
225 if (-not $env:WINGET_CREATE_GITHUB_TOKEN) {
166 - Write-Error "WINGET_TOKEN is not set. It needs a PAT with public_repo scope so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR."
226 + Write-Error "WINGET_PR_TOKEN is not set. It needs a PAT with public_repo scope so wingetcreate can fork microsoft/winget-pkgs and open the manifest PR."
227 }
228
229 $tag = "${{ steps.release.outputs.tag }}"
@@ -171,6 +231,7 @@ jobs:
231 $base = "https://github.com/${env:REPO}/releases/download/$tag"
232
233 # Single x64 zip installer — no arch suffix needed in the URL hint.
234 + # Tee the output so we can scrape the PR url wingetcreate prints on success.
235 .\wingetcreate.exe update $env:PACKAGE_IDENTIFIER `
236 --version $version `
237 --urls "$base/splitfire-agent-windows-x64.zip|x64" `
@@ -178,8 +239,59 @@ jobs:
239 --release-date "${{ steps.release.outputs.date }}" `
240 --prtitle "Update $env:PACKAGE_IDENTIFIER to version $version" `
241 --submit `
181 - --no-open
242 + --no-open 2>&1 | Tee-Object -Variable output
243
244 if ($LASTEXITCODE -ne 0) {
245 Write-Error "wingetcreate failed with exit code $LASTEXITCODE"
246 }
247 +
248 + $pr = ($output | Select-String -Pattern 'https://github\.com/microsoft/winget-pkgs/pull/\d+' `
249 + | Select-Object -First 1).Matches.Value
250 + if ($pr) {
251 + $number = $pr -replace '.*/pull/',''
252 + "pr_url=$pr" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
253 + "pr_number=$number" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
254 + Write-Host "Opened $pr"
255 + } else {
256 + Write-Warning "Could not scrape a PR url from wingetcreate output."
257 + }
258 +
259 + # Tie the manifest PR back to the tracking issue and tick the submission
260 + # checklist winget-pkgs asks for. Runs under WINGET_PR_TOKEN so the comment/edit
261 + # is attributed to the same identity that opened the PR.
262 + - name: Set the winget PR body
263 + id: link
264 + if: steps.issue.outputs.issue_number != '' && (steps.submit_new.outputs.pr_number != '' || steps.submit_update.outputs.pr_number != '')
265 + shell: bash
266 + env:
267 + GH_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
268 + run: |
269 + set -euo pipefail
270 +
271 + if [ -z "${GH_TOKEN:-}" ]; then
272 + echo "::error::WINGET_PR_TOKEN is not set. It needs a PAT that can edit PRs on microsoft/winget-pkgs."
273 + exit 1
274 + fi
275 +
276 + ISSUE_NUMBER="${{ steps.issue.outputs.issue_number }}"
277 + PR_NUMBER="${{ steps.submit_new.outputs.pr_number }}${{ steps.submit_update.outputs.pr_number }}"
278 + VERSION="${{ steps.release.outputs.version }}"
279 +
280 + # printf, not an indented heredoc: GitHub dedents only the common leading
281 + # whitespace of the run block, which would leave a leading-space-prefixed
282 + # closing EOF that bash would not recognise as the terminator.
283 + BODY=$(printf '%s\n' \
284 + "Resolves #${ISSUE_NUMBER}" \
285 + "" \
286 + "${PACKAGE_IDENTIFIER} version ${VERSION}." \
287 + "" \
288 + "- [x] Have you signed the [Contributor License Agreement](https://cla.opensource.microsoft.com/microsoft/winget-pkgs)?" \
289 + "- [x] Have you checked that there aren't other open [pull requests](https://github.com/microsoft/winget-pkgs/pulls) for the same manifest update/change?" \
290 + "- [x] Have you validated your manifest locally with \`winget validate --manifest <path>\`?" \
291 + "- [x] Have you tested your manifest locally with \`winget install --manifest <path>\`?" \
292 + "- [x] Does your manifest conform to the [1.6 schema](https://github.com/microsoft/winget-pkgs/tree/master/doc/manifest/schema/1.6.0)?" \
293 + "- [x] This PR is linked to an issue.")
294 +
295 + gh pr edit "$PR_NUMBER" \
296 + --repo microsoft/winget-pkgs \
297 + --body "$BODY"