From 041fa74422eb28c3d873f7f018a6835ff1d3774d Mon Sep 17 00:00:00 2001 From: Andrei Ivascu <7030530+aivascu@users.noreply.github.com> Date: Mon, 7 Sep 2026 15:46:39 +0300 Subject: [PATCH] Publish to NuGet with Trusted Publishing (OIDC). Exchange a GitHub OIDC token for a short-lived NuGet API key in the release workflow instead of storing a long-lived NUGET_API_KEY. --- .github/workflows/release.yml | 10 +++++++++- build/Build.cs | 6 ++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index afbaeb6..015535b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,9 @@ jobs: windows-latest: name: windows-latest runs-on: windows-latest + permissions: + contents: read + id-token: write steps: - uses: actions/checkout@v7 with: @@ -41,11 +44,16 @@ jobs: .nuke/temp ~/.nuget/packages key: ${{ runner.os }}-${{ hashFiles('**/global.json', '**/*.csproj') }} + - name: NuGet login (OIDC) + id: nuget-login + uses: NuGet/login@v1 + with: + user: ${{ secrets.NUGET_USER }} - name: Run './build.cmd Verify Cover Publish' run: ./build.cmd Verify Cover Publish --no-logo env: GitHubToken: ${{ secrets.GITHUB_TOKEN }} - NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + NUGET_API_KEY: ${{ steps.nuget-login.outputs.NUGET_API_KEY }} - uses: actions/upload-artifact@v7 with: name: testresults diff --git a/build/Build.cs b/build/Build.cs index 50eee2a..052a9cf 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -34,7 +34,7 @@ PublishArtifacts = true, InvokedTargets = [nameof(Verify), nameof(Cover), nameof(Publish)], EnableGitHubToken = true, - ImportSecrets = [Secrets.NuGetApiKey])] + ImportSecrets = [Secrets.NuGetUser])] class Build : NukeBuild { public static int Main() => Execute(x => x.Compile); @@ -54,7 +54,8 @@ class Build : NukeBuild [Parameter("GitHub auth token", Name = "github-token"), Secret] readonly string GitHubToken; [Parameter("Forces the continuous integration build flag")] readonly bool CI; - [Secret][Parameter("NuGet API Key (secret)", Name = Secrets.NuGetApiKey)] readonly string NuGetApiKey; + // On CI this is the short-lived key from NuGet/login (OIDC). Locally you can still pass a classic API key. + [Secret][Parameter("NuGet API Key", Name = Secrets.NuGetApiKey)] readonly string NuGetApiKey; readonly string NuGetSource = "https://api.nuget.org/v3/index.json"; IEnumerable Excluded => @@ -203,5 +204,6 @@ class Build : NukeBuild public static class Secrets { public const string NuGetApiKey = "NUGET_API_KEY"; + public const string NuGetUser = "NUGET_USER"; } } \ No newline at end of file