From 8d07e876f9baf50f8103fac4d553f12fa4734bd4 Mon Sep 17 00:00:00 2001 From: Kieron Lanning Date: Wed, 30 Sep 2026 22:39:42 +0100 Subject: [PATCH 1/2] feat(consumer): enforce the .NET 11 Windows consumer contract Every package is a .NET 11 Windows-only package, but nothing documented or enforced that for consumers, so a mismatch surfaced as NU1202/CS0246 confusion or a silent runtime failure. - ship buildTransitive defaults (WindowsSdkPackageVersion, PlatformTarget) and the PWC0001/PWC0002 guards in the core package, and declare them in RequiredContent - add docs/wiki/Consumer-Requirements.md and update the root and package READMEs - add scripts/verify-consumers.ps1 and the just verify-consumers recipe (12 cases) - add ConsumerRequirementsTests guarding the published target framework - fix the stale WSL version references (2.9.3 -> 3.0.1.0) and mark the project experimental in the README, the wiki home page and every package README --- .github/copilot-instructions.md | 4 + AGENTS.md | 35 +- Justfile | 10 + README.md | 38 +- docs/wiki/Consumer-Requirements.md | 234 ++++++++++++ docs/wiki/Contributing-Modules.md | 1 + docs/wiki/Contributing.md | 14 +- docs/wiki/Getting-Started.md | 16 +- docs/wiki/Home.md | 22 +- docs/wiki/Packaging.md | 10 + docs/wiki/Release-Flow.md | 11 + docs/wiki/Testing.md | 24 ++ docs/wiki/_Sidebar.md | 1 + docs/wiki/index.md | 2 + purview-build.json | 4 +- scripts/verify-consumers.ps1 | 355 ++++++++++++++++++ src/src/Azurite/Sdk/README.md | 12 +- src/src/MsSql/Sdk/README.md | 12 +- src/src/MySql/Sdk/README.md | 10 + src/src/Nats/Sdk/README.md | 10 + src/src/PostgreSql/Sdk/README.md | 10 + src/src/RabbitMq/Sdk/README.md | 10 + src/src/Redis/Sdk/README.md | 10 + src/src/WslContainers/Sdk/README.md | 16 +- .../Purview.WslContainers.props | 21 ++ .../Purview.WslContainers.targets | 73 ++++ .../ConsumerRequirementsTests.cs | 45 +++ 27 files changed, 982 insertions(+), 28 deletions(-) create mode 100644 docs/wiki/Consumer-Requirements.md create mode 100644 scripts/verify-consumers.ps1 create mode 100644 src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.props create mode 100644 src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.targets create mode 100644 src/tests/WslContainers.UnitTests/ConsumerRequirementsTests.cs diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index ea2e258..35aa381 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -20,6 +20,10 @@ Keep product, architecture, and general engineering standards centralized in `AG - Treat work as incomplete until the relevant tests pass; unit tests need no WSLC host, integration tests do. - Never weaken the WSLC session/store invariants (single shared session, serialised session mutations, the shared-store fallback, `Secret` redaction) to make a test pass. +- Treat the published consumer contract as an invariant too: `.NET 11` + a Windows target framework, + the `buildTransitive` defaults, and the `PWC0001`/`PWC0002` guards documented in + `docs/wiki/Consumer-Requirements.md`. `just verify-consumers` must pass before a consumer-facing change + is complete. - Consult the repository `.agents/` folder for additional skills/workflows that may improve execution quality. Skill content is delivered by NuGet packages and is read-only here. - Keep edits minimal, focused, and aligned with existing SDK and repository conventions. diff --git a/AGENTS.md b/AGENTS.md index da4a905..c3403d5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ installation, plus the service modules (`PostgreSql`, `Redis`, `MsSql`, `RabbitM | `src/WSLTestContainers.slnx` | Canonical solution for restore, build, test and pack | | `src/src/WslContainers` | Core runtime (`Purview.WslContainers`): `ContainerBuilder`, `WslContainer`, runtime, sessions, images, networking, mounts, wait strategies, diagnostics | | `src/src/` | Service modules; each is a thin layer over the core and carries a bespoke `Sdk/README.md` | -| `src/src//Sdk` | Package-only assets. `Sdk/README.md` is packed as the package README (suppressing the repo-root README); `Sdk/buildTransitive/**` would ship MSBuild assets | +| `src/src//Sdk` | Package-only assets. `Sdk/README.md` is packed as the package README (suppressing the repo-root README); `Sdk/buildTransitive/**` ships MSBuild assets to consumers (the core package's consumer defaults and guards) | | `src/tests` | TUnit unit (`*.UnitTests`) and WSLC integration (`*.IntegrationTests`) projects | | `spikes/WslcSpikes` | Phase 0 investigation harness (`s1`..`s14` probes); not part of the test run | | `docs/wiki` | User-facing documentation wiki, aggregated by the purview-dev website | @@ -62,6 +62,23 @@ installation, plus the service modules (`PostgreSql`, `Redis`, `MsSql`, `RabbitM session so its name is released. - **Secrets use `Secret`** and must never reach logs, names, `ToString()` or diagnostics (they are redacted). +## Consumer requirements and compatibility + +- The packages are **.NET 11, Windows-only**: every project under `src/` targets + `net11.0-windows10.0.19041.0` (`src/Directory.Build.props`) and a consumer must match. The contract, + the failures that enforce it and the CI workarounds are documented in + [Consumer Requirements](docs/wiki/Consumer-Requirements.md); update that page whenever the target + framework, the `buildTransitive` defaults or the `PWC0001`/`PWC0002` guards change. +- `Purview.WslContainers` ships `Sdk/buildTransitive/Purview.WslContainers.{props,targets}` so consumers + inherit `WindowsSdkPackageVersion`/`PlatformTarget` defaults and a clear error for an unsupported + target framework (`PWC0001`) or a 32-bit consumer (`PWC0002`). Those assets are framework-agnostic, so + NuGet no longer raises `NU1202` at restore time — the guards are the fail-fast path. Keep them, and + keep the `RequiredContent` entries that declare them. +- `src/Directory.Build.props` sets `EnableWindowsTargeting=true` because the shared CI agent is + `ubuntu-latest`; removing it fails the pipeline with `NETSDK1100`. +- The project is **experimental**: keep the experimental notice in `README.md`, `docs/wiki/Home.md` and + the package READMEs, and keep versions on a `-prerelease.N` suffix. + ## Module rules - A module supplies only defaults: image, ports, environment, module configuration (`WithXxx`), a readiness @@ -79,7 +96,9 @@ installation, plus the service modules (`PostgreSql`, `Redis`, `MsSql`, `RabbitM resolves `IsPackable` by scanning the project file, and the package metadata/icon conditions in `src/Directory.Build.props` depend on it. - Each package ships `lib/$(TFM)/.{dll,xml}`, `README.md` (from `Sdk/README.md`) and - `purview-logo-light.png`. PDBs ship only in the `.snupkg`. + `purview-logo-light.png`. PDBs ship only in the `.snupkg`. The core package additionally ships + `buildTransitive/Purview.WslContainers.{props,targets}` (see + [Consumer requirements and compatibility](#consumer-requirements-and-compatibility)). - `PackValidation.RequireExplicitContent` defaults to `true`, so `purview-build.json`'s `RequiredContent` is the **exhaustive** manifest: a produced package with no rule, or a packed entry matched by no glob, fails validation. Adding or removing packaged content means updating that map. @@ -94,6 +113,12 @@ installation, plus the service modules (`PostgreSql`, `Redis`, `MsSql`, `RabbitM exclusively locks its image-store VHD, so parallel modules fail with `0x80070020`. - Use the shared `WslcTest` helper in `src/tests/SharedTestingFramework` for integration skip/availability checks. Unit tests may use the modules' `BuildConfigurationForTesting()` internal hook. +- `WslContainers.UnitTests/ConsumerRequirementsTests.cs` guards the published target framework + (`.NETCoreApp,Version=v11.0` plus `Windows10.0.19041.0`); keep it in step with + [Consumer Requirements](docs/wiki/Consumer-Requirements.md). +- `just verify-consumers` packs and then builds throwaway consumer projects to assert the documented + guard errors and workarounds. It restores from nuget.org, so it stays out of the `[Category=Unit]` + filter and is a local/explicit step. ## Local commands @@ -102,6 +127,7 @@ just build # dotnet build (Debug) just test '/*/*/*/*[Category=Unit]' # unit tests only just lint-check / just lint-fix # CSharpier check / format just pack # build + dotnet pack into ./artifacts +just verify-consumers # build throwaway consumers against the packed packages just pipeline-pack-validate # restore, build, lint, test, pack, validate just scrub # reset bin/obj, clean, forced restore, build-server shutdown ``` @@ -117,7 +143,8 @@ Commit messages follow Conventional Commits enforced by the `commit-msg` lefthoo - `.github/workflows/release.yml` runs the shared release pipeline with `release-mode: NuGet` on a push to `main`. - Both workflows pin `dotnet-version` to `global.json`'s `sdk.version`; keep them in sync, and keep - `purview-build.json` pointing at `src/WSLTestContainers.slnx`. + `purview-build.json` pointing at `src/WSLTestContainers.slnx`. The shared workflow runs on + `ubuntu-latest`, which is why `EnableWindowsTargeting=true` must stay in `src/Directory.Build.props`. ## Completion checklist @@ -127,6 +154,8 @@ Before handing work back: - Review public API, package-content and dependency-direction implications. - Update the affected package `Sdk/README.md`, the root `README.md`, `docs/wiki` (plus `_Sidebar.md` and `mkdocs.yml` for new pages), `AGENTS.md` and `purview-build.json` when the change affects them. + `docs/wiki/Consumer-Requirements.md` is the contract every consumer-facing change has to keep + accurate, and `just verify-consumers` is the check that proves it. - Watch for the packaging traps: a new packable project missing `true` or a `RequiredContent` entry, and a new `Sdk/README.md` that does not describe its own package. - Run the appropriate build, test, formatting and pack checks in proportion to risk. diff --git a/Justfile b/Justfile index 0486d93..d222b55 100644 --- a/Justfile +++ b/Justfile @@ -111,6 +111,16 @@ pack *args: echo "Packing {{ BLUE }}{{ solution_file }}{{ NORMAL }} with {{ YELLOW }}{{ build_configuration }}{{ NORMAL }}..." dotnet pack "{{ solution_file }}" --configuration "{{ build_configuration }}" --no-restore --output "{{ artifact_folder }}" {{ args }} +# Verifies the documented consumer requirements and workarounds (docs/wiki/Consumer-Requirements.md) +# by packing and then building throwaway consumer projects against the produced packages: the +# "just reference the package from a .NET 11 Windows project" path, the shipped buildTransitive +# defaults, the guard errors for unsupported target frameworks, and the non-.NET-11 escape hatch +# that deliberately does not work. Slower than unit tests (packs and restores from nuget.org). +[group('Build and Test')] +verify-consumers *args: + just pack + pwsh -NoProfile -File scripts/verify-consumers.ps1 {{ args }} + # ----------------------------------------------------------------------------- # Formatting # ----------------------------------------------------------------------------- diff --git a/README.md b/README.md index 38a2862..37d9f24 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,39 @@ # Purview.WslContainers +[![NuGet version](https://img.shields.io/nuget/v/Purview.WslContainers.svg)](https://www.nuget.org/packages/Purview.WslContainers) +[![Release](https://github.com/purview-dev/wslc-testcontainers/actions/workflows/release.yml/badge.svg)](https://github.com/purview-dev/wslc-testcontainers/actions/workflows/release.yml) + A **WSLC-native** Testcontainers-style library for .NET that runs throwaway Linux containers for integration testing on **Microsoft WSL Containers (WSLC)** — with no Docker installation. Built directly against the `Microsoft.WSL.Containers` NuGet package (the WSLC managed C# API). No `wslc.exe`/`wsl.exe`/`docker` CLI, no Docker.DotNet, no Testcontainers internally. +> **Experimental.** This project is an experiment in running throwaway containers through Microsoft +> WSL Containers. The public API, defaults and packaging rules can change between prereleases, and +> there is no production support guarantee. Pin the exact package version you build against, and read +> [Consumer Requirements](docs/wiki/Consumer-Requirements.md) before adopting it. + > **Status: Phase 8 in progress.** Core runtime, wait strategies, the `Image`/`Tag` parser, registry auth, > observability, hardening, and **seven service modules** (PostgreSQL, Redis, SQL Server, RabbitMQ, Azurite, > NATS, MySQL). **Images are shared by default** (`StorageMode.Shared`): sessions reuse a stable > image store (`%LOCALAPPDATA%\Purview\WslContainers\images`) so images are pulled once, not per session; -> `StorageMode.PerSession` provides isolation. 69+ unit tests pass across all modules. +> `StorageMode.PerSession` provides isolation. 76 unit tests pass across all modules. ## Prerequisites -- Windows 10/11 -- **WSL ≥ 3.0.1.0** with WSL Containers, installed via `wsl --install --no-distribution` -- .NET SDK 11 (the repo pins `11.0.100-rc.1`) +- Windows 10/11. +- **WSL Containers**, installed via `wsl --install --no-distribution` (verified against WSL 3.0.1.0). +- .NET SDK 11 (the repo pins `11.0.100-rc.1`). +- A **consuming project must be a .NET 11 project that targets Windows specifically** — + `net11.0-windows10.0.19041.0`, x64 or arm64. The packages ship MSBuild defaults for the supporting + settings; the full contract, the exact errors raised when it is not met, and the + `EnableWindowsTargeting` workaround for non-Windows CI agents are documented in + [Consumer Requirements](docs/wiki/Consumer-Requirements.md). Verify: ```powershell -wsl --version # needs 3.0.1.0+ -wslc version # needs 3.0.1.0+ +wsl --version # WSL Containers installed (verified against 3.0.1.0) +wslc version # e.g. 3.0.1.0 ``` The library reports missing prerequisites via `WslContainerRuntime.GetInfoAsync()`; it never installs or updates WSL on its own. @@ -129,6 +142,7 @@ The project documentation lives in [`docs/wiki`](docs/wiki/Home.md) and is publi (`mkdocs.yml`, `docs_dir: docs/wiki`, aggregated by the purview-dev website): - [Getting Started](docs/wiki/Getting-Started.md) — prerequisites, first container, first module. +- [Consumer Requirements](docs/wiki/Consumer-Requirements.md) — the .NET 11 + Windows target framework contract, the `PWC0001`/`PWC0002` guards, and the CI workarounds. - [Architecture](docs/wiki/Architecture.md) — the shared session model, concurrency and cleanup decisions. - [Lifecycle](docs/wiki/Lifecycle.md), [Networking](docs/wiki/Networking.md), [Wait Strategies](docs/wiki/Wait-Strategies.md). - [Modules](docs/wiki/Modules.md) — the module contract and every shipped module. @@ -222,6 +236,18 @@ just test # dotnet test, one test module at a time > The `WslContainers.IntegrationTests` module runs 27 real containers in one session and takes ~4 > minutes because WSLC serialises container operations; expect slow-test warnings while it runs. +### Verifying the consumer contract + +```powershell +just verify-consumers # pack, then build 12 throwaway consumer projects against ./artifacts +just verify-consumers -Keep # same, keeping the generated projects for inspection +``` + +`just verify-consumers` asserts every claim in [Consumer Requirements](docs/wiki/Consumer-Requirements.md): +the happy path, the shipped `buildTransitive` defaults, the `PWC0001`/`PWC0002` guards, and the +non-.NET-11 escape hatch that deliberately does not work. It needs network access and is therefore a +local step rather than part of the `[Category=Unit]` pipeline filter. + ## Running the Phase 0 spikes ```powershell diff --git a/docs/wiki/Consumer-Requirements.md b/docs/wiki/Consumer-Requirements.md new file mode 100644 index 0000000..a6cc670 --- /dev/null +++ b/docs/wiki/Consumer-Requirements.md @@ -0,0 +1,234 @@ +# Consumer Requirements + +> **Experimental.** `Purview.WslContainers.*` is an experimental project: the public API, the +> defaults and these requirements can change between prereleases, and there is no production +> support guarantee. Treat every version as a preview and pin the exact package version you build +> against. + +Every package targets `net11.0-windows10.0.19041.0` and is built on the +`Microsoft.WSL.Containers` WinRT projection, so a consuming project **must be a .NET 11 (or later) +project that targets Windows specifically**. This page is the authoritative statement of that +contract, of the workarounds that exist for it, and of how each of them is verified. + +## Copy this into your project + +```xml + + net11.0-windows10.0.19041.0 + x64 + 10.0.26100.80 + +``` + +The last two lines are optional for most projects: the packages ship MSBuild defaults that supply +them (see [What the packages do for you](#what-the-packages-do-for-you)). They are shown here +because being explicit makes the requirements visible to the next person who reads your project +file, and because the defaults only fill in a value when you have not chosen one. + +## The requirements in detail + +| # | Requirement | Why it exists | +| --- | --- | --- | +| 1 | **.NET 11 or later** | Every `lib/` asset in every package is built for `net11.0-windows10.0.19041.0`. | +| 2 | **A Windows-specific target framework that names the OS version** (`net11.0-windows10.0.19041.0` or later) | The `Microsoft.WSL.Containers` projection only ships Windows assets. `net11.0-windows` on its own is not enough. | +| 3 | **64-bit** (`PlatformTarget` `x64`/`arm64`, or a matching `RuntimeIdentifier`) | The native `wslcsdk.dll` ships for `win-x64` and `win-arm64` only. | +| 4 | **`WindowsSdkPackageVersion` at least `10.0.26100.80`** | The projection is compiled against `Microsoft.Windows.SDK.NET` `10.0.26100.79`; the pack the SDK resolves for a `10.0.19041.0` target framework is older. | +| 5 | **A Windows 10/11 host with WSL Containers** to actually run containers | The library drives WSLC; it never installs or updates WSL for you. | + +### 1. .NET 11 or later + +The repository, the packages and the tests all target .NET 11 (`global.json` pins +`11.0.100-rc.1.26425.128`). A `net10.0-windows…` or `net8.0-windows…` project cannot consume the +packages; see [Non-.NET-11 Windows projects](#workaround-consuming-from-a-non-net-11-windows-project). + +### 2. A Windows-specific target framework + +```xml +net11.0-windows10.0.19041.0 +``` + +```xml +net11.0-windows +net11.0 +``` + +`net11.0-windows` resolves its platform version to `7.0`, which is older than the `10.0.19041.0` +the packages were built against, so NuGet selects no compile assets for it. Always spell out the +version. (The `Microsoft.WSL.Containers` package itself is `net8.0-windows10.0.19041.0`, which a +`net11.0-windows10.0.19041.0` project consumes without issue.) + +### 3. 64-bit consumers only + +The native WSL Containers SDK is shipped for `win-x64` and `win-arm64` only. A 32-bit (`x86`) +consumer builds but cannot load `wslcsdk.dll` at runtime, so the packages fail the build instead: + +```text +error PWC0002: Purview.WslContainers requires a 64-bit (x64 or arm64) consumer ... +``` + +### 4. Windows SDK targeting pack version + +`Microsoft.WSL.Containers` 3.0.1's projection references `Microsoft.Windows.SDK.NET` +`10.0.26100.79`. Targeting `net11.0-windows10.0.19041.0` resolves a lower pack +(`10.0.19041.x`) by default and the compiler rejects the mismatch: + +```text +error CS1705: Assembly 'wslcsdkcs' ... uses 'Microsoft.Windows.SDK.NET' which has a higher +version than referenced assembly 'Microsoft.Windows.SDK.NET' +``` + +Pin `10.0.26100.80` (the nearest published version) as shown above. The packages set this default +for you, so you only need it if you want to override the value deliberately. + +### 5. Host prerequisites + +The build requirements above are host-independent. Running containers needs a Windows 10/11 host +with WSL Containers installed (`wsl --install --no-distribution`) — see +[Getting Started](Getting-Started.md). + +## What the packages do for you + +`Purview.WslContainers` ships two `buildTransitive` MSBuild files. NuGet imports them for **direct +references and transitive references**, so every module package +(`Purview.WslContainers.PostgreSql`, `Redis`, `MsSql`, `RabbitMq`, `Azurite`, `Nats`, `MySql`) gets +them too through its dependency on the core package. + +| Package path | Effect | +| --- | --- | +| `buildTransitive/Purview.WslContainers.props` | Defaults `WindowsSdkPackageVersion` to `10.0.26100.80` when the consumer has not set it. | +| `buildTransitive/Purview.WslContainers.targets` | Defaults `PlatformTarget` to `x64` when it is unset (or `AnyCPU`) and no `RuntimeIdentifier` is selected, and fails the build with `PWC0001`/`PWC0002` when the target framework or the platform cannot be supported. | + +A consumer therefore only has to choose a target framework: + +```xml + + + net11.0-windows10.0.19041.0 + + + + + +``` + +An explicit `PlatformTarget`, `RuntimeIdentifier` or `WindowsSdkPackageVersion` in the consumer +always wins over these defaults. + +> Because `buildTransitive` assets are framework-agnostic, NuGet no longer reports `NU1202` for an +> incompatible target framework: restore succeeds and the failure comes from the guard targets +> instead. That is deliberate — `PWC0001` names the required target framework, whereas an empty +> compile-asset set only produces `CS0246` errors in your own code. + +## Error reference + +| Error | Raised by | Meaning | Fix | +| --- | --- | --- | --- | +| `PWC0001` | the shipped guard target | The consumer's target framework is not .NET 11+ targeting Windows 10.0.19041.0+ | Retarget as above, or make the reference conditional when multi-targeting. | +| `PWC0002` | the shipped guard target | The consumer is not 64-bit | Remove your `PlatformTarget`, set it to `x64`/`arm64`, or choose a matching `RuntimeIdentifier`. | +| `CS1705` | the C# compiler | `WindowsSdkPackageVersion` is older than the projection requires | Set `WindowsSdkPackageVersion` to `10.0.26100.80` or later. | +| `CS8012` | the C# compiler | A referenced assembly targets a different processor (seen when a consumer forces `x86`) | Use a 64-bit consumer. | +| `NETSDK1100` | the .NET SDK | A Windows-targeted project is being built on a non-Windows operating system | Set `EnableWindowsTargeting` (see below). | +| `CS0234`/`CS0246` for `Microsoft.WSL`/`Purview` types | the C# compiler | The package contributed no compile assets (an unsupported target framework, or an unverified escape hatch) | Fix the target framework; `PWC0001` explains the same problem with a clearer message. | + +## Workaround: building on a non-Windows CI agent + +`net11.0-windows…` projects can be restored, compiled and unit-tested on Linux or macOS, provided +the build opts in: + +```xml + + true + +``` + +Without it the SDK fails with `NETSDK1100` (*"To build a project targeting Windows on this operating +system, set the EnableWindowsTargeting property to true"*). + +This is exactly how this repository's own CI works: the shared `purview-dev/build` workflow runs on +**`ubuntu-latest`**, so `src/Directory.Build.props` sets `EnableWindowsTargeting=true` and the +pipeline is filtered to `[Category=Unit]`. See [Testing](Testing.md). + +What it does and does not do: + +- ✅ restores the Windows targeting packs and compiles `net*-windows` assemblies; +- ✅ runs unit tests that never touch the WSLC runtime; +- ❌ does not provide WSL Containers — the WSLC integration suites need a Windows host; +- ❌ does not make `wslcsdk.dll` loadable; anything that opens a session must run on Windows. + +## Workaround: consuming from a non-.NET-11 Windows project + +**There is none.** A project that targets Windows but not .NET 11 (for example +`net8.0-windows10.0.19041.0`) cannot use these packages, and the repository verifies that no +escape hatch exists. + +The historical suggestion is `AssetTargetFallback`, which tells NuGet to consider an additional +target framework for the project's package references: + +```xml + + net8.0-windows10.0.19041.0 + net11.0-windows10.0.19041.0 + +``` + +It does **not** work here. `AssetTargetFallback` is not applied to `netcoreapp`-family packages, so +the package still contributes no compile assets and the build fails in your own code with +`CS0234`/`CS0246`. `PWC0001` fires as well. + +Even if it did compile, it would not help: the `lib/` assemblies are .NET 11 assemblies, so they can +only be loaded by a .NET 11 runtime. A consumer would have to move to .NET 11 to run them anyway. + +If you need this library from a project you cannot retarget, keep the container work in a small +**.NET 11 Windows test project** (which can reference the older project) rather than trying to +consume the packages from the older project. + +## Multi-targeting + +Only the Windows inner build may reference the packages, so make the reference conditional: + +```xml + + net11.0;net11.0-windows10.0.19041.0 + + + + +``` + +An unconditional reference fails the whole build: the `net11.0` inner build reports `PWC0001`. +Keep any code that uses the library behind the same condition — +`#if WINDOWS` (defined by the SDK for Windows target frameworks) or a conditional `Compile` item — +so the non-Windows inner build can still compile. + +## Verifying these requirements + +`just verify-consumers` packs the solution and builds twelve throwaway consumer projects against the +produced packages, asserting every claim on this page: + +| Case | Consumer | Expected outcome | +| --- | --- | --- | +| 01 | `.NET 11` + Windows with the documented settings | builds; `wslcsdk.dll` copied to the output | +| 02 | …with a stale `WindowsSdkPackageVersion` | `CS1705` | +| 03 | …with `PlatformTarget=x86` | `PWC0002` | +| 04 | …with no settings at all | builds via the shipped `buildTransitive` defaults | +| 05 | a module package with no settings | builds (the defaults are transitive) | +| 06 | `net8.0-windows` + `AssetTargetFallback` | `PWC0001` — the escape hatch does not work | +| 07 | `net8.0-windows` | `PWC0001` | +| 08 | plain `net11.0` | `PWC0001` | +| 09 | …with `PlatformTarget=AnyCPU` | builds (corrected to `x64`) | +| 10 | the `net11.0-windows` shorthand (no OS version) | `PWC0001` | +| 11 | multi-targeting with a conditional `PackageReference` | builds | +| 12 | multi-targeting with an unconditional `PackageReference` | `PWC0001` | + +The script is `scripts/verify-consumers.ps1` and it only writes to the temp folder. It needs network +access (it restores transitive dependencies from nuget.org), so it is a local/CI-explicit step +rather than part of the `[Category=Unit]` filter. + +## Related + +- [Getting Started](Getting-Started.md) — prerequisites and the first container. +- [Packaging](Packaging.md) — what each package contains, including the `buildTransitive` assets. +- [Testing](Testing.md) — the Linux CI run, the unit filter and the serial WSLC rule. +- [Modules](Modules.md) — the service modules that inherit these defaults. + + diff --git a/docs/wiki/Contributing-Modules.md b/docs/wiki/Contributing-Modules.md index fbf77a3..5945bdd 100644 --- a/docs/wiki/Contributing-Modules.md +++ b/docs/wiki/Contributing-Modules.md @@ -74,4 +74,5 @@ public class MyServiceBuilder : ContainerBuilder/Sdk/README.md`** — the package's own README, shipped inside the `.nupkg`. Update it whenever a module's public API, defaults, readiness or endpoints change. - **`docs/wiki`** — the user-facing wiki aggregated by the purview-dev website. Update the topic page - ([Architecture](Architecture.md), [Lifecycle](Lifecycle.md), [Networking](Networking.md), - [Wait Strategies](Wait-Strategies.md), [Modules](Modules.md), [Testing](Testing.md), - [Packaging](Packaging.md), [Release Flow](Release-Flow.md)) and `_Sidebar.md` when adding a page. + ([Consumer Requirements](Consumer-Requirements.md), [Architecture](Architecture.md), + [Lifecycle](Lifecycle.md), [Networking](Networking.md), [Wait Strategies](Wait-Strategies.md), + [Modules](Modules.md), [Testing](Testing.md), [Packaging](Packaging.md), [Release Flow](Release-Flow.md)) + and `_Sidebar.md` when adding a page. - **`purview-build.json`** — the exhaustive `PackValidation.RequiredContent` manifest has to keep matching what the packages actually contain; see [Packaging](Packaging.md). - **`README.md`** — the repository front page, when the shape of the project changes. diff --git a/docs/wiki/Getting-Started.md b/docs/wiki/Getting-Started.md index 6268106..ccabede 100644 --- a/docs/wiki/Getting-Started.md +++ b/docs/wiki/Getting-Started.md @@ -5,10 +5,18 @@ points you at the test workflow. ## Requirements -- Windows 10/11 with **WSL ≥ 2.9.3** including WSL Containers (`wsl --install --no-distribution`). -- .NET SDK 11 or later; the packages target `net11.0-windows10.0.19041.0` (x64). -- Verify the host with `wsl --version` (needs 2.9.3+) and `wslc version`. The library never installs or - updates WSL for you — call `WslContainerRuntime.GetInfoAsync()` to report what is missing. +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`), verified against WSL + 3.0.1.0. +- **A .NET 11 project targeting Windows specifically** — `net11.0-windows10.0.19041.0`, x64 or + arm64. The packages ship MSBuild defaults for `WindowsSdkPackageVersion` and `PlatformTarget`; + an unsupported target framework fails the build with `PWC0001` and a non-64-bit consumer with + `PWC0002`. The full contract, every error, and the `EnableWindowsTargeting` workaround for + non-Windows CI agents live in [Consumer Requirements](Consumer-Requirements.md). +- Verify the host with `wsl --version` and `wslc version`. The library never installs or updates WSL + for you — call `WslContainerRuntime.GetInfoAsync()` to report what is missing. + +> **Experimental.** The API, defaults and packaging rules can change between prereleases; there is no +> production support guarantee. ## 1. Reference a package diff --git a/docs/wiki/Home.md b/docs/wiki/Home.md index 21cf11d..a9cadae 100644 --- a/docs/wiki/Home.md +++ b/docs/wiki/Home.md @@ -8,9 +8,15 @@ It is built directly against the `Microsoft.WSL.Containers` managed package — This wiki is the project documentation hub. The packages are published under the `Purview.WslContainers.*` package IDs. +> **Experimental.** This project is an experiment in running throwaway containers through Microsoft +> WSL Containers. The public API, defaults and packaging rules can change between prereleases, and +> there is no production support guarantee. Pin the exact package version you build against and read +> [Consumer Requirements](Consumer-Requirements.md) before adopting it. + ## Start here - [Getting Started](Getting-Started.md) +- [Consumer Requirements](Consumer-Requirements.md) - [Architecture](Architecture.md) - [Lifecycle](Lifecycle.md) - [Networking](Networking.md) @@ -49,13 +55,19 @@ This wiki is the project documentation hub. The packages are published under the ## Requirements -- Windows 10/11. -- **WSL ≥ 2.9.3** with WSL Containers, installed via `wsl --install --no-distribution`. -- .NET SDK 11 (the repository pins `11.0.100-rc.1.26425.128`). +- Windows 10/11 with **WSL Containers**, installed via `wsl --install --no-distribution`. The library + is verified against WSL **3.0.1.0**; `wsl --version` and `wslc version` should both report 3.0.1.0 + or later. +- .NET SDK 11 to build (the repository pins `11.0.100-rc.1.26425.128` in `global.json`). +- A consuming project must be a **.NET 11 project targeting Windows specifically**: + `net11.0-windows10.0.19041.0`, built for x64 or arm64, with `WindowsSdkPackageVersion` + `10.0.26100.80` or later. See [Consumer Requirements](Consumer-Requirements.md) for the full + contract, the exact errors raised when it is not met, and the `EnableWindowsTargeting` workaround + for non-Windows CI agents. ```powershell -wsl --version # needs 2.9.3+ -wslc version # prints e.g. 3.0.1.0 +wsl --version # WSL Containers installed (verified against 3.0.1.0) +wslc version # e.g. 3.0.1.0 ``` The library reports missing prerequisites through `WslContainerRuntime.GetInfoAsync()`; it never installs or diff --git a/docs/wiki/Packaging.md b/docs/wiki/Packaging.md index fd44694..50de688 100644 --- a/docs/wiki/Packaging.md +++ b/docs/wiki/Packaging.md @@ -13,9 +13,14 @@ Each package ships exactly: | `lib/$(TFM)/Purview.WslContainers[.].xml` | XML documentation, generated because `GenerateDocumentationFile` is on for packable projects. | | `README.md` | The package's bespoke `Sdk/README.md` (see below). | | `purview-logo-light.png` | The shared Purview package icon (`assets/images/purview-logo-light.png`). | +| `buildTransitive/Purview.WslContainers.props` | **Core package only.** Defaults `WindowsSdkPackageVersion` for consumers. | +| `buildTransitive/Purview.WslContainers.targets` | **Core package only.** Defaults `PlatformTarget` to `x64` and raises `PWC0001`/`PWC0002` for unsupported consumers. | Portable PDBs are delivered through the `.snupkg`, never inside the `.nupkg`. +`$(TFM)` is `net11.0-windows10.0.19041.0`, so every package is a **.NET 11, Windows-only** package. +Consumers must target a matching framework; see [Consumer Requirements](Consumer-Requirements.md). + ## The `Sdk/` folder convention `Purview.BuildSdk` packs a packable project's `Sdk/` folder automatically (`PurviewAutoSdkPack`): @@ -62,6 +67,11 @@ alongside the `Sdk/README.md`. Removing content from a package means removing th 3. Add the package to `RequiredContent` in `purview-build.json`. 4. Prove it with `just pack` and `just pipeline-pack-validate`. +The two `Sdk/buildTransitive/` files belong to the **core** package only: a module inherits them +through its dependency on `Purview.WslContainers`. They are declared in `RequiredContent` like any +other asset, so a package that starts or stops shipping MSBuild assets has to update that manifest — +a produced package with no rule, or a packed entry matched by no glob, fails validation. + ## Related - [Release Flow](Release-Flow.md) — how packages are versioned and published. diff --git a/docs/wiki/Release-Flow.md b/docs/wiki/Release-Flow.md index 815d8fd..57ff8bb 100644 --- a/docs/wiki/Release-Flow.md +++ b/docs/wiki/Release-Flow.md @@ -9,6 +9,10 @@ applies that value to `Version` and `PackageVersion` for every project, so a rel bump — never a manual project-file edit. `package.json` also carries the repository, homepage and issue URLs that end up in each nuspec. +The project is **experimental**, so versions stay on a `-prerelease.N` suffix: consumers should pin an +exact version rather than float, and each bump can change the API or the +[consumer requirements](Consumer-Requirements.md). + ## Local commands The `Justfile` wraps the common steps: @@ -19,6 +23,7 @@ The `Justfile` wraps the common steps: | `just test` | `dotnet test` across the solution, one test module at a time (see [Testing](Testing.md)). | | `just lint-check` / `just lint-fix` | CSharpier check / format over the repository root. | | `just pack` | Build (Debug) and `dotnet pack` into `./artifacts`. | +| `just verify-consumers` | Pack, then build throwaway consumer projects that assert the published consumer contract ([Consumer Requirements](Consumer-Requirements.md)). | | `just scrub` | Delete `bin`/`obj`, clean, re-restore with `--force-evaluate`, and shut down the build server. | | `just pipeline-pack-validate` | Shared pipeline: restore, build, lint, test, pack and **validate** the packages, without publishing. | @@ -51,6 +56,12 @@ the run with the failing module's output. Both workflows pin `dotnet-version` to the SDK in `global.json` (`11.0.100-rc.1.26425.128`); keep them in sync when the SDK is bumped, and keep `purview-build.json` pointing at `src/WSLTestContainers.slnx`. +The shared workflow runs on **`ubuntu-latest`**, so the Linux agent builds these +`net11.0-windows10.0.19041.0` projects. That only works because `src/Directory.Build.props` sets +`EnableWindowsTargeting=true`; removing it fails the pipeline with `NETSDK1100`. The agent has no WSL +Containers, which is why the pipeline is filtered to `[Category=Unit]` — see +[Consumer Requirements](Consumer-Requirements.md) and [Testing](Testing.md). + ## Related - [Packaging](Packaging.md) — the package contents and the validation manifest. diff --git a/docs/wiki/Testing.md b/docs/wiki/Testing.md index fb585da..ad1588e 100644 --- a/docs/wiki/Testing.md +++ b/docs/wiki/Testing.md @@ -14,6 +14,12 @@ Test projects are discovered under `src/tests` and the SDK stamps every test ass `purview-build.json` filters the pipeline run to `/*/*/*/*[Category=Unit]`, so the shared pipeline never starts containers. Run integration projects explicitly when you have a WSLC host. +> The shared `purview-dev/build` workflow runs on **`ubuntu-latest`**, so the pipeline builds these +> `net11.0-windows…` projects on Linux. That works because `src/Directory.Build.props` sets +> `EnableWindowsTargeting=true`; without it the SDK reports `NETSDK1100`. See +> [Consumer Requirements](Consumer-Requirements.md) for what that workaround does and does not +> cover. + ```powershell just test # every discovered test project just test '/*/*/*/*[Category=Unit]' # unit tests only @@ -46,6 +52,24 @@ running the WSLC integration suites. - `spikes/WslcSpikes` is a manual investigation harness (`dotnet run --project spikes/WslcSpikes -- sfull`, or `s1`..`s14` for individual behaviour probes); it is not part of the test run. +## Verifying the consumer contract + +`WslContainers.UnitTests/ConsumerRequirementsTests.cs` guards the shape of the shipped library inside +the normal unit run: the assembly targets `.NETCoreApp,Version=v11.0`, targets `Windows10.0.19041.0` +and declares only that OS platform. If the target framework ever drifts, that test fails — and +[Consumer Requirements](Consumer-Requirements.md), the package READMEs and the shipped +`buildTransitive` defaults all have to move with it. + +The behavioural side is covered by `just verify-consumers`, which packs the packages and builds +throwaway consumer projects for every documented outcome (see +[Consumer Requirements](Consumer-Requirements.md#verifying-these-requirements)). It is deliberately +outside the `[Category=Unit]` filter because it packs and restores from nuget.org: + +```powershell +just verify-consumers # 12 consumer projects, all assertions +just verify-consumers -Keep # same, keeping the generated projects for inspection +``` + ## Related - [Architecture](Architecture.md) — session lifetime, the concurrency gate and the shared-store fallback. diff --git a/docs/wiki/_Sidebar.md b/docs/wiki/_Sidebar.md index d575768..e962982 100644 --- a/docs/wiki/_Sidebar.md +++ b/docs/wiki/_Sidebar.md @@ -1,5 +1,6 @@ - [Home](Home.md) - [Getting Started](Getting-Started.md) +- [Consumer Requirements](Consumer-Requirements.md) - [Architecture](Architecture.md) - [Lifecycle](Lifecycle.md) - [Networking](Networking.md) diff --git a/docs/wiki/index.md b/docs/wiki/index.md index f02968e..db80aa2 100644 --- a/docs/wiki/index.md +++ b/docs/wiki/index.md @@ -8,6 +8,8 @@ directly on **Microsoft WSL Containers**, with no Docker installation. ## Guides +- [Getting Started](Getting-Started.md) +- [Consumer requirements](Consumer-Requirements.md) - [Architecture](Architecture.md) - [Lifecycle](Lifecycle.md) - [Networking](Networking.md) diff --git a/purview-build.json b/purview-build.json index b5876a0..f1050a7 100644 --- a/purview-build.json +++ b/purview-build.json @@ -19,7 +19,9 @@ "lib/$(TFM)/Purview.WslContainers.dll", "lib/$(TFM)/Purview.WslContainers.xml", "README.md", - "purview-logo-light.png" + "purview-logo-light.png", + "buildTransitive/Purview.WslContainers.props", + "buildTransitive/Purview.WslContainers.targets" ], "purview.wslcontainers.azurite": [ "lib/$(TFM)/Purview.WslContainers.Azurite.dll", diff --git a/scripts/verify-consumers.ps1 b/scripts/verify-consumers.ps1 new file mode 100644 index 0000000..80f13e7 --- /dev/null +++ b/scripts/verify-consumers.ps1 @@ -0,0 +1,355 @@ +#Requires -Version 7.0 +<# +.SYNOPSIS + Verifies the consumer requirements and workarounds documented in + docs/wiki/Consumer-Requirements.md against the packages produced by `just pack`. + +.DESCRIPTION + Generates throwaway consumer projects in the temp folder, builds each one against the + packages in ./artifacts, and asserts the outcome the documentation promises. Nothing is + written inside the repository, so the check is safe to run locally; it is deliberately + not part of the `[Category=Unit]` pipeline run because it packs and restores from + nuget.org. + + Expectations and their documentation: + 01 .NET 11 + Windows with the documented settings -> builds, wslcsdk.dll copied + 02 ...with a stale WindowsSdkPackageVersion -> CS1705 + 03 ...with PlatformTarget=x86 -> fails PWC0002 + 04 ...with no settings at all (buildTransitive defaults) -> builds, wslcsdk.dll copied + 05 a module package with no settings (defaults are transitive) -> builds + 06 net8.0-windows + AssetTargetFallback escape hatch -> PWC0001 (the hatch does not work) + 07 net8.0-windows without the escape hatch -> PWC0001 + 08 plain net11.0 (not Windows-specific) -> PWC0001 + 09 ...with PlatformTarget=AnyCPU (corrected to x64) -> builds, wslcsdk.dll copied + 10 the net11.0-windows shorthand TFM (no OS version) -> PWC0001 + 11 multi-targeting with a conditional PackageReference -> builds + 12 multi-targeting with an unconditional PackageReference -> PWC0001 + +.PARAMETER FeedPath + Folder holding the packed .nupkg files. Defaults to /artifacts. + +.PARAMETER PackageVersion + Package version to consume. Defaults to the version in package.json. + +.PARAMETER WorkPath + Scratch folder for the generated consumers. Defaults to + %TEMP%/wslc-consumer-verification. + +.PARAMETER Keep + Keep the generated consumer projects for inspection instead of deleting them. + +.EXAMPLE + just verify-consumers + +.EXAMPLE + just verify-consumers -Keep +#> +[CmdletBinding()] +param( + [string] $FeedPath, + [string] $PackageVersion, + [string] $WorkPath = (Join-Path ([System.IO.Path]::GetTempPath()) 'wslc-consumer-verification'), + [switch] $Keep +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest + +$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path +$FeedPath = if ($FeedPath) { (Resolve-Path $FeedPath).Path } else { Join-Path $repoRoot 'artifacts' } + +if (-not $PackageVersion) { + $packageJson = Get-Content (Join-Path $repoRoot 'package.json') -Raw | ConvertFrom-Json + $PackageVersion = $packageJson.version +} + +if (-not (Test-Path $FeedPath)) { + throw "Package feed '$FeedPath' does not exist. Run 'just pack' first." +} + +$corePackage = Join-Path $FeedPath "Purview.WslContainers.$PackageVersion.nupkg" +if (-not (Test-Path $corePackage)) { + throw "Package '$corePackage' was not found. Run 'just pack' (or pass -FeedPath) first." +} + +$globalPackagesLine = & dotnet nuget locals global-packages --list | Select-Object -First 1 +$globalPackages = ($globalPackagesLine -replace '^global-packages:\s*', '').Trim() + +# The packages keep the same version between local packs, so a stale extraction in the global +# packages folder would silently test the previous build. Drop it before consuming the feed. +foreach ($packageId in 'purview.wslcontainers', 'purview.wslcontainers.postgresql') { + $packageFolder = Join-Path $globalPackages $packageId + $versioned = Join-Path $packageFolder $PackageVersion + + if (Test-Path $versioned) { + Remove-Item $versioned -Recurse -Force + } +} + +# MSBuild reuses build nodes between invocations and can keep serving the parse of a package file +# that was replaced at the same path (the version never changes between local packs). Shut the +# servers down so the freshly packed assets are parsed. +& dotnet build-server shutdown | Out-Null + +if (Test-Path $WorkPath) { + Remove-Item $WorkPath -Recurse -Force +} + +New-Item -ItemType Directory -Path $WorkPath -Force | Out-Null + +# Local feed first, then nuget.org for the transitive dependencies +# (Microsoft.WSL.Containers, Npgsql, ...). +$nugetConfig = @" + + + + + + + + +"@ +Set-Content -Path (Join-Path $WorkPath 'nuget.config') -Value $nugetConfig + +# A consumer that touches a Microsoft.WSL.Containers type is the realistic shape: the +# C#/WinRT projection is what pulls in the Windows SDK version that CS1705 complains about. +# OutputType=Exe so the runtime assets (wslcsdk.dll) are copied to the output for inspection. +$apiSource = @' +using Microsoft.WSL.Containers; +using Purview.WslContainers; + +namespace Consumer; + +public static class Program +{ + public static SessionSettings Session() => new("consumer-session", @"C:\temp\wslc"); + + public static WslContainer Container() => + new ContainerBuilder().WithImage("docker.io/library/alpine:3.19").Build(); + + public static void Main() { } +} +'@ + +$portableSource = @' +namespace Consumer; + +public static class Program +{ + public static string Hello() => "hello"; + + public static void Main() { } +} +'@ + +# Single-quoted template: {{...}} tokens are replaced so MSBuild's own $(...) syntax is +# never touched by PowerShell interpolation. +$projectTemplate = @' + + + {{FRAMEWORK}} + Exe + enable + enable + {{PROPERTIES}} + +{{ITEMS}} + + + + +'@ + +$net11Windows = 'net11.0-windows10.0.19041.0' +$net8Windows = 'net8.0-windows10.0.19041.0' +$sdkPackage = 'Purview.WslContainers' +$modulePackage = 'Purview.WslContainers.PostgreSql' +$sdkVersion = '10.0.26100.80' +$staleSdkVersion = '10.0.19041.38' +$x64 = 'x64' +$escapeHatch = 'net11.0-windows10.0.19041.0' + +$multiTargetItems = @' + + + + + + +'@ + +function New-ConsumerCase { + param( + [string] $Id, + [string] $Name, + [string] $Framework = "$net11Windows", + [string] $Package = $sdkPackage, + [string] $Properties = '', + [string] $ReferenceAttributes = '', + [string] $Items = '', + [hashtable] $Sources = @{ 'Smoke.cs' = $apiSource }, + [string] $Expect = 'Builds', + [string] $RequireFile = '' + ) + + [pscustomobject]@{ + Id = $Id + Name = $Name + Framework = $Framework + Package = $Package + Properties = $Properties + ReferenceAttributes = $ReferenceAttributes + Items = $Items + Sources = $Sources + Expect = $Expect + RequireFile = $RequireFile + } +} + +$cases = @( + New-ConsumerCase -Id '01' -Name 'net11 windows + documented settings' ` + -Properties "$sdkVersion$x64" -RequireFile 'wslcsdk.dll' + + New-ConsumerCase -Id '02' -Name 'net11 windows + stale WindowsSdkPackageVersion' ` + -Properties "$staleSdkVersion$x64" -Expect 'CS1705' + + New-ConsumerCase -Id '03' -Name 'net11 windows + PlatformTarget=x86' ` + -Properties "$sdkVersionx86" -Expect 'PWC0002' + + New-ConsumerCase -Id '04' -Name 'net11 windows + buildTransitive defaults only' ` + -RequireFile 'wslcsdk.dll' + + New-ConsumerCase -Id '05' -Name 'module package + transitive defaults only' ` + -Package $modulePackage + + New-ConsumerCase -Id '06' -Name 'net8 windows + AssetTargetFallback escape hatch' ` + -Framework "$net8Windows" ` + -Properties "$escapeHatch$sdkVersion$x64" -Expect 'PWC0001' + + New-ConsumerCase -Id '07' -Name 'net8 windows without the escape hatch' ` + -Framework "$net8Windows" ` + -Properties "$sdkVersion$x64" -Expect 'PWC0001' + + New-ConsumerCase -Id '08' -Name 'plain net11.0 (not Windows-specific)' ` + -Framework 'net11.0' ` + -Properties "$sdkVersion$x64" -Expect 'PWC0001' + + New-ConsumerCase -Id '09' -Name 'net11 windows + PlatformTarget=AnyCPU' ` + -Properties "$sdkVersionAnyCPU" -RequireFile 'wslcsdk.dll' + + New-ConsumerCase -Id '10' -Name 'net11.0-windows shorthand TFM (no OS version)' ` + -Framework 'net11.0-windows' ` + -Properties "$sdkVersion$x64" -Expect 'PWC0001' + + New-ConsumerCase -Id '11' -Name 'multi-targeting + conditional PackageReference' ` + -Framework "net11.0;$net11Windows" ` + -Properties 'false' ` + -ReferenceAttributes "Condition=`"'`$(TargetFramework)' == '$net11Windows'`"" ` + -Items $multiTargetItems ` + -Sources @{ 'Smoke.Windows.cs' = $apiSource; 'Smoke.Portable.cs' = $portableSource } + + New-ConsumerCase -Id '12' -Name 'multi-targeting + unconditional PackageReference' ` + -Framework "net11.0;$net11Windows" ` + -Properties 'false' ` + -Items $multiTargetItems ` + -Sources @{ 'Smoke.Windows.cs' = $apiSource; 'Smoke.Portable.cs' = $portableSource } ` + -Expect 'PWC0001' +) + + +Write-Host '' +Write-Host 'Purview.WslContainers consumer verification' -ForegroundColor Cyan +Write-Host " feed : $FeedPath" +Write-Host " version : $PackageVersion" +Write-Host " scratch : $WorkPath" +Write-Host '' + +$results = [System.Collections.Generic.List[object]]::new() + +foreach ($case in $cases) { + $slug = ($case.Name -replace '[^a-zA-Z0-9]+', '-').Trim('-').ToLowerInvariant() + $directory = Join-Path $WorkPath ("{0}-{1}" -f $case.Id, $slug) + New-Item -ItemType Directory -Path $directory -Force | Out-Null + + $project = $projectTemplate + $project = $project.Replace('{{FRAMEWORK}}', $case.Framework) + $project = $project.Replace('{{PROPERTIES}}', $case.Properties) + $project = $project.Replace('{{ITEMS}}', $case.Items) + $project = $project.Replace('{{PACKAGE}}', $case.Package) + $project = $project.Replace('{{VERSION}}', $PackageVersion) + $project = $project.Replace('{{REFERENCE_ATTRIBUTES}}', $case.ReferenceAttributes) + Set-Content -Path (Join-Path $directory 'Consumer.csproj') -Value $project + + foreach ($source in $case.Sources.GetEnumerator()) { + Set-Content -Path (Join-Path $directory $source.Key) -Value $source.Value + } + + $output = & dotnet build (Join-Path $directory 'Consumer.csproj') --nologo -v minimal 2>&1 | Out-String + $exitCode = $LASTEXITCODE + + $matched = $output -match [regex]::Escape($case.Expect) + $passed = if ($case.Expect -eq 'Builds') { $exitCode -eq 0 } else { $exitCode -ne 0 -and $matched } + + $signal = if ($case.Expect -eq 'Builds') { + "exit $exitCode" + } + elseif ($matched) { + "exit $exitCode, matched $($case.Expect)" + } + else { + "exit $exitCode, no $($case.Expect)" + } + + if ($passed -and $case.RequireFile) { + $found = @(Get-ChildItem -Path $directory -Recurse -Filter $case.RequireFile -File -ErrorAction SilentlyContinue) + + if ($found.Count -eq 0) { + $passed = $false + $signal = "$signal; $($case.RequireFile) not copied to the output" + } + else { + $signal = "$signal; $($case.RequireFile) copied to the output" + } + } + + $results.Add( + [pscustomobject]@{ + Id = $case.Id + Case = $case.Name + Expected = $case.Expect + Observed = $signal + Passed = $passed + Output = $output.Trim() + } + ) + + $colour = if ($passed) { 'Green' } else { 'Red' } + $verdict = if ($passed) { 'PASS' } else { 'FAIL' } + Write-Host (" {0} {1} {2} (expected {3}); observed {4}" -f $verdict, $case.Id, $case.Name, $case.Expect, $signal) -ForegroundColor $colour +} + +$failed = @($results | Where-Object { -not $_.Passed }) + +if ($failed.Count -gt 0) { + Write-Host '' + Write-Host 'Failing case output (first 40 lines each):' -ForegroundColor Yellow + + foreach ($result in $failed) { + Write-Host '' + Write-Host ("--- {0} {1} ---" -f $result.Id, $result.Case) -ForegroundColor Yellow + + ($result.Output -split "`r?`n") | Select-Object -First 40 | ForEach-Object { Write-Host " $_" } + } +} + +if (-not $Keep) { + Remove-Item $WorkPath -Recurse -Force -ErrorAction SilentlyContinue +} + +Write-Host '' +Write-Host ("{0}/{1} consumer checks passed." -f ($results.Count - $failed.Count), $results.Count) -ForegroundColor $(if ($failed.Count -eq 0) { 'Green' } else { 'Red' }) + +if ($failed.Count -gt 0) { + exit 1 +} + diff --git a/src/src/Azurite/Sdk/README.md b/src/src/Azurite/Sdk/README.md index 07203df..e784f15 100644 --- a/src/src/Azurite/Sdk/README.md +++ b/src/src/Azurite/Sdk/README.md @@ -7,9 +7,19 @@ integration testing, running as WSLC containers on **Microsoft WSL Containers** dotnet add package Purview.WslContainers.Azurite ``` -Depends on `Purview.WslContainers` (the core runtime) and needs Windows with WSL ≥ 2.9.3 (WSL Containers). +Depends on `Purview.WslContainers` (the core runtime). See the [Getting Started guide](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Getting-Started.md). +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp diff --git a/src/src/MsSql/Sdk/README.md b/src/src/MsSql/Sdk/README.md index db20410..442b743 100644 --- a/src/src/MsSql/Sdk/README.md +++ b/src/src/MsSql/Sdk/README.md @@ -10,6 +10,16 @@ dotnet add package Purview.WslContainers.MsSql Depends on `Purview.WslContainers` (the core runtime) and brings `Microsoft.Data.SqlClient` for connection-string generation and readiness probing. +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp @@ -37,7 +47,7 @@ await connection.OpenAsync(); | `AcceptLicense()` | Sets `ACCEPT_EULA=Y`. Required — the library never accepts licensing terms on your behalf. | | `MsSqlContainer.GetConnectionString()` | `SqlConnectionStringBuilder` connection string for the mapped host port. | -## Requirements and behaviour +## Behaviour and constraints - **Memory:** SQL Server refuses to start below 2000 MB. The default session VM is capped at 4096 MB (`WslContainerRuntimeOptions.Default`), so it works out of the box; override with diff --git a/src/src/MySql/Sdk/README.md b/src/src/MySql/Sdk/README.md index 917de3b..c4b2ef2 100644 --- a/src/src/MySql/Sdk/README.md +++ b/src/src/MySql/Sdk/README.md @@ -10,6 +10,16 @@ dotnet add package Purview.WslContainers.MySql Depends on `Purview.WslContainers` (the core runtime) and brings `MySqlConnector` for readiness probing and connection-string generation. +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp diff --git a/src/src/Nats/Sdk/README.md b/src/src/Nats/Sdk/README.md index be41e12..a44ff10 100644 --- a/src/src/Nats/Sdk/README.md +++ b/src/src/Nats/Sdk/README.md @@ -10,6 +10,16 @@ dotnet add package Purview.WslContainers.Nats Depends on `Purview.WslContainers` (the core runtime). `NATS.Client.Core` is not referenced by this package — bring your own client. +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp diff --git a/src/src/PostgreSql/Sdk/README.md b/src/src/PostgreSql/Sdk/README.md index 6b58cb2..4216a12 100644 --- a/src/src/PostgreSql/Sdk/README.md +++ b/src/src/PostgreSql/Sdk/README.md @@ -10,6 +10,16 @@ dotnet add package Purview.WslContainers.PostgreSql Depends on `Purview.WslContainers` (the core runtime) and brings `Npgsql` for connection-string generation. See the [Getting Started guide](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Getting-Started.md). +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp diff --git a/src/src/RabbitMq/Sdk/README.md b/src/src/RabbitMq/Sdk/README.md index ab497ed..efee828 100644 --- a/src/src/RabbitMq/Sdk/README.md +++ b/src/src/RabbitMq/Sdk/README.md @@ -10,6 +10,16 @@ dotnet add package Purview.WslContainers.RabbitMq Depends on `Purview.WslContainers` (the core runtime). `RabbitMQ.Client` is not referenced by this package — bring your own client. +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp diff --git a/src/src/Redis/Sdk/README.md b/src/src/Redis/Sdk/README.md index 05a9305..61005b5 100644 --- a/src/src/Redis/Sdk/README.md +++ b/src/src/Redis/Sdk/README.md @@ -10,6 +10,16 @@ dotnet add package Purview.WslContainers.Redis Depends on `Purview.WslContainers` (the core runtime). `StackExchange.Redis` is not referenced by this package — bring your own client. +## Requirements + +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`). +- **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). + `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- **Experimental:** the API, defaults and packaging can change between prereleases; there is no + production support guarantee. + ## Quick start ```csharp diff --git a/src/src/WslContainers/Sdk/README.md b/src/src/WslContainers/Sdk/README.md index 5e464ba..be297c4 100644 --- a/src/src/WslContainers/Sdk/README.md +++ b/src/src/WslContainers/Sdk/README.md @@ -10,10 +10,20 @@ dotnet add package Purview.WslContainers ## Requirements -- Windows 10/11 with **WSL ≥ 2.9.3** including WSL Containers (`wsl --install --no-distribution`). -- .NET 11 SDK or later (`net11.0-windows10.0.19041.0`). -- Verify with `wsl --version` (needs 2.9.3+) and `wslc version`. The library never installs or updates WSL +- Windows 10/11 with **WSL Containers** (`wsl --install --no-distribution`), verified against WSL 3.0.1.0. +- **A .NET 11 project targeting Windows specifically** — `net11.0-windows10.0.19041.0`, x64 or arm64. + A consuming project that targets anything else fails the build with `PWC0001` (target framework) or + `PWC0002` (platform), and without the packages' MSBuild defaults a stale + `WindowsSdkPackageVersion` fails with `CS1705`. +- This package supplies the `buildTransitive` defaults for `WindowsSdkPackageVersion` and + `PlatformTarget` that every module package inherits, so a consumer usually only chooses a target + framework. The full contract, the error reference and the `EnableWindowsTargeting` workaround for + non-Windows CI agents are in the + [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). +- Verify the host with `wsl --version` and `wslc version`. The library never installs or updates WSL itself; `WslContainerRuntime.GetInfoAsync()` reports what is missing. +- **Experimental:** this is an experiment in driving WSL Containers. The public API, defaults and + packaging rules can change between prereleases, and there is no production support guarantee. ## Quick start diff --git a/src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.props b/src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.props new file mode 100644 index 0000000..d758601 --- /dev/null +++ b/src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.props @@ -0,0 +1,21 @@ + + + + + 10.0.26100.80 + + diff --git a/src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.targets b/src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.targets new file mode 100644 index 0000000..961b94a --- /dev/null +++ b/src/src/WslContainers/Sdk/buildTransitive/Purview.WslContainers.targets @@ -0,0 +1,73 @@ + + + + + x64 + + + + + + <_PurviewWslContainersPlatformVersionSupported + Condition="'$(TargetPlatformVersion)' != '' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetPlatformVersion), '10.0.19041.0'))" + >true + <_PurviewWslContainersTargetFrameworkSupported + Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '11.0')) AND '$(TargetPlatformIdentifier)' == 'Windows' AND '$(_PurviewWslContainersPlatformVersionSupported)' == 'true'" + >true + + + + + + + + <_PurviewWslContainersPlatformTargetSupported + Condition="'$(PlatformTarget)' == 'x64' OR '$(PlatformTarget)' == 'arm64' OR ('$(PlatformTarget)' == '' AND '$(RuntimeIdentifier)' != '')" + >true + + + + + diff --git a/src/tests/WslContainers.UnitTests/ConsumerRequirementsTests.cs b/src/tests/WslContainers.UnitTests/ConsumerRequirementsTests.cs new file mode 100644 index 0000000..eb7723a --- /dev/null +++ b/src/tests/WslContainers.UnitTests/ConsumerRequirementsTests.cs @@ -0,0 +1,45 @@ +using System.Reflection; +using System.Runtime.Versioning; + +namespace Purview.WslContainers; + +/// +/// Guards the consumer contract documented in docs/wiki/Consumer-Requirements.md: every +/// package is a .NET 11 project that targets Windows specifically. A consumer cannot restore the +/// package from anything else, so a drift here has to fail the build rather than quietly +/// invalidate the documentation and the shipped buildTransitive defaults. +/// +public class ConsumerRequirementsTests +{ + static readonly Assembly Library = typeof(WslContainerRuntime).Assembly; + static readonly string[] WindowsPlatform = ["Windows10.0.19041.0"]; + + [Test] + public async Task LibraryTargetsNet11() + { + var targetFramework = Library.GetCustomAttribute(); + + await Assert.That(targetFramework).IsNotNull(); + await Assert.That(targetFramework!.FrameworkName).IsEqualTo(".NETCoreApp,Version=v11.0"); + } + + [Test] + public async Task LibraryTargetsWindows() + { + var targetPlatform = Library.GetCustomAttribute(); + + await Assert.That(targetPlatform).IsNotNull(); + await Assert.That(targetPlatform!.PlatformName).IsEqualTo("Windows10.0.19041.0"); + } + + [Test] + public async Task LibraryIsSupportedOnWindowsOnly() + { + var platforms = Library + .GetCustomAttributes() + .Select(attribute => attribute.PlatformName) + .ToArray(); + + await Assert.That(platforms).IsEquivalentTo(WindowsPlatform); + } +} From 1521d7a0c9e970a82e2c5762d71d883fc5300ddc Mon Sep 17 00:00:00 2001 From: Kieron Lanning Date: Wed, 30 Sep 2026 22:41:18 +0100 Subject: [PATCH 2/2] chore(repo): standardise on the wsl-containers name The repository is now purview-dev/wsl-containers (GitHub redirects the old name), so every reference follows it. - point the release badge, package.json, mkdocs repo_url and the package README links at the new repository name - add the missing nuget.org Project Site link (PackageProjectUrl) for every packable project, and document where each piece of package metadata comes from --- README.md | 2 +- docs/wiki/Packaging.md | 15 +++++++++++++++ mkdocs.yml | 2 +- package.json | 8 ++++---- src/Directory.Build.props | 4 ++++ src/src/Azurite/Sdk/README.md | 6 +++--- src/src/MsSql/Sdk/README.md | 6 +++--- src/src/MySql/Sdk/README.md | 6 +++--- src/src/Nats/Sdk/README.md | 6 +++--- src/src/PostgreSql/Sdk/README.md | 8 ++++---- src/src/RabbitMq/Sdk/README.md | 8 ++++---- src/src/Redis/Sdk/README.md | 6 +++--- src/src/WslContainers/Sdk/README.md | 14 +++++++------- 13 files changed, 55 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 37d9f24..61a5e0d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Purview.WslContainers [![NuGet version](https://img.shields.io/nuget/v/Purview.WslContainers.svg)](https://www.nuget.org/packages/Purview.WslContainers) -[![Release](https://github.com/purview-dev/wslc-testcontainers/actions/workflows/release.yml/badge.svg)](https://github.com/purview-dev/wslc-testcontainers/actions/workflows/release.yml) +[![Release](https://github.com/purview-dev/wsl-containers/actions/workflows/release.yml/badge.svg)](https://github.com/purview-dev/wsl-containers/actions/workflows/release.yml) A **WSLC-native** Testcontainers-style library for .NET that runs throwaway Linux containers for integration testing on **Microsoft WSL Containers (WSLC)** — with no Docker installation. diff --git a/docs/wiki/Packaging.md b/docs/wiki/Packaging.md index 50de688..4087509 100644 --- a/docs/wiki/Packaging.md +++ b/docs/wiki/Packaging.md @@ -21,6 +21,21 @@ Portable PDBs are delivered through the `.snupkg`, never inside the `.nupkg`. `$(TFM)` is `net11.0-windows10.0.19041.0`, so every package is a **.NET 11, Windows-only** package. Consumers must target a matching framework; see [Consumer Requirements](Consumer-Requirements.md). +## Package metadata + +Metadata is split by where its source of truth lives: + +| Metadata | Source | +| --- | --- | +| `id`, `description`, `tags`, licence, authors | each project's `.csproj` | +| `version`, `repository`, `bugs` | `package.json` (applied by `Purview.BuildSdk`) | +| icon, package README, **project site** | `src/Directory.Build.props`, for every packable project | + +The **project site** (`PackageProjectUrl`) is `https://github.com/purview-dev/wsl-containers`, the +repository that hosts this documentation wiki; it shows as *Project Site* on nuget.org. Repository and +commit metadata come from SourceLink, so the `repository` entry in a locally packed `.nupkg` points at +the branch and commit that produced it. + ## The `Sdk/` folder convention `Purview.BuildSdk` packs a packable project's `Sdk/` folder automatically (`PurviewAutoSdkPack`): diff --git a/mkdocs.yml b/mkdocs.yml index c487fe2..5151edb 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,6 @@ site_name: Purview WSL Test Containers site_description: Developer documentation for Purview WSL Test Containers -repo_url: https://github.com/purview-dev/wsl-testcontainers +repo_url: https://github.com/purview-dev/wsl-containers edit_uri: edit/main/docs/wiki/ docs_dir: docs/wiki diff --git a/package.json b/package.json index b0379b6..fca5f41 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,17 @@ { - "name": "purview-wsl-testcontainers", + "name": "purview-wsl-containers", "version": "1.0.0-prerelease.1", "license": "MIT", "author": { "name": "Kieron Lanning", "url": "https://kieronlanning.dev/" }, - "homepage": "https://purview.dev/projects/wsl-testcontainers/", + "homepage": "https://purview.dev/projects/wsl-containers/", "bugs": { - "url": "https://github.com/purview-dev/wsl-testcontainers/issues" + "url": "https://github.com/purview-dev/wsl-containers/issues" }, "repository": { "type": "git", - "url": "git+https://github.com/purview-dev/wsl-testcontainers.git" + "url": "git+https://github.com/purview-dev/wsl-containers.git" } } \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 099810b..39f39eb 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -17,6 +17,10 @@ purview-logo-light.png README.md + + https://github.com/purview-dev/wsl-containers diff --git a/src/src/Azurite/Sdk/README.md b/src/src/Azurite/Sdk/README.md index e784f15..4e469ba 100644 --- a/src/src/Azurite/Sdk/README.md +++ b/src/src/Azurite/Sdk/README.md @@ -8,7 +8,7 @@ dotnet add package Purview.WslContainers.Azurite ``` Depends on `Purview.WslContainers` (the core runtime). -See the [Getting Started guide](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Getting-Started.md). +See the [Getting Started guide](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Getting-Started.md). ## Requirements @@ -16,7 +16,7 @@ See the [Getting Started guide](https://github.com/purview-dev/wsl-testcontainer - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -52,5 +52,5 @@ for the `successfully listening` log signal. Endpoints and the connection string The well-known `devstoreaccount1` key is a published constant of the emulator, but this library does not embed it: `AzuriteAccount.Key` holds a placeholder. Supply the real key in your test infrastructure before exercising authenticated operations (anonymous/local development paths are unaffected when the client does -not require the key). See [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) +not require the key). See [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) for the module contract. diff --git a/src/src/MsSql/Sdk/README.md b/src/src/MsSql/Sdk/README.md index 442b743..e69334e 100644 --- a/src/src/MsSql/Sdk/README.md +++ b/src/src/MsSql/Sdk/README.md @@ -16,7 +16,7 @@ connection-string generation and readiness probing. - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -61,5 +61,5 @@ await connection.OpenAsync(); ## Documentation -- [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. -- [Getting Started](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Getting-Started.md) — prerequisites and first-container walkthrough. +- [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. +- [Getting Started](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Getting-Started.md) — prerequisites and first-container walkthrough. diff --git a/src/src/MySql/Sdk/README.md b/src/src/MySql/Sdk/README.md index c4b2ef2..2ff2c0d 100644 --- a/src/src/MySql/Sdk/README.md +++ b/src/src/MySql/Sdk/README.md @@ -16,7 +16,7 @@ connection-string generation. - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -61,5 +61,5 @@ strategy with `WithWaitStrategy(...)` if you need different behaviour. ## Documentation -- [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. -- [Wait Strategies](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. +- [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. +- [Wait Strategies](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. diff --git a/src/src/Nats/Sdk/README.md b/src/src/Nats/Sdk/README.md index a44ff10..8c43cfd 100644 --- a/src/src/Nats/Sdk/README.md +++ b/src/src/Nats/Sdk/README.md @@ -16,7 +16,7 @@ package — bring your own client. - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -50,5 +50,5 @@ with `WithWaitStrategy(...)`. Endpoint accessors resolve the mapped host ports, ## Documentation -- [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. -- [Wait Strategies](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. +- [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. +- [Wait Strategies](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. diff --git a/src/src/PostgreSql/Sdk/README.md b/src/src/PostgreSql/Sdk/README.md index 4216a12..874d0d5 100644 --- a/src/src/PostgreSql/Sdk/README.md +++ b/src/src/PostgreSql/Sdk/README.md @@ -8,7 +8,7 @@ dotnet add package Purview.WslContainers.PostgreSql ``` Depends on `Purview.WslContainers` (the core runtime) and brings `Npgsql` for connection-string generation. -See the [Getting Started guide](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Getting-Started.md). +See the [Getting Started guide](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Getting-Started.md). ## Requirements @@ -16,7 +16,7 @@ See the [Getting Started guide](https://github.com/purview-dev/wsl-testcontainer - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -55,5 +55,5 @@ your own with `WithWaitStrategy(...)`. Call `GetConnectionString()` after `Start ## Documentation -- [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. -- [Wait Strategies](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. +- [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. +- [Wait Strategies](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. diff --git a/src/src/RabbitMq/Sdk/README.md b/src/src/RabbitMq/Sdk/README.md index efee828..de3ea32 100644 --- a/src/src/RabbitMq/Sdk/README.md +++ b/src/src/RabbitMq/Sdk/README.md @@ -16,7 +16,7 @@ bring your own client. - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -58,9 +58,9 @@ Call the endpoint accessors after `StartAsync()`. The default wait strategy matches the canonical `Server startup complete` log line rather than running `rabbitmq-diagnostics ping`: under WSLC an exec-based probe races the Erlang cookie setup and can trigger a startup failure (`eacces` reading `.erlang.cookie`). See -[Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) for the full note. +[Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) for the full note. ## Documentation -- [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. -- [Wait Strategies](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. +- [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. +- [Wait Strategies](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. diff --git a/src/src/Redis/Sdk/README.md b/src/src/Redis/Sdk/README.md index 61005b5..6eacbff 100644 --- a/src/src/Redis/Sdk/README.md +++ b/src/src/Redis/Sdk/README.md @@ -16,7 +16,7 @@ package — bring your own client. - **A .NET 11 project targeting Windows specifically** (`net11.0-windows10.0.19041.0`, x64 or arm64). `Purview.WslContainers` supplies `buildTransitive` defaults for `WindowsSdkPackageVersion` and `PlatformTarget`, and rejects an unsupported consumer with `PWC0001`/`PWC0002` — see the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - **Experimental:** the API, defaults and packaging can change between prereleases; there is no production support guarantee. @@ -57,5 +57,5 @@ await using var garnet = new RedisBuilder("ghcr.io/microsoft/garnet:latest").Bui ## Documentation -- [Modules](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. -- [Wait Strategies](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. +- [Modules](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Modules.md) — the module contract and readiness choices. +- [Wait Strategies](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Wait-Strategies.md) — overriding readiness checks. diff --git a/src/src/WslContainers/Sdk/README.md b/src/src/WslContainers/Sdk/README.md index be297c4..a078c38 100644 --- a/src/src/WslContainers/Sdk/README.md +++ b/src/src/WslContainers/Sdk/README.md @@ -19,7 +19,7 @@ dotnet add package Purview.WslContainers `PlatformTarget` that every module package inherits, so a consumer usually only chooses a target framework. The full contract, the error reference and the `EnableWindowsTargeting` workaround for non-Windows CI agents are in the - [consumer requirements](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Consumer-Requirements.md). + [consumer requirements](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Consumer-Requirements.md). - Verify the host with `wsl --version` and `wslc version`. The library never installs or updates WSL itself; `WslContainerRuntime.GetInfoAsync()` reports what is missing. - **Experimental:** this is an experiment in driving WSL Containers. The public API, defaults and @@ -104,11 +104,11 @@ and diagnostics. ## Documentation -See the [project wiki](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Home.md): -[Getting Started](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Getting-Started.md), -[Architecture](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Architecture.md), -[Lifecycle](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Lifecycle.md), -[Networking](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Networking.md) and -[Wait Strategies](https://github.com/purview-dev/wsl-testcontainers/blob/main/docs/wiki/Wait-Strategies.md). +See the [project wiki](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Home.md): +[Getting Started](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Getting-Started.md), +[Architecture](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Architecture.md), +[Lifecycle](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Lifecycle.md), +[Networking](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Networking.md) and +[Wait Strategies](https://github.com/purview-dev/wsl-containers/blob/main/docs/wiki/Wait-Strategies.md). Ready-made service modules ship as `Purview.WslContainers.PostgreSql`, `Redis`, `MsSql`, `RabbitMq`, `Azurite`, `Nats` and `MySql`.