ci(winget): file Package Request issue first, split into two tokens
Restructure the winget release workflow so the Package Request issue is filed before the manifest PR, then referenced from the PR body with "Resolves #N" (wingetcreate has no --prbody, so a post-submit `gh pr edit` injects it). Split the single WINGET_TOKEN into two role-based secrets so the issue and the PR are authored by two distinct GitHub accounts: - WINGET_ISSUE_TOKEN authors the Package Request issue - WINGET_PR_TOKEN forks winget-pkgs, opens the manifest PR, and edits its body to link the issue (replaces WINGET_TOKEN) Role-based naming keeps this YAML identical across getsigit/sigit and smbcloudXYZ/smbcloud-cli; only the secret values differ per repo. Co-Authored-By: siGit Code v1.6.7-acp <noreply@sigit.si>
keypair34 committed
Oct 12, 2026 at 14:01 UTC
bf4a5efb4c2e7392a2de253cde78905e775b9618
1 file changed
+87
-35
.github/workflows/release-winget.yml
+87
-35
@@ -123,6 +123,68 @@ jobs:
123
shell: pwsh
124
run: Invoke-WebRequest -Uri "https://aka.ms/wingetcreate/latest" -OutFile wingetcreate.exe
125
126
+ # File the Package Request issue *first*, then reference it from the PR
127
+ # with "Resolves #N" below. winget-pkgs' Package Request is an issue
128
+ # *form* (.github/ISSUE_TEMPLATE/package_request.yml): the title must be
129
+ # "[Package Request]: ..." and the body has to carry the labelled fields
130
+ # below (Installer Url especially — without it a maintainer just replies
131
+ # "please provide the installer link"). A free-text body lands as
132
+ # Needs-Triage and can't be acted on.
133
+ #
134
+ # The issue and the PR are deliberately authored by *two different*
135
+ # GitHub accounts, because the author is decided by which PAT creates
136
+ # each one. The role-to-account mapping lives in the repo secrets, not
137
+ # here, so this YAML is identical in getsigit/sigit and smbcloud-cli;
138
+ # only the secret values are swapped:
139
+ #
140
+ # repo WINGET_ISSUE_TOKEN WINGET_PR_TOKEN
141
+ # getsigit/sigit setoelkahfi paydii
142
+ # smbcloudXYZ/... paydii setoelkahfi
143
+ #
144
+ # Both PATs need public_repo scope on microsoft/winget-pkgs (fork + open
145
+ # issues/PRs). WINGET_PR_TOKEN replaces the old single WINGET_TOKEN.
146
+ - name: File the winget Package Request issue
147
+ id: issue
148
+ shell: bash
149
+ env:
150
+ # Authored by the issue account for this repo.
151
+ GH_TOKEN: ${{ secrets.WINGET_ISSUE_TOKEN }}
152
+ run: |
153
+ set -euo pipefail
154
+
155
+ if [ -z "${GH_TOKEN:-}" ]; then
156
+ echo "WINGET_ISSUE_TOKEN is not set. It needs a PAT (public_repo) for the account that should author the Package Request issue." >&2
157
+ exit 1
158
+ fi
159
+
160
+ VERSION="${{ steps.release.outputs.version }}"
161
+ TAG="${{ steps.release.outputs.tag }}"
162
+
163
+ # The release assets, same URLs the update step feeds wingetcreate.
164
+ BASE="https://github.com/${REPO}/releases/download/${TAG}"
165
+ INSTALLER_AMD64="${BASE}/smb-win-amd64.exe"
166
+ INSTALLER_ARM64="${BASE}/smb-win-arm64.exe"
167
+
168
+ ISSUE_BODY=$(cat <<EOF
169
+ Download Page Url: https://github.com/${REPO}/releases/tag/${TAG}
170
+ Publisher: smbCloud
171
+ Package Name: smbCloud CLI
172
+ Description: smbCloud command line interface.
173
+ Package Version: ${VERSION}
174
+ Installer Url: ${INSTALLER_AMD64}
175
+ Installer Url: ${INSTALLER_ARM64}
176
+ EOF
177
+ )
178
+
179
+ ISSUE_URL=$(gh issue create \
180
+ --repo microsoft/winget-pkgs \
181
+ --title "[Package Request]: ${PACKAGE_IDENTIFIER} ${VERSION}" \
182
+ --body "$ISSUE_BODY")
183
+
184
+ echo "Opened issue ${ISSUE_URL}"
185
+ echo "issue_url=${ISSUE_URL}" >> "$GITHUB_OUTPUT"
186
+ echo "issue_number=${ISSUE_URL##*/}" >> "$GITHUB_OUTPUT"
187
+
188
- name: Submit new package
189
id: submit_new
190
if: steps.exists.outputs.found == 'false'
@@ -131,10 +193,10 @@ jobs:
193
# wingetcreate reads the token from this variable. Passing it as
194
# --token instead makes the tool warn that the token can end up in
195
# logs, which on a shared runner is not a warning worth ignoring.
134
- WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
196
+ WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
197
run: |
198
if (-not $env:WINGET_CREATE_GITHUB_TOKEN) {
137
- 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."
199
+ 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."
200
}
201
202
$version = "${{ steps.release.outputs.version }}"
@@ -164,10 +226,10 @@ jobs:
226
if: steps.exists.outputs.found == 'true'
227
shell: pwsh
228
env:
167
- WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_TOKEN }}
229
+ WINGET_CREATE_GITHUB_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
230
run: |
231
if (-not $env:WINGET_CREATE_GITHUB_TOKEN) {
170
- 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."
232
+ 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."
233
}
234
235
$tag = "${{ steps.release.outputs.tag }}"
@@ -198,58 +260,47 @@ jobs:
260
Write-Warning "Could not find the PR URL in wingetcreate output; skipping issue linking."
261
}
262
201
- # wingetcreate has no --prbody flag, so it always opens the PR with the
202
- # winget-pkgs template: an empty Description and an unticked
203
- # "Linked to an issue" box next to a "Resolves #[Issue Number]"
204
- # placeholder. We used to tick that box and fill in the issue number by
205
- # hand after every release. This step does it instead.
263
+ # wingetcreate has no --prbody flag (only --prtitle), so it always opens
264
+ # the PR with the winget-pkgs template: an empty Description and an
265
+ # unticked "Linked to an issue" box next to a "Resolves #[Issue Number]"
266
+ # placeholder. The issue already exists (filed first, above), so this
267
+ # step just rewrites the body to point the PR at it with "Resolves #N".
268
#
207
- # On a first submission it also files the Package Request issue the
208
- # linkable number comes from. Updates to an existing package don't need
209
- # one (the checkbox is "if applicable"), so there we just fill the
210
- # Description.
211
- - name: Link the winget PR to a Package Request issue
269
+ # This must run as the PR author (WINGET_PR_TOKEN) — the account that
270
+ # opened the PR via wingetcreate — since only the author (or a repo
271
+ # maintainer) can edit it.
272
+ - name: Set the winget PR body and link the issue
273
id: link
274
if: >-
275
(steps.submit_new.outputs.pr_number != '') ||
276
(steps.submit_update.outputs.pr_number != '')
277
shell: bash
278
env:
218
- # The PR and the issue both live in microsoft/winget-pkgs, which the
219
- # default GITHUB_TOKEN can't write to. Reuse the wingetcreate PAT,
220
- # which already has the scope to open PRs there.
221
- GH_TOKEN: ${{ secrets.WINGET_TOKEN }}
279
+ GH_TOKEN: ${{ secrets.WINGET_PR_TOKEN }}
280
run: |
281
set -euo pipefail
282
283
PR_URL="${{ steps.submit_new.outputs.pr_url || steps.submit_update.outputs.pr_url }}"
226
- NEW_PACKAGE="${{ steps.exists.outputs.found == 'false' }}"
284
+ ISSUE_NUMBER="${{ steps.issue.outputs.issue_number }}"
285
VERSION="${{ steps.release.outputs.version }}"
286
TAG="${{ steps.release.outputs.tag }}"
287
230
- ISSUE_NUMBER=""
231
- if [ "$NEW_PACKAGE" = "true" ]; then
232
- ISSUE_URL=$(gh issue create \
233
- --repo microsoft/winget-pkgs \
234
- --title "Package Request: ${PACKAGE_IDENTIFIER} ${VERSION}" \
235
- --body "Request to add ${PACKAGE_IDENTIFIER} version ${VERSION} to the Windows Package Manager Community Repository. Installers come from ${TAG} of ${REPO}.")
236
- echo "Opened issue ${ISSUE_URL}"
237
- ISSUE_NUMBER="${ISSUE_URL##*/}"
238
- fi
239
-
240
- # Rewrite the template body: fill the Description, tick the issue
241
- # box when we have an issue, and drop in the real number (or remove
242
- # the placeholder line on updates that aren't linked to anything).
288
if [ -n "$ISSUE_NUMBER" ]; then
289
CHECKBOX="- [x] Linked to an issue (if applicable)"
290
RESOLVES="- Resolves #${ISSUE_NUMBER}"
246
- DESC="Adds ${PACKAGE_IDENTIFIER} version ${VERSION} from ${TAG}."
291
else
292
CHECKBOX="- [ ] Linked to an issue (if applicable)"
293
RESOLVES=""
294
+ fi
295
+
296
+ if [ "${{ steps.exists.outputs.found }}" = "false" ]; then
297
+ DESC="Adds ${PACKAGE_IDENTIFIER} version ${VERSION} from ${TAG}."
298
+ else
299
DESC="Updates ${PACKAGE_IDENTIFIER} to version ${VERSION} from ${TAG}."
300
fi
301
302
+ # Mirrors the current .github/PULL_REQUEST_TEMPLATE.md; keep the
303
+ # checklist items in sync with it (e.g. the 1.12 schema line).
304
BODY=$(cat <<EOF
305
## 📖 Description
306
${DESC}
@@ -260,8 +311,9 @@ jobs:
311
## 📦 Manifest Checklist
312
- [x] Checked that there aren't other open [pull requests](https://github.com/microsoft/winget-pkgs/pulls) for the same manifest update/change
313
- [x] This PR only modifies one (1) manifest
263
- - [x] Validated manifest locally with \`winget validate\`
264
- - [x] Tested manifest locally with \`winget install\`
314
+ - [x] Validated manifest locally with \`winget validate --manifest <directory>\`
315
+ - [x] Tested manifest locally with \`winget install --manifest <directory>\`
316
+ - [x] Manifest conforms to the [1.12 schema](https://github.com/microsoft/winget-pkgs/tree/master/doc/manifest/schema/1.12.0)
317
EOF
318
)
319