From b60ef10eb1bbe4a371ffda1b8a91c49f53489c54 Mon Sep 17 00:00:00 2001 From: Daniel Grimes Date: Sun, 12 Jul 2026 12:46:04 +0000 Subject: [PATCH] ci(release): switch NuGet publish to Trusted Publishing (OIDC, keyless) Replace the long-lived NUGET_API_KEY secret with NuGet Trusted Publishing: the release job now requests a GitHub OIDC token (id-token: write) and exchanges it via NuGet/login@v1 (SHA-pinned) for a short-lived (1h) API key minted right before the push. Per NuGet's guidance that API keys are discouraged for automated publishing. Requires a one-time nuget.org policy (owner=grinidx, repo=UniswapSharp, workflow=release.yml) and a NUGET_USER secret (nuget.org profile username, not a key). Updated CLAUDE.md publishing note accordingly. --- .github/workflows/release.yml | 16 +++++++++++++--- CLAUDE.md | 6 ++++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d3d570..059b947 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,6 +12,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: write # attach assets to the GitHub Release + id-token: write # OIDC token for NuGet Trusted Publishing (keyless, no long-lived API key) steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 @@ -32,11 +33,20 @@ jobs: - name: Pack run: dotnet pack src/UniswapSharp/UniswapSharp.csproj -c Release -o ./artifacts --no-build + # Trusted Publishing: exchange the GitHub OIDC token for a short-lived (1 hour) NuGet API key. + # No long-lived secret to store/rotate. Requires a policy on nuget.org: + # Repository Owner: grinidx · Repository: UniswapSharp · Workflow File: release.yml + # NUGET_USER is your nuget.org profile username (not email); store it as a repo secret/variable. + - name: NuGet login (OIDC → temporary API key) + id: nuget-login + uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1.2.0 + with: + user: ${{ secrets.NUGET_USER }} + - name: Push to NuGet - env: - NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} run: | - dotnet nuget push "./artifacts/*.nupkg" --api-key "$NUGET_API_KEY" \ + dotnet nuget push "./artifacts/*.nupkg" \ + --api-key "${{ steps.nuget-login.outputs.NUGET_API_KEY }}" \ --source https://api.nuget.org/v3/index.json --skip-duplicate - name: Attach artifacts to GitHub Release diff --git a/CLAUDE.md b/CLAUDE.md index c1b144a..28749f8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -126,8 +126,10 @@ place. Remaining work is **Phase B** (V3 feature-parity port) and beyond. 3. **`CurrencyAmount.ToExact` hardening** - DONE. Reimplemented with exact `BigInteger` arithmetic (Decimal.js parity); the old `(decimal)` cast overflowed for large amounts. Hardened test-first, incl. a max-uint256 case (`CurrencyAmountTests.cs`). -4. **NuGet packaging** - DONE (metadata, SourceLink, symbols, MinVer, tag-driven release). To publish, - add the `NUGET_API_KEY` secret and push a `v*` tag; `1.0.0` is reserved for V3-parity-complete. +4. **NuGet packaging** - DONE (metadata, SourceLink, symbols, MinVer `v`-prefixed tag-driven release). + Publishing uses **NuGet Trusted Publishing (OIDC, keyless)** via `release.yml`: configure a trusted-publishing + policy on nuget.org (owner `grinidx`, repo `UniswapSharp`, workflow `release.yml`), set the `NUGET_USER` + repo secret to your nuget.org profile username, then push a `v*` tag. No long-lived API key is stored. 5. **README + usage example** - DONE (see `README.md` + `docs/PORTING.md`); keep in sync as stubs land. 6. **V4 (later phase)** - Uniswap V4 reuses V3's concentrated-liquidity math (ticks, sqrt-price) and adds the singleton `PoolManager`, hooks and flash accounting. It is