Skip to content

Publish DotCraft Harness NuGet #4

Publish DotCraft Harness NuGet

Publish DotCraft Harness NuGet #4

name: Publish DotCraft Harness NuGet
on:
workflow_dispatch:
inputs:
target:
description: "Dry run only, or publish to nuget.org"
required: true
default: dry-run
type: choice
options:
- dry-run
- nuget-org
confirm:
description: "Required for nuget-org: enter the exact DotCraft.Harness version from the project file"
required: false
type: string
permissions:
contents: read
jobs:
pack:
name: Validate, test, and pack
runs-on: ubuntu-latest
outputs:
version: ${{ steps.validate.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Validate release inputs
id: validate
shell: pwsh
env:
PACKAGE_PROJECT: ./src/DotCraft.Harness/DotCraft.Harness.csproj
TARGET: ${{ inputs.target }}
CONFIRM: ${{ inputs.confirm }}
GITHUB_REF_FULL: ${{ github.ref }}
run: |
$ErrorActionPreference = "Stop"
if (!(Test-Path $env:PACKAGE_PROJECT)) {
throw "Package project not found: $($env:PACKAGE_PROJECT)"
}
[xml]$project = Get-Content -Raw $env:PACKAGE_PROJECT
$version = @($project.Project.PropertyGroup | ForEach-Object { $_.Version } | Where-Object { ![string]::IsNullOrWhiteSpace($_) } | Select-Object -First 1)
$version = "$version".Trim()
if ([string]::IsNullOrWhiteSpace($version)) {
throw "Set <Version> in $($env:PACKAGE_PROJECT) before publishing."
}
$previewPattern = '^\d+\.\d+\.\d+-preview\.\d+$'
$stablePattern = '^\d+\.\d+\.\d+$'
if ($version -match $previewPattern) {
$channel = "preview"
}
elseif ($version -match $stablePattern) {
$channel = "stable"
}
else {
throw "DotCraft.Harness <Version> must be MAJOR.MINOR.PATCH-preview.N or MAJOR.MINOR.PATCH. Current value: $version"
}
if ($env:TARGET -eq "nuget-org") {
if ($env:GITHUB_REF_FULL -ne "refs/heads/main") {
throw "nuget.org publishing is allowed only from the main branch."
}
if ($env:CONFIRM -cne $version) {
throw "Confirmation must exactly match the DotCraft.Harness version: $version"
}
}
$indexUrl = "https://api.nuget.org/v3-flatcontainer/dotcraft.harness/index.json"
try {
$index = Invoke-RestMethod -Uri $indexUrl
$versions = @($index.versions)
}
catch {
$statusCode = 0
if ($_.Exception.Response -and $_.Exception.Response.StatusCode) {
$statusCode = [int]$_.Exception.Response.StatusCode
}
if ($statusCode -eq 404) {
$versions = @()
}
else {
throw
}
}
if ($versions -contains $version.ToLowerInvariant()) {
throw "DotCraft.Harness $version already exists on nuget.org."
}
"version=$version" >> $env:GITHUB_OUTPUT
Write-Host "Validated DotCraft.Harness $version ($channel) for $($env:TARGET)."
- name: Restore
run: dotnet restore ./tests/DotCraft.Harness.Tests/DotCraft.Harness.Tests.csproj
- name: Build
shell: pwsh
env:
PACKAGE_VERSION: ${{ steps.validate.outputs.version }}
run: |
$ErrorActionPreference = "Stop"
dotnet build ./tests/DotCraft.Harness.Tests/DotCraft.Harness.Tests.csproj `
--configuration Release `
--no-restore `
/p:Version=$env:PACKAGE_VERSION `
/p:PackageVersion=$env:PACKAGE_VERSION `
/p:ContinuousIntegrationBuild=true
- name: Test
run: dotnet test ./tests/DotCraft.Harness.Tests/DotCraft.Harness.Tests.csproj --configuration Release --no-build
- name: Pack release artifacts
shell: pwsh
env:
PACKAGE_VERSION: ${{ steps.validate.outputs.version }}
run: |
$ErrorActionPreference = "Stop"
New-Item -ItemType Directory -Force -Path artifacts/harness-nuget | Out-Null
dotnet pack ./src/DotCraft.Harness/DotCraft.Harness.csproj `
--configuration Release `
--no-build `
--output artifacts/harness-nuget `
/p:Version=$env:PACKAGE_VERSION `
/p:PackageVersion=$env:PACKAGE_VERSION `
/p:ContinuousIntegrationBuild=true
- name: Test Harness consumer
run: dotnet run --project ./tests/DotCraft.Harness.Consumer/DotCraft.Harness.Consumer.csproj --configuration Release
- name: Upload package artifacts
uses: actions/upload-artifact@v4
with:
name: dotcraft-harness-${{ steps.validate.outputs.version }}
path: artifacts/harness-nuget/*.nupkg
if-no-files-found: error
publish:
name: Publish to nuget.org
needs: pack
if: ${{ inputs.target == 'nuget-org' }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
- name: Download package artifacts
uses: actions/download-artifact@v4
with:
name: dotcraft-harness-${{ needs.pack.outputs.version }}
path: artifacts/harness-nuget
- name: Validate NuGet trusted publishing user
shell: pwsh
env:
NUGET_USER: ${{ vars.NUGET_USER }}
run: |
if ([string]::IsNullOrWhiteSpace($env:NUGET_USER)) {
throw "Set NUGET_USER to the nuget.org username that created the Trusted Publishing policy. Do not use the GitHubActions publisher label or an email address."
}
- name: NuGet login through Trusted Publishing
id: login
uses: NuGet/login@v1
with:
user: ${{ vars.NUGET_USER }}
- name: Push exact package artifact
shell: pwsh
env:
PACKAGE_VERSION: ${{ needs.pack.outputs.version }}
NUGET_API_KEY: ${{ steps.login.outputs.NUGET_API_KEY }}
run: |
$ErrorActionPreference = "Stop"
$package = "artifacts/harness-nuget/DotCraft.Harness.$env:PACKAGE_VERSION.nupkg"
dotnet nuget push $package `
--source https://api.nuget.org/v3/index.json `
--api-key $env:NUGET_API_KEY