From 38855dc8d930ab1e4bf7c56892da41191882e747 Mon Sep 17 00:00:00 2001 From: Alyx Dallagiacomo <47258081+AlyxSharkBite@users.noreply.github.com> Date: Tue, 1 Sep 2026 07:49:34 -0700 Subject: [PATCH] Add a trusted-publishing workflow and fix the package metadata publish.yml pushes the exact assets attached to a published GitHub release to NuGet.org, authenticated by trusted publishing (OIDC) against a policy scoped to this repository, this workflow file and the `release` environment. Two human gates stand in front of the irreversible push: publishing the release, and approving the environment. The csproj pointed PackageProjectUrl at upstream LZO, which NuGet renders as "Project website"; it now points at this repository, with upstream attribution staying in the description and README. The description leads with the GPL-2.0-or-later consequence so it is visible on the gallery page rather than only behind the license link, and the package gains explicit RepositoryUrl and tags. Co-Authored-By: Claude Fable 5 --- .github/workflows/publish.yml | 120 +++++++++++++++++++++++++++ src/MiniLzoSharp/MiniLzoSharp.csproj | 10 ++- 2 files changed, 127 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..b4e8a69 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,120 @@ +name: Publish to NuGet.org + +# Publishes the exact package that was attached to a GitHub release. It does not build one: the +# assets uploaded by package.yml are downloaded and pushed as-is, so what reaches NuGet.org is +# byte for byte what the release carries and what the tests passed against. +# +# Authentication is trusted publishing (OIDC). NuGet.org verifies a short-lived, GitHub-signed +# token against a policy naming this repository, this workflow file and the release environment, +# then issues an API key valid for one hour. There is no long-lived secret to leak or rotate. +# +# Publishing to NuGet.org cannot be undone: a package can be unlisted but never deleted. Two +# deliberate human steps therefore stand in front of it — publishing the GitHub release, and +# approving the release environment. + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Release tag to publish, for example v1.0.0' + required: true + type: string + +permissions: + contents: read + +concurrency: + group: publish-${{ github.event.release.tag_name || inputs.tag }} + cancel-in-progress: false + +env: + DOTNET_NOLOGO: true + DOTNET_CLI_TELEMETRY_OPTOUT: true + +jobs: + publish: + name: Push to NuGet.org + runs-on: ubuntu-latest + timeout-minutes: 15 + + # Gates the job on the required reviewer configured for this environment, and scopes the + # trusted publishing policy: a token from any other environment will not be accepted. + environment: + name: release + url: https://www.nuget.org/packages/MiniLzoSharp + + permissions: + # Lets GitHub mint the OIDC token that NuGet.org exchanges for a short-lived API key. + id-token: write + # Reading the release assets to publish. + contents: read + + steps: + - name: Set up .NET + uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 + with: + dotnet-version: '10.0.x' + + - name: Download the release assets + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.event.release.tag_name || inputs.tag }} + run: | + set -euo pipefail + + mkdir -p artifacts + gh release download "$TAG" --repo "${GITHUB_REPOSITORY}" --dir artifacts --pattern '*.nupkg' --pattern '*.snupkg' + ls -l artifacts + + - name: Verify the assets before pushing + env: + TAG: ${{ github.event.release.tag_name || inputs.tag }} + run: | + set -euo pipefail + + # The tag is the source of truth for the version, so confirm the package agrees with it + # rather than trusting the filename. Publishing the wrong version is not reversible. + version="${TAG#v}" + nupkg="artifacts/MiniLzoSharp.${version}.nupkg" + + if [ ! -f "$nupkg" ]; then + echo "::error::Release $TAG has no asset named MiniLzoSharp.${version}.nupkg" + exit 1 + fi + + if ! unzip -p "$nupkg" 'MiniLzoSharp.nuspec' | grep -q "${version}"; then + echo "::error::$nupkg does not declare version ${version}." + exit 1 + fi + + # A package missing its licence would be published without the notice the GPL terms of + # both this work and the upstream LZO library require. + for entry in LICENSE README.md lib/net10.0/MiniLzoSharp.dll; do + if ! unzip -Z1 "$nupkg" | grep -qx "$entry"; then + echo "::error::$nupkg is missing $entry" + exit 1 + fi + done + + echo "Verified MiniLzoSharp ${version}, ready to push." + + - name: Exchange the OIDC token for a short-lived NuGet API key + # Requested immediately before the push: NuGet's temporary keys last one hour, and each + # token buys exactly one key. + id: login + uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1.2.0 + with: + user: ${{ secrets.NUGET_USER }} + + - name: Push + # The matching .snupkg is picked up automatically from the same directory. + # --skip-duplicate makes a re-run after a partial failure safe rather than an error. + run: | + set -euo pipefail + + dotnet nuget push 'artifacts/*.nupkg' \ + --api-key '${{ steps.login.outputs.NUGET_API_KEY }}' \ + --source https://api.nuget.org/v3/index.json \ + --skip-duplicate diff --git a/src/MiniLzoSharp/MiniLzoSharp.csproj b/src/MiniLzoSharp/MiniLzoSharp.csproj index 5f5e7fc..074338e 100644 --- a/src/MiniLzoSharp/MiniLzoSharp.csproj +++ b/src/MiniLzoSharp/MiniLzoSharp.csproj @@ -21,8 +21,10 @@ MiniLzoSharp - A managed C# implementation of the MiniLZO (LZO1X-1) real-time compression codec, - derived from the LZO library by Markus F.X.J. Oberhumer + Licensed GPL-2.0-or-later, inherited from the upstream LZO library: applications + that use this package take on GPL obligations of their own. A managed C# + implementation of the MiniLZO (LZO1X-1) real-time compression codec, derived from + the LZO library by Markus F.X.J. Oberhumer (https://www.oberhumer.com/opensource/lzo/). Produces and consumes raw LZO1X blocks interoperable with the upstream C implementation. @@ -31,7 +33,9 @@ C# implementation Copyright (c) 2026 Alyx Dallagiacomo. Derived from the LZO library, Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer. GPL-2.0-or-later README.md - https://www.oberhumer.com/opensource/lzo/ + https://github.com/AlyxSharkBite/MiniLzoSharp + https://github.com/AlyxSharkBite/MiniLzoSharp + lzo;lzo1x;minilzo;compression;decompression