Skip to content

[Maintenance] ci(release): migrate NuGet publish to Trusted Publishing (OIDC) #207

Description

@Chris-Wolfgang

Scope

Migrate .github/workflows/release.yaml off secrets.NUGET_API_KEY and onto NuGet Trusted Publishing (OIDC). Removes the long-lived API key from the repo — every release exchanges the workflow's GitHub OIDC token for an ephemeral (~1-hour) push key via NuGet/login@v1.

Why

Two motivations:

  1. Security posture — no long-lived key on GitHub or NuGet to leak, phish, or forget to rotate. If a workflow secret DOES leak, the blast radius is one workflow run.
  2. Fleet standardization — the SECURITY.md "Release path & compromise scope" appendix (tracked in [Maintenance] docs(security): add Release path & compromise scope appendix to SECURITY.md #140) reads identically across every repo when they are all on OIDC. Currently 9 repos are on OIDC and this one is not — the appendix in this repo would have to say NUGET_API_KEY while the fleet says OIDC.

What to do

1. Configure Trusted Publishing on nuget.org (one-time, manual, before merging the workflow change):

For each package this repo publishes (some repos ship multiple), on nuget.org:

  • Package page → ManageTrusted Publishing → Add policy
  • Owner: Chris-Wolfgang
  • Repository: <this repo name>
  • Workflow: .github/workflows/release.yaml

2. Update release.yaml:

Replace the publish-nuget job with the canonical OIDC version. Reference implementations:

Key elements:

  • permissions: { id-token: write, contents: read } (add id-token: write)
  • NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1 (SHA-pinned) as a step, id: nuget-login
  • Publish step uses --api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }} — this is the STEP OUTPUT (ephemeral), NOT secrets.NUGET_API_KEY
  • Remove the NUGET_API_KEY env-var wiring from the publish job — no repo secret is referenced

This is a change to .github/workflows/release.yaml, which is a protected file. Merge via admin-bypass per protected-file-pr-split.

3. After first successful OIDC release:

Blocks

#140 — that appendix will land in this repo's SECURITY.md once this migration is done. The appendix's "Release path" bullet needs to name OIDC for the fleet to be consistent.

Fleet context

Snapshot as of 2026-07-14:

  • Migrated (9): AuditTrail, ETL-FixedWidth, ETL-Json, ETL-SqlBulkCopy, ETL-Transformers, ETL-Xml, Etl-DbClient, Try-Pattern, console-app-template
  • Still on NUGET_API_KEY (17, including this repo): D20-Dice, DateTime-Extensions, DbContextBuilder, ETL-Abstractions, ETL-Csv, ETL-Test-Kit, Extensions-Logging-Data, Hawsey, IAsyncEnumerable-Extensions, ICollection-Extensions, IComparable-Extensions, IEnumerable-Extensions, IEquatable-Extensions, In-memory-Logger, Log-Compressor, String-Extensions, System.Mail-Extensions

Metadata

Metadata

Assignees

No one assigned

    Labels

    maintenance - CI/CDMaintenance: Docker, CI workflow, build/publish pipelinemaintenance-taskA Maintenance sub-issue — actionable improvement work

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions