From 60e68bd1142bacc2540965fec376f8103e72a678 Mon Sep 17 00:00:00 2001 From: John Korsnes Date: Mon, 21 Sep 2026 18:22:55 +0200 Subject: [PATCH 1/3] ci: use NuGet OIDC trusted publishing instead of a long-lived API key Same pattern as Slackbot.Net's Release.yml: NuGet/login exchanges GitHub's OIDC token for a short-lived NuGet API key at publish time, so NUGETORGAPIKEY no longer needs to be stored as a long-lived secret. --- .github/workflows/PreRelease.yml | 9 ++++++++- .github/workflows/Release.yml | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/PreRelease.yml b/.github/workflows/PreRelease.yml index ae51f91..6fb81a4 100644 --- a/.github/workflows/PreRelease.yml +++ b/.github/workflows/PreRelease.yml @@ -6,6 +6,8 @@ on: jobs: build: runs-on: ubuntu-latest + permissions: + id-token: write steps: - uses: actions/checkout@v4 @@ -32,8 +34,13 @@ jobs: useConfigFile: true - name: Pack run: dotnet pack /p:Version=${{ steps.gitversion.outputs.NuGetVersionV2 }}-${{ steps.gitversion.outputs.ShortSha }} /p:InformationalVersion=${{ steps.gitversion.outputs.informationalVersion }} /p:PackageReleaseNotes="https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.gitversion.outputs.NuGetVersionV2 }}" -o ./releases + - name: NuGet login (OIDC → temp API key) + uses: NuGet/login@v1 + id: nuget_login + with: + user: ${{ secrets.NUGET_USER }} - name: Publish - run: dotnet nuget push ./releases/**/*.nupkg -k=${{ secrets.NUGETORGAPIKEY }} -s=nuget.org + run: dotnet nuget push ./releases/**/*.nupkg -k=${{ steps.nuget_login.outputs.NUGET_API_KEY }} -s=nuget.org - run: git log $(git describe --tags --abbrev=0)..HEAD --oneline - name: Log commit messages since last release id: releasenotes diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 00b91bd..420d8b2 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -6,6 +6,9 @@ on: jobs: build: runs-on: ubuntu-latest + permissions: + contents: write + id-token: write steps: - uses: actions/checkout@v3 @@ -32,8 +35,13 @@ jobs: useConfigFile: true - name: Pack run: dotnet pack /p:Version=${{ steps.gitversion.outputs.majorMinorPatch }} /p:InformationalVersion=${{ steps.gitversion.outputs.informationalVersion }} /p:PackageReleaseNotes="https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.gitversion.outputs.majorMinorPatch }}" -o ./releases + - name: NuGet login (OIDC → temp API key) + uses: NuGet/login@v1 + id: nuget_login + with: + user: ${{ secrets.NUGET_USER }} - name: Publish - run: dotnet nuget push ./releases/**/*.nupkg -k=${{ secrets.NUGETORGAPIKEY }} -s=nuget.org + run: dotnet nuget push ./releases/**/*.nupkg -k=${{ steps.nuget_login.outputs.NUGET_API_KEY }} -s=nuget.org - name: Generate CHANGELOG.md id: releasenotes run: | From 62d45f88c1c5e63ac2f16486b39c68db92f6ea40 Mon Sep 17 00:00:00 2001 From: John Korsnes Date: Mon, 21 Sep 2026 18:25:34 +0200 Subject: [PATCH 2/3] ci: consolidate Release/PreRelease into one workflow with a prerelease toggle Same shape as Slackbot.Net's Release.yml: a single workflow_dispatch input picks the version scheme, and the GitHub release step is skipped for prereleases - one workflow to run instead of two near-duplicates. --- .github/workflows/PreRelease.yml | 50 -------------------------------- .github/workflows/Release.yml | 37 ++++++++++++++++++++--- 2 files changed, 33 insertions(+), 54 deletions(-) delete mode 100644 .github/workflows/PreRelease.yml diff --git a/.github/workflows/PreRelease.yml b/.github/workflows/PreRelease.yml deleted file mode 100644 index 6fb81a4..0000000 --- a/.github/workflows/PreRelease.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: PreRelease - -on: - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - permissions: - id-token: write - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 9.0.x - - name: Restore dependencies - run: dotnet restore - - name: Build - run: dotnet build --no-restore - - name: Test - run: dotnet test --no-build --verbosity normal - - run: echo "ACTIONS_ALLOW_UNSECURE_COMMANDS=true" >> $GITHUB_ENV - - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v0 - with: - versionSpec: "5.x" - - name: Determine Version - id: gitversion - uses: gittools/actions/gitversion/execute@v0 - with: - useConfigFile: true - - name: Pack - run: dotnet pack /p:Version=${{ steps.gitversion.outputs.NuGetVersionV2 }}-${{ steps.gitversion.outputs.ShortSha }} /p:InformationalVersion=${{ steps.gitversion.outputs.informationalVersion }} /p:PackageReleaseNotes="https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.gitversion.outputs.NuGetVersionV2 }}" -o ./releases - - name: NuGet login (OIDC → temp API key) - uses: NuGet/login@v1 - id: nuget_login - with: - user: ${{ secrets.NUGET_USER }} - - name: Publish - run: dotnet nuget push ./releases/**/*.nupkg -k=${{ steps.nuget_login.outputs.NUGET_API_KEY }} -s=nuget.org - - run: git log $(git describe --tags --abbrev=0)..HEAD --oneline - - name: Log commit messages since last release - id: releasenotes - run: | - echo 'RELEASE_NOTES<> $GITHUB_ENV - git log $(git describe --tags --abbrev=0)..HEAD --oneline >> $GITHUB_ENV - echo 'EOF' >> $GITHUB_ENV diff --git a/.github/workflows/Release.yml b/.github/workflows/Release.yml index 420d8b2..c2d416f 100644 --- a/.github/workflows/Release.yml +++ b/.github/workflows/Release.yml @@ -2,6 +2,11 @@ name: Release on: workflow_dispatch: + inputs: + prerelease: + description: Publish a prerelease package (skips creating a GitHub release) + type: boolean + default: false jobs: build: @@ -10,6 +15,9 @@ jobs: contents: write id-token: write + outputs: + version: ${{ steps.version.outputs.value }} + steps: - uses: actions/checkout@v3 with: @@ -33,8 +41,16 @@ jobs: uses: gittools/actions/gitversion/execute@v0 with: useConfigFile: true + - name: Resolve package version + id: version + run: | + if [ "${{ inputs.prerelease }}" = "true" ]; then + echo "value=${{ steps.gitversion.outputs.NuGetVersionV2 }}-${{ steps.gitversion.outputs.ShortSha }}" >> "$GITHUB_OUTPUT" + else + echo "value=${{ steps.gitversion.outputs.majorMinorPatch }}" >> "$GITHUB_OUTPUT" + fi - name: Pack - run: dotnet pack /p:Version=${{ steps.gitversion.outputs.majorMinorPatch }} /p:InformationalVersion=${{ steps.gitversion.outputs.informationalVersion }} /p:PackageReleaseNotes="https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.gitversion.outputs.majorMinorPatch }}" -o ./releases + run: dotnet pack /p:Version=${{ steps.version.outputs.value }} /p:InformationalVersion=${{ steps.gitversion.outputs.informationalVersion }} /p:PackageReleaseNotes="https://github.com/$GITHUB_REPOSITORY/releases/tag/${{ steps.version.outputs.value }}" -o ./releases - name: NuGet login (OIDC → temp API key) uses: NuGet/login@v1 id: nuget_login @@ -42,11 +58,24 @@ jobs: user: ${{ secrets.NUGET_USER }} - name: Publish run: dotnet nuget push ./releases/**/*.nupkg -k=${{ steps.nuget_login.outputs.NUGET_API_KEY }} -s=nuget.org + + release: + needs: build + if: ${{ !inputs.prerelease }} + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - run: git log $(git describe --tags --abbrev=0)..HEAD --oneline - name: Generate CHANGELOG.md id: releasenotes run: | gh api repos/$GITHUB_REPOSITORY/releases/generate-notes \ - -f tag_name="${{ steps.gitversion.outputs.majorMinorPatch }}" \ + -f tag_name="${{ needs.build.outputs.version }}" \ -q .body > CHANGELOG.md echo -e "\n\n" >> CHANGELOG.md git log $(git describe --tags --abbrev=0)..HEAD --oneline >> CHANGELOG.md @@ -58,8 +87,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ steps.gitversion.outputs.majorMinorPatch }} - release_name: Release ${{ steps.gitversion.outputs.majorMinorPatch }} + tag_name: ${{ needs.build.outputs.version }} + release_name: Release ${{ needs.build.outputs.version }} body_path: CHANGELOG.md draft: false prerelease: false From 9a61720d00819d1d6cad0df6b40ea5c848cd48f6 Mon Sep 17 00:00:00 2001 From: John Korsnes Date: Mon, 21 Sep 2026 18:31:23 +0200 Subject: [PATCH 3/3] docs: tag the scoped-recurring-actions change as a breaking release +semver: major AddRecurrer's move from singleton to scoped registration (#12) breaks any consumer holding a reference to a recurring action expecting it to stay the same instance across ticks, or calling GetServices() (no longer registered as an open multi-service - only the concrete T is). GitVersion's +semver: major convention (no explicit config override in this repo, so its default regex applies) picks this up for the next release.