Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions .github/workflows/publish_nuget.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ on:

permissions:
contents: write
id-token: write # Required for NuGet trusted publishing (OIDC token exchange).

jobs:
publish-nuget:
name: publish-nuget
runs-on: ubuntu-latest
environment: nuget # Must match the environment named in the nuget.org Trusted Publisher policy.

steps:
- name: "Checkout"
Expand Down Expand Up @@ -41,8 +43,29 @@ jobs:
- name: "dotnet pack"
run: dotnet pack /p:PackageVersion=${{ env.PACKAGE_VERSION }} -c Release -o ./output

- name: "NuGet login (OIDC)"
# Exchanges the workflow's OIDC token for a short-lived NuGet API key
# under the Trusted Publisher policy configured on nuget.org.
# Requires:
# - permissions.id-token: write at the workflow level (above)
# - environment: nuget on this job (matches the policy)
# - NUGET_USER repo secret = the package owner's nuget.org username
# See https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing
uses: NuGet/login@v1
id: nuget-login
with:
user: ${{ secrets.NUGET_USER }}

- name: "dotnet nuget push"
run: dotnet nuget push "output/*.nupkg" -k ${{ secrets.NUGET_KEY }} -s https://api.nuget.org/v3/index.json --skip-duplicate
run: |
dotnet nuget push "output/*.nupkg" \
--api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }} \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate
dotnet nuget push "output/*.snupkg" \
--api-key ${{ steps.nuget-login.outputs.NUGET_API_KEY }} \
--source https://api.nuget.org/v3/index.json \
--skip-duplicate

- name: "Extract latest release notes"
shell: pwsh
Expand All @@ -64,7 +87,9 @@ jobs:
name: "ShellSyntaxTree ${{ github.ref_name }}"
tag_name: ${{ github.ref_name }}
body_path: RELEASE_NOTES_LATEST.md
files: output/*.nupkg
files: |
output/*.nupkg
output/*.snupkg
draft: false
prerelease: ${{ contains(github.ref_name, '-') }}
env:
Expand Down
31 changes: 30 additions & 1 deletion TOOLING.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,38 @@ parses to its declared `expected` AST.
|---|---|---|
| `NuGet.Config` | repo root | feed configuration (currently `nuget.org`) |
| `dotnet pack` | shell | produces `.nupkg` and `.snupkg` (symbol package) |
| `dotnet nuget push` | CI only (`NUGET_KEY` secret) | publishes to `nuget.org` on tag |
| `dotnet nuget push` | CI only (`NuGet/login@v1` OIDC) | publishes to `nuget.org` on tag |
| Central Package Management | `Directory.Packages.props` | single source of truth for package versions |

### NuGet trusted publishing

`publish_nuget.yml` uses
[trusted publishing](https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing)
— no long-lived API key in repo secrets. The workflow exchanges its
OIDC token for a short-lived API key via the `NuGet/login@v1` action.

Required configuration (one-time, on `nuget.org`):

1. Sign in to nuget.org → **Account → Trusted Publisher Policies** →
**Add new policy**.
2. Publisher: GitHub Actions. Repository owner: `Aaronontheweb`.
Repository: `ShellSyntaxTree`. Workflow file: `publish_nuget.yml`.
Environment: `nuget`. Optional package-name pattern:
`ShellSyntaxTree*`.

Required configuration (one-time, in repo settings):

1. **Settings → Environments → New environment** → name `nuget`.
Optional protection: restrict deployment to tags matching
`v*.*.*`.
2. **Settings → Secrets and variables → Actions → New repository
secret** — `NUGET_USER` set to the nuget.org account username
that owns the package. The legacy `NUGET_KEY` secret can be
deleted once trusted publishing is verified.

The workflow's `permissions: id-token: write` and `environment: nuget`
declarations are required for the OIDC exchange to succeed.

## Source-Level Conventions

- `Directory.Build.props` enforces: `Nullable=enable`, `LangVersion=latest`,
Expand Down
Loading