Skip to content

chore(ci): adopt NuGet trusted publishing (OIDC) for releases#11

Merged
Aaronontheweb merged 1 commit into
devfrom
chore/trusted-publishing
May 10, 2026
Merged

chore(ci): adopt NuGet trusted publishing (OIDC) for releases#11
Aaronontheweb merged 1 commit into
devfrom
chore/trusted-publishing

Conversation

@Aaronontheweb

Copy link
Copy Markdown
Owner

Summary

Replaces the long-lived NUGET_KEY repo secret with NuGet trusted publishing (OIDC). Pattern lifted from netclaw-dev/skill-server's release workflow and matches Microsoft's guidance.

Workflow changes (.github/workflows/publish_nuget.yml)

  • permissions: id-token: write — required for OIDC token issuance to the workflow
  • environment: nuget on the publish-nuget job — links to a GitHub environment that pairs with the trusted publisher policy on nuget.org
  • New step: NuGet/login@v1 with user: \${{ secrets.NUGET_USER }} — exchanges the OIDC token for a short-lived NuGet API key
  • dotnet nuget push uses \${{ steps.nuget-login.outputs.NUGET_API_KEY }} instead of \${{ secrets.NUGET_KEY }}
  • Now also pushes .snupkg (symbol package) and attaches it to the GitHub release alongside the .nupkg

⚠️ One-time setup required before next tag push

This PR doesn't configure the nuget.org policy or the GitHub environment — those are out-of-band manual steps the package owner must complete. Until they're in place, the next `v..` tag push will fail at the NuGet login (OIDC) step.*

On nuget.org

  1. Sign in → Account → Trusted Publisher Policies → Add new policy
  2. Configure:
    • Publisher: GitHub Actions
    • Repository owner: Aaronontheweb
    • Repository name: ShellSyntaxTree
    • Workflow file: publish_nuget.yml
    • Environment: nuget
    • Package owner: your nuget.org username (the one set in NUGET_USER below)
    • Optional: package-name pattern ShellSyntaxTree* (scopes the policy to this package family)

On the repo

  1. Settings → Environments → New environment → name it nuget. Optional: restrict deployment to tags matching v*.*.*.
  2. Settings → Secrets and variables → Actions → add repo secret NUGET_USER (your nuget.org account username — NOT an API key). The legacy NUGET_KEY secret can be deleted once trusted publishing is verified working.

TOOLING.md

Updated the "NuGet" section to describe the new flow plus a new "NuGet trusted publishing" subsection documenting the one-time setup so future contributors find the instructions in the repo.

Verification

  • ✅ Workflow file YAML valid (no syntax errors)
  • ⚠️ End-to-end verification only happens on the next tag push, after the nuget.org policy + nuget environment are in place
  • The id-token: write permission only takes effect on tag-push runs, so this PR's own pr_validation.yml run won't exercise it (pr_validation.yml is unchanged)

Test plan

  • CI passes on Test-ubuntu-latest
  • CI passes on Test-windows-latest

Next

After this PR merges and the one-time nuget.org + repo-environment setup is done, push the v0.1.0-alpha tag (deliberately deferred at PR 7). publish_nuget.yml will use the OIDC flow to publish.

Replaces the long-lived NUGET_KEY repo secret with NuGet trusted
publishing per the netclaw-dev/skill-server pattern and Microsoft's
guidance: https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing

Workflow changes (.github/workflows/publish_nuget.yml):
- permissions.id-token: write (required for OIDC token issuance)
- environment: nuget on the publish-nuget job (links to the GitHub
  environment that backs the trusted publisher policy on nuget.org)
- New step: NuGet/login@v1 with user: ${{ secrets.NUGET_USER }} —
  exchanges the OIDC token for a short-lived NuGet API key
- dotnet nuget push uses ${{ steps.nuget-login.outputs.NUGET_API_KEY }}
  instead of ${{ secrets.NUGET_KEY }}
- Now also pushes .snupkg (symbol package) and uploads it to the
  GitHub release alongside the .nupkg

TOOLING.md updates:
- "NuGet" section mentions the trusted-publishing flow
- New subsection "NuGet trusted publishing" documents the one-time
  nuget.org policy + GitHub environment setup the package owner
  must complete before the next release can succeed

One-time setup required before next tag push:
- nuget.org → Account → Trusted Publisher Policies → add policy for
  GitHub Actions / Aaronontheweb / ShellSyntaxTree / publish_nuget.yml
  / environment "nuget"
- Repo Settings → Environments → create "nuget" environment
- Repo Settings → Secrets → set NUGET_USER (nuget.org username);
  legacy NUGET_KEY can be deleted once verified

The workflow file is the single source of truth; if the trusted
publisher policy isn't configured at tag time, the publish step
fails with a clear "OIDC token rejected" error and no package is
pushed (safer fail-mode than the legacy long-lived API key).
@Aaronontheweb Aaronontheweb enabled auto-merge (squash) May 10, 2026 20:32
@Aaronontheweb Aaronontheweb merged commit 782afa5 into dev May 10, 2026
2 checks passed
@Aaronontheweb Aaronontheweb deleted the chore/trusted-publishing branch May 10, 2026 20:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant