release.yml builds, tests, packs and creates the GitHub Release, then stops. The upload to nuget.org is done by hand from the web UI, which is what #115 tracks for this release and what the equivalent issue tracks on each of the other package repos.
Two things go wrong with a manual upload:
- The
.snupkg is a separate upload, and it is the one that gets forgotten. The package then carries Source Link metadata that no debugger can use.
- Nothing ties the file on nuget.org to the commit that produced it, beyond trusting that what was uploaded is what the workflow built.
What to add
A push step after the release is created, using NuGet.org Trusted Publishing, which exchanges the workflow's GitHub OIDC token for a short-lived API key so no long-lived secret sits in the repo.
- Add
id-token: write to the job's permissions, alongside the contents: write already there.
- Register a trusted publishing policy on nuget.org for
ScottLilly/CSharpExtender and the Release workflow: https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing
- Push with
dotnet nuget push ./artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate. The .snupkg is pushed automatically alongside the matching .nupkg and needs no separate command.
--skip-duplicate so re-running a partly failed workflow does not fail on a version already pushed.
Confirm trusted publishing is available to this account before wiring it up. If it is not, the fallback is an API key scoped by glob to ScottLilly.* with the shortest practical expiry, stored as a repository secret.
Guard the push
The workflow already takes a draft input. Gate the push the same way, or on an input of its own, so packing and cutting a draft release stays possible without publishing.
A push to nuget.org cannot be undone. A version can be unlisted, but never replaced or removed, so the guard matters more here than anywhere else in the workflow.
release.ymlbuilds, tests, packs and creates the GitHub Release, then stops. The upload to nuget.org is done by hand from the web UI, which is what #115 tracks for this release and what the equivalent issue tracks on each of the other package repos.Two things go wrong with a manual upload:
.snupkgis a separate upload, and it is the one that gets forgotten. The package then carries Source Link metadata that no debugger can use.What to add
A push step after the release is created, using NuGet.org Trusted Publishing, which exchanges the workflow's GitHub OIDC token for a short-lived API key so no long-lived secret sits in the repo.
id-token: writeto the job'spermissions, alongside thecontents: writealready there.ScottLilly/CSharpExtenderand theReleaseworkflow: https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishingdotnet nuget push ./artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate. The.snupkgis pushed automatically alongside the matching.nupkgand needs no separate command.--skip-duplicateso re-running a partly failed workflow does not fail on a version already pushed.Confirm trusted publishing is available to this account before wiring it up. If it is not, the fallback is an API key scoped by glob to
ScottLilly.*with the shortest practical expiry, stored as a repository secret.Guard the push
The workflow already takes a
draftinput. Gate the push the same way, or on an input of its own, so packing and cutting a draft release stays possible without publishing.A push to nuget.org cannot be undone. A version can be unlisted, but never replaced or removed, so the guard matters more here than anywhere else in the workflow.