Multi-target against .NET 9 RC2 #964
This file contains 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
# General links | |
# https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables | |
# https://docs.github.com/en/actions/learn-github-actions/contexts#github-context | |
# https://docs.github.com/en/webhooks-and-events/webhooks/webhook-events-and-payloads | |
# https://docs.github.com/en/actions/learn-github-actions/expressions | |
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions | |
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs | |
name: Build | |
on: | |
push: | |
branches: [ 'master', 'release/**' ] | |
pull_request: | |
branches: [ 'master', 'release/**' ] | |
release: | |
types: [published] | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
env: | |
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true | |
DOTNET_CLI_TELEMETRY_OPTOUT: true | |
jobs: | |
build-and-test: | |
timeout-minutes: 60 | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, windows-latest, macos-latest] | |
runs-on: ${{ matrix.os }} | |
permissions: | |
contents: read | |
steps: | |
- name: Tune GitHub-hosted runner network | |
uses: smorimoto/tune-github-hosted-runner-network@v1 | |
- name: Setup PostgreSQL | |
uses: ikalnytskyi/action-setup-postgres@v6 | |
with: | |
username: postgres | |
password: postgres | |
- name: Setup .NET | |
uses: actions/setup-dotnet@v4 | |
with: | |
dotnet-version: | | |
6.0.x | |
8.0.x | |
9.0.x | |
- name: Show installed versions | |
shell: pwsh | |
run: | | |
Write-Host "$(pwsh --version) is installed at $PSHOME" | |
psql --version | |
Write-Host "Active .NET SDK: $(dotnet --version)" | |
- name: Git checkout | |
uses: actions/checkout@v4 | |
- name: Restore tools | |
run: | | |
dotnet tool restore | |
- name: Restore packages | |
run: | | |
dotnet restore | |
- name: Calculate version suffix | |
shell: pwsh | |
run: | | |
if ($env:GITHUB_REF_TYPE -eq 'tag') { | |
# Get the version prefix/suffix from the git tag. For example: 'v1.0.0-preview1-final' => '1.0.0' and 'preview1-final' | |
$segments = $env:GITHUB_REF_NAME -split "-" | |
$versionPrefix = $segments[0].TrimStart('v') | |
$versionSuffix = $segments.Length -eq 1 ? '' : $segments[1..$($segments.Length - 1)] -join '-' | |
[xml]$xml = Get-Content Directory.Build.props | |
$configuredVersionPrefix = $xml.Project.PropertyGroup.JsonApiDotNetCoreVersionPrefix | Select-Object -First 1 | |
if ($configuredVersionPrefix -ne $versionPrefix) { | |
Write-Error "Version prefix from git release tag '$versionPrefix' does not match version prefix '$configuredVersionPrefix' stored in Directory.Build.props." | |
# To recover from this: | |
# - Delete the GitHub release | |
# - Run: git push --delete origin the-invalid-tag-name | |
# - Adjust JsonApiDotNetCoreVersionPrefix in Directory.Build.props, commit and push | |
# - Recreate the GitHub release | |
} | |
} | |
else { | |
# Get the version suffix from the auto-incrementing build number. For example: '123' => 'master-00123' | |
$revision = "{0:D5}" -f [convert]::ToInt32($env:GITHUB_RUN_NUMBER, 10) | |
$branchName = ![string]::IsNullOrEmpty($env:GITHUB_HEAD_REF) ? $env:GITHUB_HEAD_REF : $env:GITHUB_REF_NAME | |
$safeName = $branchName.Replace('/', '-').Replace('_', '-') | |
$versionSuffix = "$safeName-$revision" | |
} | |
Write-Output "Using version suffix: $versionSuffix" | |
Write-Output "PACKAGE_VERSION_SUFFIX=$versionSuffix" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
- name: Build | |
shell: pwsh | |
run: | | |
dotnet build --no-restore --configuration Release /p:VersionSuffix=$env:PACKAGE_VERSION_SUFFIX | |
- name: Test | |
env: | |
# Override log levels, to reduce logging output when running tests in ci-build. | |
Logging__LogLevel__Microsoft.Hosting.Lifetime: 'None' | |
Logging__LogLevel__Microsoft.AspNetCore.Hosting.Diagnostics: 'None' | |
Logging__LogLevel__Microsoft.Extensions.Hosting.Internal.Host: 'None' | |
Logging__LogLevel__Microsoft.EntityFrameworkCore.Database.Command: 'None' | |
Logging__LogLevel__JsonApiDotNetCore: 'None' | |
run: | | |
dotnet test --no-build --configuration Release --collect:"XPlat Code Coverage" --logger "GitHubActions;summary.includeSkippedTests=true" | |
- name: Upload coverage to codecov.io | |
if: matrix.os == 'ubuntu-latest' | |
env: | |
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
uses: codecov/codecov-action@v4 | |
with: | |
fail_ci_if_error: true | |
verbose: true | |
- name: Generate packages | |
shell: pwsh | |
run: | | |
dotnet pack --no-build --configuration Release --output $env:GITHUB_WORKSPACE/artifacts/packages /p:VersionSuffix=$env:PACKAGE_VERSION_SUFFIX | |
- name: Upload packages to artifacts | |
if: matrix.os == 'ubuntu-latest' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: packages | |
path: artifacts/packages | |
- name: Generate documentation | |
shell: pwsh | |
env: | |
# This contains the git tag name on release; in that case we build the docs without publishing them. | |
DOCFX_SOURCE_BRANCH_NAME: ${{ github.base_ref || github.ref_name }} | |
run: | | |
cd docs | |
& ./generate-examples.ps1 | |
dotnet docfx docfx.json | |
if ($LastExitCode -ne 0) { | |
Write-Error "docfx failed with exit code $LastExitCode." | |
} | |
Copy-Item CNAME _site/CNAME | |
Copy-Item home/*.html _site/ | |
Copy-Item home/*.ico _site/ | |
New-Item -Force _site/styles -ItemType Directory | Out-Null | |
Copy-Item -Recurse home/assets/* _site/styles/ | |
- name: Upload documentation to artifacts | |
if: matrix.os == 'ubuntu-latest' | |
uses: actions/upload-artifact@v4 | |
with: | |
name: documentation | |
path: docs/_site | |
inspect-code: | |
timeout-minutes: 60 | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, windows-latest, macos-latest] | |
runs-on: ${{ matrix.os }} | |
permissions: | |
contents: read | |
steps: | |
- name: Tune GitHub-hosted runner network | |
uses: smorimoto/tune-github-hosted-runner-network@v1 | |
- name: Setup .NET | |
uses: actions/setup-dotnet@v4 | |
with: | |
dotnet-version: | | |
6.0.x | |
8.0.x | |
9.0.x | |
- name: Git checkout | |
uses: actions/checkout@v4 | |
- name: Restore tools | |
run: | | |
dotnet tool restore | |
- name: InspectCode | |
shell: pwsh | |
run: | | |
$inspectCodeOutputPath = Join-Path $env:RUNNER_TEMP 'jetbrains-inspectcode-results.xml' | |
Write-Output "INSPECT_CODE_OUTPUT_PATH=$inspectCodeOutputPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
dotnet jb inspectcode JsonApiDotNetCore.sln --build --dotnetcoresdk=$(dotnet --version) --output="$inspectCodeOutputPath" --format="xml" --profile=WarningSeverities.DotSettings --properties:Configuration=Release --properties:ContinuousIntegrationBuild=false --properties:RunAnalyzers=false --severity=WARNING --verbosity=WARN -dsl=GlobalAll -dsl=GlobalPerProduct -dsl=SolutionPersonal -dsl=ProjectPersonal | |
- name: Verify outcome | |
shell: pwsh | |
run: | | |
[xml]$xml = Get-Content $env:INSPECT_CODE_OUTPUT_PATH | |
if ($xml.report.Issues -and $xml.report.Issues.Project) { | |
foreach ($project in $xml.report.Issues.Project) { | |
if ($project.Issue.Count -gt 0) { | |
$project.ForEach({ | |
Write-Output "`nProject $($project.Name)" | |
$failed = $true | |
$_.Issue.ForEach({ | |
$issueType = $xml.report.IssueTypes.SelectSingleNode("IssueType[@Id='$($_.TypeId)']") | |
$severity = $_.Severity ?? $issueType.Severity | |
Write-Output "[$severity] $($_.File):$($_.Line) $($_.TypeId): $($_.Message)" | |
}) | |
}) | |
} | |
} | |
if ($failed) { | |
Write-Error "One or more projects failed code inspection." | |
} | |
} | |
cleanup-code: | |
timeout-minutes: 60 | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, windows-latest, macos-latest] | |
runs-on: ${{ matrix.os }} | |
permissions: | |
contents: read | |
steps: | |
- name: Tune GitHub-hosted runner network | |
uses: smorimoto/tune-github-hosted-runner-network@v1 | |
- name: Setup .NET | |
uses: actions/setup-dotnet@v4 | |
with: | |
dotnet-version: | | |
6.0.x | |
8.0.x | |
9.0.x | |
- name: Git checkout | |
uses: actions/checkout@v4 | |
with: | |
fetch-depth: 2 | |
- name: Restore tools | |
run: | | |
dotnet tool restore | |
- name: Restore packages | |
run: | | |
dotnet restore | |
- name: CleanupCode (on PR diff) | |
if: github.event_name == 'pull_request' | |
shell: pwsh | |
run: | | |
# Not using the environment variables for SHAs, because they may be outdated. This may happen on force-push after the build is queued, but before it starts. | |
# The below works because HEAD is detached (at the merge commit), so HEAD~1 is at the base branch. When a PR contains no commits, this job will not run. | |
$headCommitHash = git rev-parse HEAD | |
$baseCommitHash = git rev-parse HEAD~1 | |
Write-Output "Running code cleanup on commit range $baseCommitHash..$headCommitHash in pull request." | |
dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --max-runs=5 --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN -f commits -a $headCommitHash -b $baseCommitHash --fail-on-diff --print-diff | |
- name: CleanupCode (on branch) | |
if: github.event_name == 'push' || github.event_name == 'release' | |
shell: pwsh | |
run: | | |
Write-Output "Running code cleanup on all files." | |
dotnet regitlint -s JsonApiDotNetCore.sln --print-command --skip-tool-check --jb --dotnetcoresdk=$(dotnet --version) --jb-profile="JADNC Full Cleanup" --jb --properties:Configuration=Release --jb --properties:RunAnalyzers=false --jb --verbosity=WARN --fail-on-diff --print-diff | |
publish: | |
timeout-minutes: 60 | |
runs-on: ubuntu-latest | |
needs: [ build-and-test, inspect-code, cleanup-code ] | |
if: ${{ !github.event.pull_request.head.repo.fork }} | |
permissions: | |
packages: write | |
contents: write | |
steps: | |
- name: Tune GitHub-hosted runner network | |
uses: smorimoto/tune-github-hosted-runner-network@v1 | |
- name: Download artifacts | |
uses: actions/download-artifact@v4 | |
- name: Publish to GitHub Packages | |
if: github.event_name == 'push' || github.event_name == 'release' | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
shell: pwsh | |
run: | | |
dotnet nuget add source --username 'json-api-dotnet' --password "$env:GITHUB_TOKEN" --store-password-in-clear-text --name 'github' 'https://nuget.pkg.github.com/json-api-dotnet/index.json' | |
dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:GITHUB_TOKEN" --source 'github' | |
- name: Publish documentation | |
if: github.event_name == 'push' && github.ref == 'refs/heads/master' | |
uses: peaceiris/actions-gh-pages@v4 | |
with: | |
github_token: ${{ secrets.GITHUB_TOKEN }} | |
publish_branch: gh-pages | |
publish_dir: ./documentation | |
commit_message: 'Auto-generated documentation from' | |
- name: Publish to NuGet | |
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/v') | |
env: | |
NUGET_ORG_API_KEY: ${{ secrets.NUGET_ORG_API_KEY }} | |
shell: pwsh | |
run: | | |
dotnet nuget push "$env:GITHUB_WORKSPACE/packages/*.nupkg" --api-key "$env:NUGET_ORG_API_KEY" --source 'nuget.org' |