Publish NuGet Packages #12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Publish NuGet Packages | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Full NuGet package version to produce, for example 4.0.0-preview.1" | |
| required: true | |
| type: string | |
| publish: | |
| description: "Push packages to the configured NuGet source" | |
| required: true | |
| default: false | |
| type: boolean | |
| nuget_user: | |
| description: "NuGet.org username/profile name. Uses repository variable NUGET_USER when omitted." | |
| required: false | |
| default: "" | |
| type: string | |
| skip_duplicate: | |
| description: "Pass --skip-duplicate to dotnet nuget push" | |
| required: true | |
| default: true | |
| type: boolean | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: publish-nuget-${{ github.ref_name }} | |
| cancel-in-progress: false | |
| env: | |
| DOTNET_NOLOGO: true | |
| DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | |
| jobs: | |
| pack: | |
| name: Pack all NuGet packages | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7.0.1 | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v6.0.0 | |
| with: | |
| dotnet-version: 10.0.x | |
| - name: Validate requested version | |
| shell: bash | |
| env: | |
| PACKAGE_VERSION: ${{ inputs.version }} | |
| run: | | |
| set -euo pipefail | |
| if [[ ! "$PACKAGE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z][0-9A-Za-z.-]*)?(\+[0-9A-Za-z][0-9A-Za-z.-]*)?$ ]]; then | |
| echo "Package version must be a SemVer value such as 3.0.8-preview.1 or 4.0.0-preview.1." >&2 | |
| exit 1 | |
| fi | |
| case "$GITHUB_REF_NAME" in | |
| release/3.0) | |
| if [[ "$PACKAGE_VERSION" != 3.0.* ]]; then | |
| echo "release/3.0 publishes the 3.0.x package line; got '$PACKAGE_VERSION'." >&2 | |
| exit 1 | |
| fi | |
| ;; | |
| main) | |
| if [[ "$PACKAGE_VERSION" != 4.* ]]; then | |
| echo "main publishes the 4.x package line; got '$PACKAGE_VERSION'." >&2 | |
| exit 1 | |
| fi | |
| ;; | |
| esac | |
| - name: Restore | |
| run: dotnet restore PdfBoxNet.slnx | |
| - name: Build | |
| run: dotnet build PdfBoxNet.slnx --configuration Release --no-restore | |
| - name: Test | |
| run: dotnet test PdfBoxNet.slnx --configuration Release --no-build --nologo | |
| - name: Pack | |
| shell: bash | |
| env: | |
| PACKAGE_VERSION: ${{ inputs.version }} | |
| run: | | |
| set -euo pipefail | |
| rm -rf artifacts/packages | |
| dotnet pack PdfBoxNet.slnx \ | |
| --configuration Release \ | |
| --no-build \ | |
| --output artifacts/packages \ | |
| -p:ContinuousIntegrationBuild=true \ | |
| -p:Version="$PACKAGE_VERSION" | |
| - name: Verify package output | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| packages=(artifacts/packages/*.nupkg) | |
| if [ "${#packages[@]}" -eq 0 ]; then | |
| echo "No NuGet packages were produced." >&2 | |
| exit 1 | |
| fi | |
| printf '%s\n' "${packages[@]}" | sort | |
| { | |
| echo "### NuGet packages" | |
| echo | |
| for package in "${packages[@]}"; do | |
| echo "- `$(basename "$package")`" | |
| done | sort | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload package artifacts | |
| uses: actions/upload-artifact@v7.0.1 | |
| with: | |
| name: nuget-packages-${{ inputs.version }} | |
| path: artifacts/packages/*.nupkg | |
| if-no-files-found: error | |
| publish: | |
| name: Publish packages | |
| runs-on: ubuntu-latest | |
| needs: pack | |
| if: ${{ inputs.publish }} | |
| environment: nuget.org | |
| permissions: | |
| actions: read | |
| contents: write | |
| id-token: write | |
| steps: | |
| - name: Ref safety check | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| case "$GITHUB_REF_NAME" in | |
| main|release/3.0) | |
| ;; | |
| *) | |
| echo "Publishing is only allowed from main or release/3.0; current ref is '$GITHUB_REF_NAME'." >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v6.0.0 | |
| with: | |
| dotnet-version: 10.0.x | |
| - name: Download package artifacts | |
| uses: actions/download-artifact@v8.0.1 | |
| with: | |
| name: nuget-packages-${{ inputs.version }} | |
| path: artifacts/packages | |
| - name: Resolve NuGet trusted publishing user | |
| id: nuget_user | |
| shell: bash | |
| env: | |
| INPUT_NUGET_USER: ${{ inputs.nuget_user }} | |
| VAR_NUGET_USER: ${{ vars.NUGET_USER }} | |
| run: | | |
| set -euo pipefail | |
| user="${INPUT_NUGET_USER:-$VAR_NUGET_USER}" | |
| if [ -z "$user" ]; then | |
| echo "Set the NUGET_USER repository/environment variable or provide the nuget_user workflow input." >&2 | |
| echo "Use the nuget.org username/profile name, not an email address." >&2 | |
| exit 1 | |
| fi | |
| echo "user=$user" >> "$GITHUB_OUTPUT" | |
| - name: NuGet login via trusted publishing | |
| id: nuget_login | |
| uses: NuGet/login@v1.2.0 | |
| with: | |
| user: ${{ steps.nuget_user.outputs.user }} | |
| - name: Push packages | |
| shell: bash | |
| env: | |
| NUGET_API_KEY: ${{ steps.nuget_login.outputs.NUGET_API_KEY }} | |
| NUGET_SOURCE: https://api.nuget.org/v3/index.json | |
| SKIP_DUPLICATE: ${{ inputs.skip_duplicate }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${NUGET_API_KEY:-}" ]; then | |
| echo "NuGet trusted publishing did not return a temporary API key." >&2 | |
| exit 1 | |
| fi | |
| args=(dotnet nuget push artifacts/packages/*.nupkg --source "$NUGET_SOURCE" --api-key "$NUGET_API_KEY") | |
| if [ "$SKIP_DUPLICATE" = "true" ]; then | |
| args+=(--skip-duplicate) | |
| fi | |
| "${args[@]}" | |
| - name: Create GitHub release | |
| shell: bash | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| PACKAGE_VERSION: ${{ inputs.version }} | |
| run: | | |
| set -euo pipefail | |
| shopt -s nullglob | |
| tag="v${PACKAGE_VERSION}" | |
| title="PdfBox.Net ${PACKAGE_VERSION}" | |
| packages=(artifacts/packages/*.nupkg) | |
| if [ "${#packages[@]}" -eq 0 ]; then | |
| echo "No NuGet packages were found to attach to the GitHub release." >&2 | |
| exit 1 | |
| fi | |
| if gh release view "$tag" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then | |
| echo "GitHub release $tag already exists; refreshing package assets." | |
| gh release upload "$tag" "${packages[@]}" --repo "$GITHUB_REPOSITORY" --clobber | |
| else | |
| gh release create "$tag" "${packages[@]}" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --target "$GITHUB_SHA" \ | |
| --title "$title" \ | |
| --generate-notes | |
| fi | |
| release_url="$(gh release view "$tag" --repo "$GITHUB_REPOSITORY" --json url --jq .url)" | |
| { | |
| echo "### GitHub release" | |
| echo | |
| echo "- [$tag]($release_url)" | |
| } >> "$GITHUB_STEP_SUMMARY" |