mirror of
https://github.com/OPCFoundation/UA-.NETStandard.git
synced 2026-10-17 05:11:13 +08:00
d623007a3f
# Description Removes the Azure Pipelines CI and package-publishing definitions from `master`. GitHub Actions already owns all CI and package publishing for `master`, but pushes to `master` still queued the Azure definitions. They duplicated the Actions work and posted failing checks, for example [`Nuget Preview (Push Nuget Preview Pack Nugets Debug)`](https://github.com/OPCFoundation/UA-.NETStandard/runs/109065914524) on `19dc504c5`. ## Removed - `azure-pipelines.yml`, `azure-pipelines-preview.yml` - `.azurepipelines/` templates: `ci.yml`, `coverage.yml`, `preview.yml`, `sample-ha-longhaul.yml`, `sln.yml`, `test.yml`, `test-aot.yml` - Helpers only those templates used: `get-matrix.ps1`, `get-root.ps1`, `evaluate-test-results.ps1` - `TrxGateScriptTests`: it tested only `evaluate-test-results.ps1`. The Actions equivalent, `.github/scripts/get-test-verdict.ps1`, keeps its own `CiTestVerdictTests`. ## Kept **OneFuzz:** `.azurepipelines/onefuzz.yml` stays. Submitting to the internal OneFuzz service needs the Azure DevOps-only `onefuzz-task`, which has no GitHub Actions equivalent. The pipeline has no push, PR or schedule trigger, so it never runs on `master` pushes. The public drop build keeps running in the GitHub `fuzz-public-drop` job. **Scripts GitHub Actions still invokes:** these stay in `.azurepipelines/`, so every workflow path and `release.yml`'s candidate-bound checkout keep working. Only `generate-slnx.ps1` changes, and only its comment. | Script | Used by | | --- | --- | | `set-version.ps1` | buildandtest, nightly, nuget-publish, docker-image, stress / stability / long-haul, `run-dotnet-tests` action | | `generate-slnx.ps1`, `signlist{Debug,Release}.txt`, `validate-source-generator-packages.ps1` (+ `expected-packages.txt`) | nuget-publish | | `package-version-policy.ps1`, `validate-nuget-package-set.ps1`, `validate-preview-package-ordering.ps1`, `assert-published-packages-match.ps1` | nuget-publish, release | | `check-coverage.ps1` | buildandtest, nightly | | `validate-migration-plugin.ps1` | buildandtest | I didn't rename the directory on purpose. `release.yml` checks out the candidate commit and runs `./.azurepipelines/package-version-policy.ps1` from it, so moving the scripts would break promotion of any candidate built before the move. ## Docs and comments - `UA.slnx` drops the deleted files. - `codecov.yml`, `coverage-thresholds.json`, `targets.props`, the Redundancy sample test comments, the `.github` scripts and workflows, `CONTRIBUTING.md`, `docs/` and `fuzzing/` no longer describe Azure as running on `master` (`/azp run`, the `azure` Codecov flag, "the Azure gate", the Azure long-haul and AoT legs). - In the Developer Guide, the "Triggering a pipeline run" and "Migration status" sections are replaced by "Pull requests from outside contributors" and "Azure Pipelines on other branches". - The new section names `onefuzz.yml` as the one remaining Azure definition. - It keeps the warning that the `Release` ruleset's Azure required check must be lifted before cutting a new `release/2.<minor>` branch. - `master` is merged in, including the #4555 docs rewrite. Its new `docs/RedundancySampleTests.md` needed the Azure references removed again. `docs/README.md` already had none. ## Reviewer notes - **Azure DevOps side (admin action, not in this PR):** the definitions are configured in the Azure DevOps portal. With the YAML gone, `master` pushes give the CI and preview definitions nothing to run. Disabling definition 14's push trigger/schedule, definition 16's build-completion trigger, and the stale definition 13 stops any residual "file not found" runs. Leave the OneFuzz definition enabled. - `master378`, the 1.x `release/*` lines and the frozen `release/2.0.0` keep their own `azure-pipelines.yml`. This PR only touches `master`. ## Related Issues - Follow-up to #4513 (GitHub Actions for CI and nightly). ## Checklist - [ ] I have signed the [CLA](https://opcfoundation.org/license/cla/ContributorLicenseAgreementv1.0.pdf) and read the [CONTRIBUTING](https://github.com/OPCFoundation/UA-.NETStandard/blob/master/CONTRIBUTING.md) doc. - [ ] I have added tests that prove my fix is effective or that my feature works and increased code coverage. - [x] I have added all necessary documentation. - [ ] I have verified that my changes do not introduce (new) build or analyzer warnings. - [ ] I ran **all** tests locally using the **UA.slnx** solution against at least .net **framework** and .net **10**, and all passed. - [ ] I fixed **all** failing and flaky tests in the CI pipelines and **all** CodeQL warnings. - [ ] I have addressed **all** PR feedback received. This PR removes a test and adds none. Locally, at `9b00da817`, the full `Opc.Ua.Tools.Tests` suite passed on net10.0: 884 passed, 1 skipped. The later commits (OneFuzz restore, merge with `master`) touch only YAML and docs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
475 lines
18 KiB
YAML
475 lines
18 KiB
YAML
name: Nightly full validation
|
|
|
|
# GitHub-hosted equivalent of the full-scope workload Azure Pipelines used to
|
|
# run on a schedule.
|
|
on:
|
|
schedule:
|
|
# Weekly full-scope run, Sunday 02:00 UTC.
|
|
- cron: '0 2 * * 0'
|
|
workflow_dispatch:
|
|
inputs:
|
|
include_macos:
|
|
description: 'Include the macOS runners'
|
|
type: boolean
|
|
default: true
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
# See the identical setting in buildandtest.yml: Nerdbank.GitVersioning
|
|
# appends its cloud-build variables to $GITHUB_ENV once per project, and a
|
|
# parallel solution build tears a line. The `Set cloud version` step already
|
|
# exports the same variables once per job via `nbgv cloud -c -a`.
|
|
NBGV_SetCloudBuildVersionVars: 'false'
|
|
|
|
# Deliberately separate from the pull-request workflow's group, and never
|
|
# cancel-in-progress: a manual full-scope run is expensive and approved, so a
|
|
# new push must not discard it.
|
|
concurrency:
|
|
group: nightly-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
discover:
|
|
name: Expand the full workload
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
tests: ${{ steps.matrix.outputs.tests }}
|
|
builds: ${{ steps.matrix.outputs.builds }}
|
|
crash_corpus_tests: ${{ steps.corpus.outputs.tests }}
|
|
aot_matrix: ${{ steps.aot.outputs.matrix }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Expand the full test and build matrix
|
|
id: matrix
|
|
shell: pwsh
|
|
env:
|
|
INCLUDE_MACOS: ${{ github.event_name == 'schedule' || inputs.include_macos }}
|
|
run: |
|
|
./.github/scripts/get-ci-matrix.ps1 `
|
|
-Scope full `
|
|
-ExcludeMacOS:($env:INCLUDE_MACOS -ne 'true') `
|
|
-ManifestPath '${{ runner.temp }}/workload-manifest.json'
|
|
|
|
# The crash corpus only extends the encoder fuzz project, so its matrix is
|
|
# the same profile table narrowed to that one project rather than a second
|
|
# hand-maintained profile list. macOS is excluded: the corpus job is about
|
|
# input coverage, not platform coverage.
|
|
- name: Expand the crash-corpus matrix
|
|
id: corpus
|
|
shell: pwsh
|
|
run: |
|
|
./.github/scripts/get-ci-matrix.ps1 `
|
|
-Scope full `
|
|
-ExcludeMacOS `
|
|
-OnlyProject 'fuzzing/Opc.Ua.Encoders.Fuzz.Tests/Opc.Ua.Encoders.Fuzz.Tests.csproj'
|
|
|
|
- name: Build the NativeAOT matrix
|
|
id: aot
|
|
shell: pwsh
|
|
env:
|
|
INCLUDE_MACOS: ${{ github.event_name == 'schedule' || inputs.include_macos }}
|
|
run: |
|
|
# Windows is included here and not in the pull-request workflow, so
|
|
# the full-scope run is where win-x64 Native AoT is covered.
|
|
$matrix = @(
|
|
@{ os = 'ubuntu-latest'; rid = 'linux-x64' }
|
|
@{ os = 'windows-latest'; rid = 'win-x64' }
|
|
)
|
|
if ($env:INCLUDE_MACOS -eq 'true') {
|
|
$matrix += @{ os = 'macos-15-intel'; rid = 'osx-x64' }
|
|
$matrix += @{ os = 'macos-latest'; rid = 'osx-arm64' }
|
|
}
|
|
"matrix=$(ConvertTo-Json -InputObject @($matrix) -Compress)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
|
|
- name: Upload the workload manifest
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: workload-manifest
|
|
path: ${{ runner.temp }}/workload-manifest.json
|
|
if-no-files-found: error
|
|
|
|
build-solutions:
|
|
name: build-${{ matrix.entry.name }}
|
|
needs: discover
|
|
runs-on: ${{ matrix.entry.runsOn }}
|
|
timeout-minutes: 120
|
|
strategy:
|
|
fail-fast: false
|
|
max-parallel: 20
|
|
matrix:
|
|
entry: ${{ fromJSON(needs.discover.outputs.builds) }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v6
|
|
with:
|
|
dotnet-version: ${{ matrix.entry.dotnet }}
|
|
|
|
- name: Set cloud version
|
|
shell: pwsh
|
|
run: ./.azurepipelines/set-version.ps1
|
|
|
|
- name: Build ${{ matrix.entry.solution }} (${{ matrix.entry.customTestTarget }})
|
|
shell: pwsh
|
|
env:
|
|
CI_SOLUTION: ${{ matrix.entry.solution }}
|
|
CI_CUSTOM_TEST_TARGET: ${{ matrix.entry.customTestTarget }}
|
|
CI_CONFIGURATION: ${{ matrix.entry.configuration }}
|
|
run: |
|
|
dotnet build $env:CI_SOLUTION `
|
|
--configuration $env:CI_CONFIGURATION `
|
|
"/p:CustomTestTarget=$($env:CI_CUSTOM_TEST_TARGET)"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Host "::error title=Solution build::$($env:CI_SOLUTION) failed to build for $($env:CI_CUSTOM_TEST_TARGET) ($($env:CI_CONFIGURATION))."
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
tests:
|
|
name: test-${{ matrix.entry.name }}
|
|
needs: discover
|
|
runs-on: ${{ matrix.entry.runsOn }}
|
|
timeout-minutes: ${{ matrix.entry.timeoutMinutes }}
|
|
strategy:
|
|
fail-fast: false
|
|
# Bounded so one approved full-scope run cannot take the whole
|
|
# organisation's runner concurrency for itself.
|
|
max-parallel: 40
|
|
matrix:
|
|
entry: ${{ fromJSON(needs.discover.outputs.tests) }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- uses: ./.github/actions/run-dotnet-tests
|
|
with:
|
|
projects: ${{ matrix.entry.projects }}
|
|
custom-test-target: ${{ matrix.entry.customTestTarget }}
|
|
framework: ${{ matrix.entry.framework }}
|
|
configuration: ${{ matrix.entry.configuration }}
|
|
dotnet: ${{ matrix.entry.dotnet }}
|
|
filter: ${{ matrix.entry.filter }}
|
|
hang-timeout: ${{ matrix.entry.hangTimeout }}
|
|
per-project-timeout: ${{ matrix.entry.perProjectTimeout }}
|
|
coverage: ${{ matrix.entry.coverage }}
|
|
artifact-name: dotnet-results-${{ matrix.entry.id }}
|
|
|
|
aot:
|
|
name: aot-${{ matrix.os }}
|
|
needs: discover
|
|
runs-on: ${{ matrix.os }}
|
|
timeout-minutes: 90
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include: ${{ fromJSON(needs.discover.outputs.aot_matrix) }}
|
|
env:
|
|
CONFIGURATION: Release
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v6
|
|
with:
|
|
dotnet-version: '10.0.401'
|
|
|
|
- name: Set cloud version
|
|
shell: pwsh
|
|
run: ./.azurepipelines/set-version.ps1
|
|
|
|
# The three AOT binaries are separate projects to bound the native linker's
|
|
# input, and every one of them is published and run on every AOT platform.
|
|
- name: Publish and run the NativeAOT tests
|
|
shell: pwsh
|
|
env:
|
|
RID: ${{ matrix.rid }}
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$projects = @(
|
|
'tests/Opc.Ua.Aot.Tests/Opc.Ua.Aot.Tests.csproj',
|
|
'tests/Opc.Ua.Aot.Tests.Historian/Opc.Ua.Aot.Tests.Historian.csproj',
|
|
'tests/Opc.Ua.Aot.Tests.Mcp/Opc.Ua.Aot.Tests.Mcp.csproj')
|
|
$failed = @()
|
|
foreach ($project in $projects) {
|
|
$stem = [System.IO.Path]::GetFileNameWithoutExtension($project)
|
|
Write-Host "::group::$stem ($($env:RID))"
|
|
try {
|
|
$output = dotnet publish $project --configuration $env:CONFIGURATION |
|
|
ForEach-Object { Write-Host $_; "$_" }
|
|
if ($LASTEXITCODE -ne 0) {
|
|
# Surface the MSBuild errors in the annotation, not just
|
|
# the exit code buried in the collapsed group.
|
|
$errors = @($output | Where-Object { $_ -match ': error ' } | Select-Object -Unique -First 5)
|
|
$reason = if ($errors.Count -gt 0) { $errors -join ' | ' } else { 'see the step log' }
|
|
throw "Publish failed with exit code $LASTEXITCODE`: $reason"
|
|
}
|
|
|
|
$publishDir = Join-Path (Split-Path $project -Parent) "bin/$($env:CONFIGURATION)/net10.0/$($env:RID)/publish"
|
|
if (-not (Test-Path -LiteralPath $publishDir -PathType Container)) {
|
|
throw "Publish succeeded but '$publishDir' does not exist."
|
|
}
|
|
# Match the exact file name: on Linux and macOS the native
|
|
# executable has no extension, so for 'Opc.Ua.Aot.Tests'
|
|
# PowerShell reports BaseName 'Opc.Ua.Aot' and Extension '.Tests'.
|
|
$name = if ($IsWindows) { "$stem.exe" } else { $stem }
|
|
$executable = Get-ChildItem -LiteralPath $publishDir -File |
|
|
Where-Object { $_.Name -ceq $name } |
|
|
Select-Object -First 1
|
|
if ($null -eq $executable) {
|
|
# A managed publish that silently fell back from NativeAOT
|
|
# would leave a .dll here and nothing to run; that is a
|
|
# failure, not an empty pass.
|
|
$found = (Get-ChildItem -LiteralPath $publishDir -File |
|
|
Where-Object { $_.Name -like "$stem*" } |
|
|
ForEach-Object Name) -join ', '
|
|
throw "No NativeAOT executable '$name' was produced in '$publishDir' (found: $found)."
|
|
}
|
|
|
|
& $executable.FullName --results-directory "./TestResults/$stem"
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "The NativeAOT test run exited with code $LASTEXITCODE."
|
|
}
|
|
}
|
|
catch {
|
|
$failed += $stem
|
|
Write-Host "::error title=$stem ($($env:RID))::$($_.Exception.Message)"
|
|
}
|
|
finally {
|
|
Write-Host '::endgroup::'
|
|
}
|
|
}
|
|
if ($failed.Count -gt 0) {
|
|
throw "NativeAOT failed for: $($failed -join ', ')."
|
|
}
|
|
|
|
- name: Upload NativeAOT results
|
|
if: ${{ always() }}
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: aot-results-${{ matrix.os }}-${{ matrix.rid }}
|
|
path: |
|
|
**/TestResults/**
|
|
**/*-report.html
|
|
|
|
coverage:
|
|
name: coverage
|
|
needs: [discover, tests]
|
|
runs-on: ubuntu-latest
|
|
# always(): the coverage of a run whose tests failed is still worth
|
|
# reporting.
|
|
if: ${{ always() }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup .NET
|
|
uses: actions/setup-dotnet@v6
|
|
with:
|
|
dotnet-version: '10.0.401'
|
|
|
|
- name: Download test results
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
pattern: dotnet-results-*
|
|
path: coverage-artifacts
|
|
|
|
- name: Detect coverage
|
|
id: probe
|
|
shell: pwsh
|
|
env:
|
|
TESTS_RESULT: ${{ needs.tests.result }}
|
|
run: |
|
|
$reports = @(Get-ChildItem -Path coverage-artifacts -Recurse -File -Filter *.cobertura.xml -ErrorAction SilentlyContinue)
|
|
Write-Host "Found $($reports.Count) Cobertura report(s)."
|
|
"has_reports=$(($reports.Count -gt 0).ToString().ToLowerInvariant())" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
if ($reports.Count -gt 0) {
|
|
exit 0
|
|
}
|
|
|
|
# Whether "no coverage" is expected depends on whether the matrix ran. A
|
|
# matrix that completed and published nothing means the collector is
|
|
# broken, and reporting green would hide that indefinitely.
|
|
if ($env:TESTS_RESULT -eq 'success') {
|
|
Write-Host '::error title=Coverage::The test matrix completed but published no coverage at all; the collector is not working.'
|
|
exit 1
|
|
}
|
|
Write-Host "::warning title=Coverage::The test matrix did not complete (result: $($env:TESTS_RESULT)), so there is no coverage to evaluate."
|
|
|
|
- name: Merge coverage report
|
|
if: ${{ steps.probe.outputs.has_reports == 'true' }}
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
dotnet tool install --tool-path tools dotnet-reportgenerator-globaltool
|
|
./tools/reportgenerator `
|
|
'-reports:coverage-artifacts/**/*.cobertura.xml' `
|
|
'-targetdir:CodeCoverage' `
|
|
'-reporttypes:Cobertura;HtmlSummary' `
|
|
'-title:UA .Net Standard Full Test Coverage' `
|
|
'-assemblyfilters:-*.Tests'
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-Host "::error title=Coverage::ReportGenerator failed with exit code $LASTEXITCODE."
|
|
exit $LASTEXITCODE
|
|
}
|
|
|
|
- name: Upload merged coverage report
|
|
if: ${{ steps.probe.outputs.has_reports == 'true' }}
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
name: coverage-report
|
|
path: CodeCoverage
|
|
|
|
# Project floors only: there is no pull request to diff against, so
|
|
# check-coverage.ps1 skips its changed-lines gate.
|
|
- name: Evaluate coverage
|
|
if: ${{ steps.probe.outputs.has_reports == 'true' }}
|
|
shell: pwsh
|
|
run: |
|
|
./.azurepipelines/check-coverage.ps1 `
|
|
-CoberturaPath CodeCoverage/Cobertura.xml `
|
|
-ThresholdsPath coverage-thresholds.json `
|
|
-RepoRoot '${{ github.workspace }}' `
|
|
-SummaryPath coverage-summary.md
|
|
$outcome = $LASTEXITCODE
|
|
if (Test-Path coverage-summary.md) {
|
|
Get-Content coverage-summary.md | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append
|
|
}
|
|
if ($outcome -ne 0) {
|
|
Write-Host '::error title=Coverage::Coverage thresholds were not met; see the job summary for the numbers.'
|
|
exit 1
|
|
}
|
|
|
|
# Replays the full fuzz crash corpus that Azure DevOps used to supply as the
|
|
# secure file FuzzingArtifacts.zip. The corpus lives on the orphan branch
|
|
# 'fuzz-corpus' of this repository (see fuzzing/CrashCorpus.md) and takes too
|
|
# long to replay on every pull request, so it runs here. The commit is
|
|
# pinned: a push to the branch changes nothing until this SHA is updated in a
|
|
# reviewed pull request.
|
|
crash-corpus:
|
|
name: crash-corpus-${{ matrix.entry.name }}
|
|
needs: discover
|
|
runs-on: ${{ matrix.entry.runsOn }}
|
|
timeout-minutes: 90
|
|
env:
|
|
FUZZ_CORPUS_COMMIT: 843ba944a7b144a7ae6429151846d9e5ab28d29f
|
|
strategy:
|
|
fail-fast: false
|
|
max-parallel: 4
|
|
matrix:
|
|
entry: ${{ fromJSON(needs.discover.outputs.crash_corpus_tests) }}
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Check out the crash corpus
|
|
uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ env.FUZZ_CORPUS_COMMIT }}
|
|
path: .fuzz-crash-corpus
|
|
fetch-depth: 1
|
|
persist-credentials: false
|
|
|
|
- name: Overlay the crash corpus
|
|
shell: pwsh
|
|
run: |
|
|
$ErrorActionPreference = 'Stop'
|
|
$source = Join-Path $env:GITHUB_WORKSPACE '.fuzz-crash-corpus'
|
|
$actual = (git -C $source rev-parse HEAD).Trim()
|
|
if ($actual -ne $env:FUZZ_CORPUS_COMMIT) {
|
|
throw "The crash corpus is at $actual, expected $env:FUZZ_CORPUS_COMMIT."
|
|
}
|
|
|
|
# Each top-level folder overlays the fuzzing/ project of the same name,
|
|
# the location the Azure template extracted to, so the assets land where
|
|
# FuzzTargetTestsBase enumerates them.
|
|
$count = 0
|
|
foreach ($area in Get-ChildItem -LiteralPath $source -Directory | Where-Object Name -ne '.git') {
|
|
$target = Join-Path 'fuzzing' $area.Name
|
|
if (-not (Test-Path -LiteralPath $target)) {
|
|
throw "Corpus folder '$($area.Name)' has no matching fuzzing/ project."
|
|
}
|
|
Copy-Item -Path (Join-Path $area.FullName '*') -Destination $target -Recurse -Force
|
|
$count += @(Get-ChildItem -LiteralPath $area.FullName -Recurse -File).Count
|
|
}
|
|
if ($count -eq 0) {
|
|
throw 'The crash corpus is empty; a replay of nothing would report coverage that was never performed.'
|
|
}
|
|
Remove-Item -LiteralPath $source -Recurse -Force
|
|
Write-Host "Overlaid $count corpus files from commit $actual."
|
|
"Crash corpus: ``$actual`` ($count files)" | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Append
|
|
|
|
- uses: ./.github/actions/run-dotnet-tests
|
|
with:
|
|
projects: ${{ matrix.entry.projects }}
|
|
custom-test-target: ${{ matrix.entry.customTestTarget }}
|
|
framework: ${{ matrix.entry.framework }}
|
|
configuration: ${{ matrix.entry.configuration }}
|
|
dotnet: ${{ matrix.entry.dotnet }}
|
|
filter: ${{ matrix.entry.filter }}
|
|
hang-timeout: ${{ matrix.entry.hangTimeout }}
|
|
per-project-timeout: ${{ matrix.entry.perProjectTimeout }}
|
|
# Not dotnet-results-*: the coverage job merges those, and this replay
|
|
# measures inputs, not code coverage.
|
|
artifact-name: crash-corpus-results-${{ matrix.entry.id }}
|
|
|
|
nightly-summary:
|
|
# Deliberately NOT named 'build-and-test summary': that name belongs to the
|
|
# required pull-request check in buildandtest.yml, and two workflows
|
|
# reporting the same context would make a manual run able to satisfy - or
|
|
# break - branch protection.
|
|
name: nightly summary
|
|
runs-on: ubuntu-latest
|
|
if: ${{ always() }}
|
|
needs: [discover, build-solutions, tests, aot, coverage, crash-corpus]
|
|
steps:
|
|
- name: Evaluate job results
|
|
shell: pwsh
|
|
env:
|
|
DISCOVER_RESULT: ${{ needs.discover.result }}
|
|
BUILD_RESULT: ${{ needs.build-solutions.result }}
|
|
TEST_RESULT: ${{ needs.tests.result }}
|
|
AOT_RESULT: ${{ needs.aot.result }}
|
|
COVERAGE_RESULT: ${{ needs.coverage.result }}
|
|
CORPUS_RESULT: ${{ needs.crash-corpus.result }}
|
|
run: |
|
|
$results = [ordered]@{
|
|
'discover' = $env:DISCOVER_RESULT
|
|
'build-solutions' = $env:BUILD_RESULT
|
|
'tests' = $env:TEST_RESULT
|
|
'aot' = $env:AOT_RESULT
|
|
'coverage' = $env:COVERAGE_RESULT
|
|
'crash-corpus' = $env:CORPUS_RESULT
|
|
}
|
|
|
|
$bad = @()
|
|
foreach ($job in $results.GetEnumerator()) {
|
|
Write-Host "$($job.Key): $($job.Value)"
|
|
if (@('success', 'skipped') -notcontains $job.Value) {
|
|
$bad += "$($job.Key)=$($job.Value)"
|
|
}
|
|
}
|
|
|
|
# The crash-corpus replay is part of the full scope and its matrix is
|
|
# never empty, so unlike the other jobs it may not be skipped.
|
|
if ($env:CORPUS_RESULT -eq 'skipped') {
|
|
$bad += 'crash-corpus=skipped'
|
|
}
|
|
|
|
if ($bad.Count -gt 0) {
|
|
Write-Host "::error::Nightly jobs did not succeed: $($bad -join ', ')"
|
|
exit 1
|
|
}
|
|
Write-Host 'All nightly jobs succeeded or were intentionally skipped.'
|