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"