Skip to content

docs: split the README into topic pages and move the changelog out #52

docs: split the README into topic pages and move the changelog out

docs: split the README into topic pages and move the changelog out #52

Workflow file for this run

# Build and test on every push to main and every PR.
#
# Split into two jobs on purpose: the unit suite and the integration suite, the latter needing
# Docker for its PostgreSQL container.
#
# Actions are pinned to commit SHAs, not tags. A tag can be moved to a different commit — that is
# how the tj-actions/changed-files compromise (March 2025) reached every workflow that trusted
# `@v45` — a SHA cannot. The trailing `# vX.Y.Z` is what Dependabot reads to propose an update,
# so keep it next to the SHA (see .github/dependabot.yml).
#
# For information on GitHub Actions with .NET, see:
# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: .NET
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
workflow_dispatch:
permissions:
contents: read
defaults:
run:
shell: bash
# A new push to a PR makes the in-flight run pointless; main is never cancelled.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
DOTNET_NOLOGO: true
DOTNET_CLI_TELEMETRY_OPTOUT: true
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
jobs:
test:
name: Test (${{ matrix.os }})
runs-on: ${{ matrix.os }}
# Linux only. The matrix is kept as a single entry rather than flattened to a plain `runs-on`
# so the job keeps reporting as `Test (ubuntu-latest)` — that exact string is a required check
# in the branch protection rule on main, and a rename would leave it required and never
# reported, hanging PRs instead of failing them. Re-adding an OS is a one-line change here.
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest ]
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Setup .NET
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
dotnet-version: 10.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release --no-restore
# This used to fan out across ubuntu/windows/macos for the repository-convention tests, which
# do real path work. Dropped as unearned: no shipped code touches the filesystem, so the only
# thing the other runners proved was that the *test harness* composes paths portably — which
# it does via Path.Combine, and which fails loudly on the machine of whoever hits it. Fix that
# reactively if a Windows contributor ever appears.
- name: Unit tests
run: >
dotnet test -c Release --no-build
--filter "TestCategory!=Integration"
--logger "trx;LogFileName=unit-${{ matrix.os }}.trx"
--results-directory TestResults
- name: Upload test results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: test-results-${{ matrix.os }}
path: TestResults/*.trx
if-no-files-found: ignore
integration:
name: Integration (PostgreSQL 18)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Setup .NET
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
dotnet-version: 10.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release --no-restore
# CI=true turns an unavailable container into a failure instead of an inconclusive skip.
# Without it a broken Docker setup would retire the end-to-end layer and still report green.
- name: Integration tests
env:
CI: true
run: >
dotnet test -c Release --no-build
--filter "TestCategory=Integration"
--logger "trx;LogFileName=integration.trx"
--results-directory TestResults
- name: Upload test results
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: always()
with:
name: test-results-integration
path: TestResults/*.trx
if-no-files-found: ignore
# The only job that exercises the delivery chain rather than the code: NuGet restore, the packaged
# .targets injecting the design-time attribute, EF's host discovering it, and a real
# `dotnet ef migrations add`. Deliberately independent of the other jobs so it reports in parallel.
#
# No database is involved — scaffolding a migration never connects.
consumer:
name: Consumer smoke test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Setup .NET
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
dotnet-version: 10.0.x
- name: Scaffold a migration from a throwaway consumer project
run: ./test/consumer-smoke-test.sh
pack:
name: Pack
runs-on: ubuntu-latest
needs: [ test, integration ]
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
- name: Setup .NET
uses: actions/setup-dotnet@26b0ec14cb23fa6904739307f278c14f94c95bf1 # v5.4.0
with:
dotnet-version: 10.0.x
# Packing is itself a check: a package that declares PackageReadmeFile without packing the
# file fails here with NU5019, and satellites that lose their .targets ship silently broken.
- name: Pack
run: dotnet pack -c Release -o dist
- name: List package contents
run: |
for package in dist/*.nupkg; do
echo "=== $(basename "$package")"
unzip -l "$package" | awk '{ print " " $NF }' | grep -E 'README|targets|\.dll$' || true
done
# The smoke test's *other* invocation mode. The `consumer` job runs it with no argument, where
# it packs its own feed; here it is handed a pre-built one, exactly as the release workflow
# does. The two are not interchangeable — packing pre-populates NUGET_PACKAGES with the
# solution's dependencies, and a restore that only works because of that side effect passes
# one way and fails the other. That difference broke a release, because until now nothing
# exercised this mode before release day.
- name: Consumer smoke test against the packed feed
run: ./test/consumer-smoke-test.sh dist
# Generating here too means a broken SBOM step surfaces on a PR rather than on release day.
- name: Generate SBOMs
run: |
dotnet tool restore
version="$(dotnet msbuild src/EFCore.ComplexIndexes/EFCore.ComplexIndexes.csproj -getProperty:Version)"
for directory in src/*/; do
id="$(basename "$directory")"
dotnet cyclonedx "$directory$id.csproj" \
--output dist --filename "$id.$version.cdx.json" --output-format Json \
--set-type Library --set-nuget-purl --set-name "$id" --set-version "$version" \
--include-project-references --exclude-filter Microsoft.EntityFrameworkCore.Design
done
- name: Upload packages
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: nupkg
path: |
dist/*.nupkg
dist/*.snupkg
dist/*.cdx.json