-
Notifications
You must be signed in to change notification settings - Fork 0
Combine push-nuget-packages staging workflow and production action. #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3c369e6
c694275
4bb81a8
278cadb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,49 +1,128 @@ | ||
| name: Push NuGet Packages | ||
| description: Downloads .nupkg release assets and publishes them to a NuGet feed using OIDC trusted publishing | ||
| description: Downloads .nupkg release assets and publishes them to a NuGet feed using OIDC trusted publishing or a static API key | ||
| inputs: | ||
| version: | ||
| required: true | ||
| description: Release tag to download package assets from | ||
| description: > | ||
| Release to download package assets from. | ||
| release-state: | ||
| required: true | ||
| description: Whether version identifies a 'published' release (by tag) or a 'draft' release (by name). One of 'published' or 'draft' | ||
| exclude-package-pattern: | ||
| required: false | ||
| default: '' | ||
| description: Glob pattern of package filenames to exclude from the push | ||
| nuget-user: | ||
| publish-mode: | ||
| required: true | ||
| description: NuGet trusted publishing user | ||
| nuget-source-domain: | ||
| description: How to authenticate the push. One of 'trusted-publishing' or 'api-key' | ||
| nuget-user: | ||
| required: false | ||
| default: '' | ||
| description: NuGet trusted publishing user (required when publish-mode is trusted-publishing) | ||
| feed-url: | ||
| required: true | ||
| description: NuGet feed domain used for both the trusted-publishing token service and the package source | ||
| description: > | ||
| NuGet package source URL, used as the push source. For publish-mode | ||
| 'trusted-publishing' its domain also extracted to build the token | ||
| service URL and audience. | ||
| api-key: | ||
| required: false | ||
| default: '' | ||
| description: API key used to authenticate the push (required when publish-mode is api-key) | ||
| runs: | ||
| using: composite | ||
| steps: | ||
| - name: Validate inputs | ||
| shell: pwsh | ||
| run: | | ||
| $publishMode = "${{ inputs.publish-mode }}" | ||
| $validModes = @('trusted-publishing', 'api-key') | ||
| if ($validModes -notcontains $publishMode) { | ||
| throw "publish-mode must be one of: $($validModes -join ', '). Got '$publishMode'." | ||
| } | ||
| $releaseState = "${{ inputs.release-state }}" | ||
| $validReleaseStates = @('published', 'draft') | ||
| if ($validReleaseStates -notcontains $releaseState) { | ||
| throw "release-state must be one of: $($validReleaseStates -join ', '). Got '$releaseState'." | ||
| } | ||
| if ($publishMode -eq 'trusted-publishing' -and -not "${{ inputs.nuget-user }}") { | ||
| throw "nuget-user is required when publish-mode is 'trusted-publishing'." | ||
| } | ||
| if ($publishMode -eq 'trusted-publishing' -and "${{ inputs.api-key }}") { | ||
| throw "api-key must not be set when publish-mode is 'trusted-publishing'." | ||
| } | ||
| if ($publishMode -eq 'api-key' -and -not "${{ inputs.api-key }}") { | ||
| throw "api-key is required when publish-mode is 'api-key'." | ||
| } | ||
| $feedUrl = "${{ inputs.feed-url }}" | ||
| $parsedUri = $null | ||
| if (-not [Uri]::TryCreate($feedUrl, [UriKind]::Absolute, [ref]$parsedUri)) { | ||
| throw "feed-url must be a valid absolute URL. Got '$feedUrl'." | ||
| } | ||
| - name: Setup .NET SDK | ||
| uses: actions/setup-dotnet@v6 | ||
| with: | ||
| dotnet-version: 'latest' | ||
| - name: Download assets from release | ||
| - name: Download assets from published release | ||
| if: inputs.release-state == 'published' | ||
| shell: pwsh | ||
| run: | | ||
| $version = "${{ inputs.version }}" | ||
| gh release download $version --repo "${{ github.repository }}" --pattern "*.nupkg" --dir nugets | ||
| if ($LASTEXITCODE -ne 0) { | ||
| throw "Failed to download release assets for tag '$version'" | ||
| } | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| - name: Download assets from draft release | ||
| if: inputs.release-state == 'draft' | ||
| shell: pwsh | ||
| run: | | ||
| gh release download "${{ inputs.version }}" --repo "${{ github.repository }}" --pattern "*.nupkg" --dir nugets | ||
| $name = "${{ inputs.version }}" | ||
| $releases = gh api "repos/${{ github.repository }}/releases" | ConvertFrom-Json | ||
| $release = $releases | Where-Object { $_.name -eq $name } | Select-Object -First 1 | ||
| if (-not $release) { | ||
| throw "Could not find a draft release named '$name'" | ||
| } | ||
| Write-Output "Found draft release id $($release.id) with tag '$($release.tag_name)' for '$name'" | ||
| gh release download $release.tag_name --repo "${{ github.repository }}" --pattern "*.nupkg" --dir nugets | ||
| if ($LASTEXITCODE -ne 0) { | ||
| throw "Failed to download release assets for tag '$($release.tag_name)'" | ||
| } | ||
| env: | ||
| GH_TOKEN: ${{ github.token }} | ||
| - name: Resolve NuGet feed domain | ||
| id: resolve | ||
| if: inputs.publish-mode == 'trusted-publishing' | ||
| shell: pwsh | ||
| run: | | ||
| $domain = ([Uri]"${{ inputs.feed-url }}").GetLeftPart([System.UriPartial]::Authority) | ||
| Write-Output "domain=$domain" >> $env:GITHUB_OUTPUT | ||
| - name: Get NuGet trusted publishing API key | ||
| if: inputs.publish-mode == 'trusted-publishing' | ||
| uses: NuGet/login@v1 | ||
| id: login | ||
| with: | ||
| user: ${{ inputs.nuget-user }} | ||
| token-service-url: ${{ inputs.nuget-source-domain }}/api/v2/token | ||
| audience: ${{ inputs.nuget-source-domain }} | ||
| - name: Push NuGet packages to production feed | ||
| token-service-url: ${{ steps.resolve.outputs.domain }}/api/v2/token | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Question: I don't recall if I asked this, but why do we use v2 instead of v3?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was just going off of what the default was: https://github.com/NuGet/login#-inputs |
||
| audience: ${{ steps.resolve.outputs.domain }} | ||
| - name: Push NuGet packages | ||
| shell: pwsh | ||
| run: | | ||
| $getChildItemParams = @{ Path = 'nugets/*'; Include = '*.nupkg' } | ||
| $excludePattern = "${{ inputs.exclude-package-pattern }}" | ||
| if ($excludePattern) { $getChildItemParams.Exclude = $excludePattern } | ||
| $packages = Get-ChildItem @getChildItemParams | ||
| Write-Output "Pushing $($packages.Count) NuGet package(s) to ${{ inputs.nuget-source-domain }}:" | ||
| $source = "${{ inputs.feed-url }}" | ||
| $apiKey = if ("${{ inputs.publish-mode }}" -eq 'trusted-publishing') { "${{ steps.login.outputs.NUGET_API_KEY }}" } else { "${{ inputs.api-key }}" } | ||
| Write-Output "Pushing $($packages.Count) NuGet package(s) to $source`:" | ||
| $packages | ForEach-Object { Write-Output " - $($_.Name)" } | ||
| $failed = @() | ||
| foreach ($package in $packages) | ||
| { | ||
| dotnet nuget push $package.FullName --source ${{ inputs.nuget-source-domain }}/api/v2/package --api-key ${{ steps.login.outputs.NUGET_API_KEY }} | ||
| dotnet nuget push $package.FullName --source $source --api-key $apiKey --skip-duplicate | ||
| if ($LASTEXITCODE -ne 0) { $failed += $package.Name } | ||
| } | ||
| if ($failed.Count -gt 0) { | ||
| throw "Failed to push $($failed.Count) package(s): $($failed -join ', ')" | ||
| } | ||
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Praise: fancy!