@smbcloud / cli / commits / bf4a5ef

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