From 190dae453cb53432086fc72d794cc0b22739bc54 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 14:12:10 +0100 Subject: [PATCH 01/19] docs: add AI agent docs --- AGENTS.md | 67 ++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 15 ++++++++++ docs/Architecture.md | 38 +++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 docs/Architecture.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..bf7d5e2 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,67 @@ +# AGENTS.md + +Guidance for AI coding agents and contributors working in this repository. + +## Overview + +Appy.Parsing is an open-source .NET library, published to nuget.org, that turns raw text into +objects. A regex-based lexer splits text into tokens and a parser combines tokens into objects; +fluent builders define the grammar. Usage lives in [README.md](README.md), design in +[docs/Architecture.md](docs/Architecture.md). + +## Build Commands + +```bash +dotnet tool restore # cake, minver-cli, gpr +dotnet cake # Default target: clean, build, test, pack into .artifacts/ +dotnet test src/Appy.Parsing.sln # tests only +dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" +``` + +- The cake build treats warnings as errors. +- `config.yml` lists the projects cake builds and their role (`Package` or `Test`). A new + project not listed there is skipped by the build. +- Never run the `Publish` cake target or `dotnet nuget push` locally; CI publishes. + +## Structure + +| Path | Purpose | +|------|---------| +| `src/Appy.Parsing/` | The library: `Builder/`, `Lexers/`, `Parsers/` | +| `src/Appy.Parsing.Tests/` | xUnit tests | +| `src/Directory.Build.*` | Shared build settings, package metadata, MinVer settings | +| `build.cake`, `functions.cake`, `config.yml` | Cake build | +| `.github/workflows/` | `ci.yaml` on pull requests, `publish.yaml` on push to `master` or a tag | +| `docs/` | Architecture and plans | + +## Versioning and Publishing + +- [MinVer](https://github.com/adamralph/minver) derives the version from git tags + (`MAJOR.MINOR.PATCH`, no `v` prefix). Untagged commits get a `-preview.0.N` suffix. +- A push to `master` that touches `src/` publishes a preview package; a tag publishes that + version. Do not create tags or releases unless a maintainer asks. +- Dropping a target framework or public API is a breaking change: call it out in the PR. + +## Tests + +- xUnit with FluentAssertions. Tests build real lexers and parsers through the builders; no mocks. +- Add or update a test with every behaviour change, and write it first. + +## Code Style + +- `.editorconfig`: 4 spaces, CRLF; 2 spaces for XML, JSON and YAML. +- Match the existing code: `_camelCase` private fields, lower camel case private methods + (`populateUnmatchedPart`), no explicit `private` modifier. +- Public types and members carry XML doc comments. + +## Git Conventions + +- Branches: `feat/…`, `fix/…`, `docs/…`, `chore/…`, from `master`. +- Commits: conventional commits, `type(scope): subject`, imperative, lower case, no trailing dot + ([CONTRIBUTING.md](CONTRIBUTING.md#commit)). Breaking changes go in a `BREAKING CHANGE:` footer. +- No `Co-Authored-By` or tool attribution trailers. +- Public repository: never commit secrets, private feeds or internal links. + +## Documentation + +- [docs/Architecture.md](docs/Architecture.md): start here diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..2c18207 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,15 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +@./AGENTS.md + +## Build & Test + +```bash +dotnet tool restore +dotnet cake # clean, build, test, pack into .artifacts/ +dotnet test src/Appy.Parsing.sln # tests only +``` + +Never run the `Publish` cake target or `dotnet nuget push`; publishing happens in CI only. diff --git a/docs/Architecture.md b/docs/Architecture.md new file mode 100644 index 0000000..ea85ff3 --- /dev/null +++ b/docs/Architecture.md @@ -0,0 +1,38 @@ +# Appy.Parsing: Architecture + +## Overview + +Appy.Parsing converts raw text into objects in two stages. A `Lexer` runs one combined regular +expression (one named group per `Tokenizer`) and turns each match into a token object; text that +matches nothing is kept as a string unless the lexer ignores it. A `Parser` then applies its +`TokenParser` rules in registration order. Each rule encodes the token sequence as a string of type +identifiers, matches its pattern against it and replaces the matched run with the object it +creates, repeating until the rule no longer matches. + +`LexerBuilder` and `ParserBuilder` are the public entry points: fluent builders that declare the +grammar. Build and test guidance lives in [AGENTS.md](../AGENTS.md). + +## System Diagram + +```mermaid +graph LR + Text["Input text"] --> Lexer + LexerBuilder -->|creates| Lexer + Lexer -->|tokens| Parser + ParserBuilder -->|creates| Parser + Parser -->|applies TokenParser rules in order| Result["object[] or T"] +``` + +## Key Patterns + +### Builders define the grammar + +`LexerBuilder.Match*` registers tokenizers (regex, enum values via `[Match]`, dictionaries). +`ParserBuilder.Match*` registers token rules with `MatchOptions` (`AllInOrder`, `AnyOrder`, +`AtLeastOne`) that expand into one rule per accepted token combination. Builders compose with +`CombineWith`. + +### Cached tokenization + +`Lexer` caches the token array per input expression in a `ConcurrentDictionary`, so repeated +expressions skip the regex pass. From dbb567adee7cb2ed8dd5ae8915a3aabb3205eedf Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 14:17:09 +0100 Subject: [PATCH 02/19] docs(plan): add net10 migration plan --- AGENTS.md | 1 + docs/Architecture.md | 6 ++ docs/plans/001-net10-migration.md | 92 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 docs/plans/001-net10-migration.md diff --git a/AGENTS.md b/AGENTS.md index bf7d5e2..e1aa278 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -65,3 +65,4 @@ dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" ## Documentation - [docs/Architecture.md](docs/Architecture.md): start here +- [docs/plans/](docs/plans/): implementation plans (`NNN-slug.md`) diff --git a/docs/Architecture.md b/docs/Architecture.md index ea85ff3..e3e61f6 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -36,3 +36,9 @@ graph LR `Lexer` caches the token array per input expression in a `ConcurrentDictionary`, so repeated expressions skip the regex pass. + +## Plans + +| Plan | Status | Summary | +|------|--------|---------| +| [001 .NET 10 Migration](plans/001-net10-migration.md) | Planned | Target net10.0, net9.0 and net8.0; align build and CI | diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md new file mode 100644 index 0000000..e75964e --- /dev/null +++ b/docs/plans/001-net10-migration.md @@ -0,0 +1,92 @@ +# .NET 10 Migration + +- **Status:** Planned +- **Branch:** `feat/net10` + +## Summary + +Move Appy.Parsing from `net6.0;netstandard2.0` to `net10.0;net9.0;net8.0` on the .NET 10 SDK, +with tests on `net10.0`. The build, packages, test +stack and GitHub Actions line up with +[Appy.Configuration](https://github.com/YellowLineParking/Appy.Configuration), which already made +this move. No public API or behaviour change is intended; only the supported frameworks change. + +## Decisions + +| Decision | Context | Alternatives Considered | +|----------|---------|------------------------| +| Library `net10.0;net9.0;net8.0`, tests `net10.0` | net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. The code has no framework-specific paths, so one test TFM covers it. | Keep `netstandard2.0`: keeps .NET Framework users, but they can stay on 1.x. | +| **Release 2.0.0** (to approve) | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | +| MinVer 8.0.0 (MSBuild and CLI), `preview.0` pre-release identifiers, minimum major.minor `2.0` | MinVer 8 fails on the old "default pre-release phase" option used today. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | Stay on MinVer 4.1.0: works, but old. | +| Central package management, Traversal build, `.sln` kept | Same layout as the reference repo. | `.slnx`: the reference still uses `.sln`. | +| xUnit v3 4.0.1, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v2 2.9.3 as the reference: works, but leaves a migration for later. | +| Package validation against 1.1.0 | Guards the API from this release on. The only expected findings are the two dropped TFMs (PKV006), suppressed explicitly. | None (the reference has none): a TFM or API drop could ship silently. | +| Drop `Microsoft.SourceLink.GitHub`, `Nullable`, unused `Moq` | Source Link ships in the .NET 8+ SDK; the polyfill and `Moq` are unused on net8+. | Keep them as the reference does: dead dependencies. | +| Nullable reference types stay off | Annotating the public API is a separate change. | Enable now: widens a framework-only PR. | + +## Tasks + +Each task is one commit. The `!` marks the breaking change. + +- [ ] 1. `feat(dotnet)!: target net10.0, net9.0 and net8.0`: `global.json` SDK `10.0.100` with + `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0`; remove the + `Nullable` package, the `Microsoft.NETCore.App.Ref` download and the annotator properties; + `PackageTags` to `NET10;NET9;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. +- [ ] 2. `chore(deps): adopt central package management and upgrade packages`: add + `src/Directory.Packages.props`, move all versions out of `Directory.Build.props` and the csproj + files, drop `Moq` and `Microsoft.SourceLink.GitHub`. Latest stable on nuget.org at planning time: + Microsoft.NET.Test.Sdk 18.10.1, FluentAssertions 7.2.2, NodaTime 3.3.5, + GitHubActionsTestLogger 3.0.5, XunitXml.TestLogger 8.0.0. Test: build with `-warnaserror`, 14 tests pass. +- [ ] 3. `test: migrate tests to xUnit v3`: `xunit` to `xunit.v3` 4.0.1, + `xunit.runner.visualstudio` 4.0.0, `OutputType` `Exe`, per the xUnit v3 migration guide. Test: + 14 tests discovered and passing (a count of 0 is a failure). +- [ ] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the + reference without the Docker tasks (Cake 6 `DotNet*` API, Traversal support); add `src/build.csproj` + (Microsoft.Build.Traversal 4.1.82, pinned in `global.json`); `dotnet-tools.json` cake.tool 6.3.0, + minver-cli 8.0.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as + the reference). MinVer 8.0.0 with `MinVerDefaultPreReleaseIdentifiers=preview.0` and + `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets`, and the same values passed to the CLI + from `build.cake` (Cake.MinVer only exposes the old phase option, so use argument customization). + If Cake.MinVer cannot drive minver-cli 8, pin both MinVer packages to the newest version that works. + Test: `dotnet cake` prints the same version as the `.nupkg` file name. +- [ ] 5. `feat(packages): enable package validation against 1.1.0`: `EnablePackageValidation`, + `PackageValidationBaselineVersion=1.1.0`, and a generated `CompatibilitySuppressions.xml` with only + PKV006 for `net6.0` and `netstandard2.0`. Test: pack fails before the suppression file (red) and + passes with it (green). +- [ ] 6. `ci: update GitHub Actions for .NET 10`: `ci.yaml` and `publish.yaml` as the reference: + `actions/checkout@v6`, `actions/cache@v5`, `actions/setup-dotnet@v5` (global.json on Linux, + 8.0.x/9.0.x/10.0.x on the Windows and macOS matrix). Triggers stay as they are; no Docker steps. + Test: PR checks green on all three OSes. +- [ ] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net9.0, net10.0; + 1.x stays available for `netstandard2.0` and `net6.0`), AGENTS.md (central package management, + xUnit v3), this plan's status. The README badge moves to 2.0.0 after the release, as a + `docs(readme)` commit. + +## Verification + +- [ ] `dotnet build src/Appy.Parsing.sln -c Release -warnaserror`: 0 warnings, 0 errors. +- [ ] `dotnet test src/Appy.Parsing.sln`: 14 passed on net10.0 (4 facts, 10 theory cases). +- [ ] `dotnet cake` (Default target) is green, and `.artifacts/Appy.Parsing.2.0.0-preview.0.N.nupkg` + holds `lib/net8.0`, `lib/net9.0` and `lib/net10.0` only. +- [ ] Package validation runs on pack; the suppression file lists only the two PKV006 entries. +- [ ] No `.cs` change under `src/Appy.Parsing/`, so the public API is unchanged. +- [ ] Nothing is published or tagged from a local machine. +- [ ] Done when: the PR is merged, a maintainer tags `2.0.0`, the publish workflow is green, and + nuget.org lists Appy.Parsing 2.0.0 for net8.0, net9.0 and net10.0. Merging also publishes a + `2.0.0-preview.0.N` package first; that is expected. + +## Key Files + +``` +global.json # SDK 10, Traversal SDK pin +src/Directory.Build.props # package metadata, validation settings +src/Directory.Build.targets # MinVer settings +src/Directory.Packages.props # (new) central package versions +src/build.csproj # (new) Traversal build +src/Appy.Parsing/Appy.Parsing.csproj # library TFMs +src/Appy.Parsing/CompatibilitySuppressions.xml # (new) PKV006 for dropped TFMs +src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj # test TFM, xUnit v3 +build.cake, dotnet-tools.json # Cake 6, MinVer 8 +.github/workflows/ci.yaml, publish.yaml # action versions, SDK setup +README.md, AGENTS.md # supported frameworks, conventions +``` From 26e7a4ef7c4bd10dd10e10c5614af22a459afc52 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 14:47:15 +0100 Subject: [PATCH 03/19] docs(plan): apply review decisions --- docs/Architecture.md | 2 +- docs/plans/001-net10-migration.md | 80 +++++++++++++++---------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/docs/Architecture.md b/docs/Architecture.md index e3e61f6..d86e5fe 100644 --- a/docs/Architecture.md +++ b/docs/Architecture.md @@ -41,4 +41,4 @@ expressions skip the regex pass. | Plan | Status | Summary | |------|--------|---------| -| [001 .NET 10 Migration](plans/001-net10-migration.md) | Planned | Target net10.0, net9.0 and net8.0; align build and CI | +| [001 .NET 10 Migration](plans/001-net10-migration.md) | In Progress | Target net10.0 and net8.0; align build and CI | diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index e75964e..27f7bda 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -1,25 +1,25 @@ # .NET 10 Migration -- **Status:** Planned +- **Status:** In Progress - **Branch:** `feat/net10` ## Summary -Move Appy.Parsing from `net6.0;netstandard2.0` to `net10.0;net9.0;net8.0` on the .NET 10 SDK, -with tests on `net10.0`. The build, packages, test -stack and GitHub Actions line up with -[Appy.Configuration](https://github.com/YellowLineParking/Appy.Configuration), which already made -this move. No public API or behaviour change is intended; only the supported frameworks change. +Move Appy.Parsing from `net6.0;netstandard2.0` to `net10.0;net8.0` on the .NET 10 SDK, with tests +on `net10.0`, and release it as 2.0.0. The build, packages, test stack and GitHub Actions line up +with [Appy.Configuration](https://github.com/YellowLineParking/Appy.Configuration), which already +made this move. No public API or behaviour change is intended; only the supported frameworks change. ## Decisions | Decision | Context | Alternatives Considered | |----------|---------|------------------------| -| Library `net10.0;net9.0;net8.0`, tests `net10.0` | net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. The code has no framework-specific paths, so one test TFM covers it. | Keep `netstandard2.0`: keeps .NET Framework users, but they can stay on 1.x. | -| **Release 2.0.0** (to approve) | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | -| MinVer 8.0.0 (MSBuild and CLI), `preview.0` pre-release identifiers, minimum major.minor `2.0` | MinVer 8 fails on the old "default pre-release phase" option used today. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | Stay on MinVer 4.1.0: works, but old. | +| Library `net10.0;net8.0`, tests `net10.0` | net10.0 and net8.0 are the supported LTS releases. net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. The code has no framework-specific paths, so one test TFM covers it. | Also `net9.0`: a short-term release that net8.0 assets already cover. Keep `netstandard2.0`: .NET Framework users can stay on 1.x. | +| Release 2.0.0 | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | +| MinVer as the reference (2.3.0, package and CLI), phase `preview`, minimum major.minor `2.0` | One versioning setup across both repos. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | MinVer 8: needs a workaround in `build.cake` because Cake.MinVer only exposes the phase option that MinVer 8 rejects. | | Central package management, Traversal build, `.sln` kept | Same layout as the reference repo. | `.slnx`: the reference still uses `.sln`. | -| xUnit v3 4.0.1, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v2 2.9.3 as the reference: works, but leaves a migration for later. | +| xUnit v3 3.2.2 with `xunit.runner.visualstudio` 3.1.5, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode; 3.2.2 matches the sibling repos. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v3 4.x: newer, not yet used alongside. xUnit v2 as the reference: leaves a migration for later. | +| CI installs only the .NET 10 SDK (from `global.json`) | The SDK builds both TFMs; tests run on net10.0 only. | Install 8/9/10 as the reference: unused runtimes. | | Package validation against 1.1.0 | Guards the API from this release on. The only expected findings are the two dropped TFMs (PKV006), suppressed explicitly. | None (the reference has none): a TFM or API drop could ship silently. | | Drop `Microsoft.SourceLink.GitHub`, `Nullable`, unused `Moq` | Source Link ships in the .NET 8+ SDK; the polyfill and `Moq` are unused on net8+. | Keep them as the reference does: dead dependencies. | | Nullable reference types stay off | Annotating the public API is a separate change. | Enable now: widens a framework-only PR. | @@ -28,65 +28,63 @@ this move. No public API or behaviour change is intended; only the supported fra Each task is one commit. The `!` marks the breaking change. -- [ ] 1. `feat(dotnet)!: target net10.0, net9.0 and net8.0`: `global.json` SDK `10.0.100` with +- [ ] 1. `feat(dotnet)!: target net10.0 and net8.0`: `global.json` SDK `10.0.100` with `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0`; remove the `Nullable` package, the `Microsoft.NETCore.App.Ref` download and the annotator properties; - `PackageTags` to `NET10;NET9;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. + `PackageTags` to `NET10;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. - [ ] 2. `chore(deps): adopt central package management and upgrade packages`: add `src/Directory.Packages.props`, move all versions out of `Directory.Build.props` and the csproj - files, drop `Moq` and `Microsoft.SourceLink.GitHub`. Latest stable on nuget.org at planning time: - Microsoft.NET.Test.Sdk 18.10.1, FluentAssertions 7.2.2, NodaTime 3.3.5, - GitHubActionsTestLogger 3.0.5, XunitXml.TestLogger 8.0.0. Test: build with `-warnaserror`, 14 tests pass. -- [ ] 3. `test: migrate tests to xUnit v3`: `xunit` to `xunit.v3` 4.0.1, - `xunit.runner.visualstudio` 4.0.0, `OutputType` `Exe`, per the xUnit v3 migration guide. Test: + files, drop `Moq` and `Microsoft.SourceLink.GitHub`. Versions: Microsoft.NET.Test.Sdk 18.10.1, + FluentAssertions 7.2.2, NodaTime 3.3.5, GitHubActionsTestLogger 3.0.5, XunitXml.TestLogger 8.0.0, + MinVer 2.3.0. Test: build with `-warnaserror`, 14 tests pass. +- [ ] 3. `test: migrate tests to xUnit v3`: `xunit` to `xunit.v3` 3.2.2, + `xunit.runner.visualstudio` 3.1.5, `OutputType` `Exe`, per the xUnit v3 migration guide. Test: 14 tests discovered and passing (a count of 0 is a failure). - [ ] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the reference without the Docker tasks (Cake 6 `DotNet*` API, Traversal support); add `src/build.csproj` (Microsoft.Build.Traversal 4.1.82, pinned in `global.json`); `dotnet-tools.json` cake.tool 6.3.0, - minver-cli 8.0.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as - the reference). MinVer 8.0.0 with `MinVerDefaultPreReleaseIdentifiers=preview.0` and - `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets`, and the same values passed to the CLI - from `build.cake` (Cake.MinVer only exposes the old phase option, so use argument customization). - If Cake.MinVer cannot drive minver-cli 8, pin both MinVer packages to the newest version that works. - Test: `dotnet cake` prints the same version as the `.nupkg` file name. + minver-cli 2.3.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as + the reference). `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets` and + `WithMinimumMajorMinor("2.0")` in `build.cake`. Test: `dotnet cake` prints the same version as the + `.nupkg` file name. - [ ] 5. `feat(packages): enable package validation against 1.1.0`: `EnablePackageValidation`, `PackageValidationBaselineVersion=1.1.0`, and a generated `CompatibilitySuppressions.xml` with only PKV006 for `net6.0` and `netstandard2.0`. Test: pack fails before the suppression file (red) and passes with it (green). - [ ] 6. `ci: update GitHub Actions for .NET 10`: `ci.yaml` and `publish.yaml` as the reference: - `actions/checkout@v6`, `actions/cache@v5`, `actions/setup-dotnet@v5` (global.json on Linux, - 8.0.x/9.0.x/10.0.x on the Windows and macOS matrix). Triggers stay as they are; no Docker steps. - Test: PR checks green on all three OSes. -- [ ] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net9.0, net10.0; - 1.x stays available for `netstandard2.0` and `net6.0`), AGENTS.md (central package management, - xUnit v3), this plan's status. The README badge moves to 2.0.0 after the release, as a - `docs(readme)` commit. + `actions/checkout@v6`, `actions/cache@v5`, `actions/setup-dotnet@v5` reading `global.json` in + every job. Triggers stay as they are; no Docker steps. Test: PR checks green on all three OSes. +- [ ] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net10.0; 1.x stays + available for `netstandard2.0` and `net6.0`), AGENTS.md (central package management, xUnit v3), + this plan's status. The README badge moves to 2.0.0 after the release, as a `docs(readme)` commit. ## Verification - [ ] `dotnet build src/Appy.Parsing.sln -c Release -warnaserror`: 0 warnings, 0 errors. - [ ] `dotnet test src/Appy.Parsing.sln`: 14 passed on net10.0 (4 facts, 10 theory cases). - [ ] `dotnet cake` (Default target) is green, and `.artifacts/Appy.Parsing.2.0.0-preview.0.N.nupkg` - holds `lib/net8.0`, `lib/net9.0` and `lib/net10.0` only. + holds `lib/net8.0` and `lib/net10.0` only. - [ ] Package validation runs on pack; the suppression file lists only the two PKV006 entries. +- [ ] No `net6.0`, `net9.0` or `netstandard2.0` left outside the suppression file and the docs that + explain the change. - [ ] No `.cs` change under `src/Appy.Parsing/`, so the public API is unchanged. - [ ] Nothing is published or tagged from a local machine. - [ ] Done when: the PR is merged, a maintainer tags `2.0.0`, the publish workflow is green, and - nuget.org lists Appy.Parsing 2.0.0 for net8.0, net9.0 and net10.0. Merging also publishes a + nuget.org lists Appy.Parsing 2.0.0 for net8.0 and net10.0. Merging also publishes a `2.0.0-preview.0.N` package first; that is expected. ## Key Files ``` -global.json # SDK 10, Traversal SDK pin -src/Directory.Build.props # package metadata, validation settings -src/Directory.Build.targets # MinVer settings -src/Directory.Packages.props # (new) central package versions -src/build.csproj # (new) Traversal build -src/Appy.Parsing/Appy.Parsing.csproj # library TFMs +global.json # SDK 10, Traversal SDK pin +src/Directory.Build.props # package metadata, validation settings +src/Directory.Build.targets # MinVer settings +src/Directory.Packages.props # (new) central package versions +src/build.csproj # (new) Traversal build +src/Appy.Parsing/Appy.Parsing.csproj # library TFMs src/Appy.Parsing/CompatibilitySuppressions.xml # (new) PKV006 for dropped TFMs src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj # test TFM, xUnit v3 -build.cake, dotnet-tools.json # Cake 6, MinVer 8 -.github/workflows/ci.yaml, publish.yaml # action versions, SDK setup -README.md, AGENTS.md # supported frameworks, conventions +build.cake, dotnet-tools.json # Cake 6, MinVer +.github/workflows/ci.yaml, publish.yaml # action versions, SDK setup +README.md, AGENTS.md # supported frameworks, conventions ``` From 0d88442654d4f6cb252df390d9385ad806be6ff0 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 14:50:26 +0100 Subject: [PATCH 04/19] feat(dotnet)!: target net10.0 and net8.0 --- docs/plans/001-net10-migration.md | 2 +- global.json | 5 ++--- src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj | 2 +- src/Appy.Parsing/Appy.Parsing.csproj | 16 +--------------- src/Directory.Build.props | 4 +--- 5 files changed, 6 insertions(+), 23 deletions(-) diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 27f7bda..6e2d6f3 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -28,7 +28,7 @@ made this move. No public API or behaviour change is intended; only the supporte Each task is one commit. The `!` marks the breaking change. -- [ ] 1. `feat(dotnet)!: target net10.0 and net8.0`: `global.json` SDK `10.0.100` with +- [x] 1. `feat(dotnet)!: target net10.0 and net8.0`: `global.json` SDK `10.0.100` with `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0`; remove the `Nullable` package, the `Microsoft.NETCore.App.Ref` download and the annotator properties; `PackageTags` to `NET10;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. diff --git a/global.json b/global.json index 264dc52..f72210c 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,6 @@ { - "projects": [ "src" ], "sdk": { - "version": "6.0.300", - "rollForward": "latestPatch" + "version": "10.0.100", + "rollForward": "latestFeature" } } \ No newline at end of file diff --git a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj index 4fbaf93..07eca1e 100644 --- a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj +++ b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net10.0 false latest diff --git a/src/Appy.Parsing/Appy.Parsing.csproj b/src/Appy.Parsing/Appy.Parsing.csproj index f232fa6..ac92565 100644 --- a/src/Appy.Parsing/Appy.Parsing.csproj +++ b/src/Appy.Parsing/Appy.Parsing.csproj @@ -1,26 +1,12 @@  - net6.0;netstandard2.0 + net10.0;net8.0 Library - latest - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - 3.0.0 - False - - \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 3bf5c94..290b4e5 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -24,7 +24,7 @@ https://github.com/YellowLineParking/Appy.Parsing MIT https://github.com/YellowLineParking/Appy.Parsing/releases - NET6;NETCore + NET10;NET8;parsing;lexer @@ -43,8 +43,6 @@ - 1.0.0-alpha.160 - 1.2.1 2.4.18 From 4114020e47fe13d175a20aa925c17a1166c92b19 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 14:56:48 +0100 Subject: [PATCH 05/19] chore(deps): adopt central package management and upgrade packages --- docs/plans/001-net10-migration.md | 2 +- .../Appy.Parsing.Tests.csproj | 15 +++++++------ src/Appy.Parsing.Tests/LexerTests.cs | 2 +- src/Directory.Build.props | 21 ++----------------- src/Directory.Packages.props | 15 +++++++++++++ 5 files changed, 26 insertions(+), 29 deletions(-) create mode 100644 src/Directory.Packages.props diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 6e2d6f3..986032e 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -32,7 +32,7 @@ Each task is one commit. The `!` marks the breaking change. `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0`; remove the `Nullable` package, the `Microsoft.NETCore.App.Ref` download and the annotator properties; `PackageTags` to `NET10;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. -- [ ] 2. `chore(deps): adopt central package management and upgrade packages`: add +- [x] 2. `chore(deps): adopt central package management and upgrade packages`: add `src/Directory.Packages.props`, move all versions out of `Directory.Build.props` and the csproj files, drop `Moq` and `Microsoft.SourceLink.GitHub`. Versions: Microsoft.NET.Test.Sdk 18.10.1, FluentAssertions 7.2.2, NodaTime 3.3.5, GitHubActionsTestLogger 3.0.5, XunitXml.TestLogger 8.0.0, diff --git a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj index 07eca1e..45cf750 100644 --- a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj +++ b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj @@ -7,17 +7,16 @@ - - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/src/Appy.Parsing.Tests/LexerTests.cs b/src/Appy.Parsing.Tests/LexerTests.cs index 45b51da..1dbfc77 100644 --- a/src/Appy.Parsing.Tests/LexerTests.cs +++ b/src/Appy.Parsing.Tests/LexerTests.cs @@ -24,6 +24,6 @@ public LexerTests() => [Fact] public void ParsesTokens() => _subject.Tokenize("9 * 6 / 3 - 2") - .Should().BeEquivalentTo(9, new MultiToken(), 6, new DivideToken(), 3, new MinusToken(), 2); + .Should().BeEquivalentTo(new object[] { 9, new MultiToken(), 6, new DivideToken(), 3, new MinusToken(), 2 }); } } \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 290b4e5..cdc2e0d 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -28,7 +28,7 @@ - 1571;1572;1573;1574;1591 + 1571;1572;1573;1574;1591;NU1507 @@ -38,24 +38,7 @@ - - + - - 2.4.18 - - - - 0.1.0 - 17.0.0 - 5.10.3 - 4.14.6 - 2.4.1 - 2.4.3 - 1.3.0 - 2.1.26 - 1.1.2 - - diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props new file mode 100644 index 0000000..ee006ab --- /dev/null +++ b/src/Directory.Packages.props @@ -0,0 +1,15 @@ + + + true + + + + + + + + + + + + From e5629fcd028632785d8267013d401fa84ea5cb26 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 15:14:02 +0100 Subject: [PATCH 06/19] test: migrate tests to xUnit v3 --- docs/plans/001-net10-migration.md | 11 +++++++---- src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj | 5 ++--- src/Directory.Packages.props | 7 +++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 986032e..9258bb2 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -35,11 +35,14 @@ Each task is one commit. The `!` marks the breaking change. - [x] 2. `chore(deps): adopt central package management and upgrade packages`: add `src/Directory.Packages.props`, move all versions out of `Directory.Build.props` and the csproj files, drop `Moq` and `Microsoft.SourceLink.GitHub`. Versions: Microsoft.NET.Test.Sdk 18.10.1, - FluentAssertions 7.2.2, NodaTime 3.3.5, GitHubActionsTestLogger 3.0.5, XunitXml.TestLogger 8.0.0, - MinVer 2.3.0. Test: build with `-warnaserror`, 14 tests pass. -- [ ] 3. `test: migrate tests to xUnit v3`: `xunit` to `xunit.v3` 3.2.2, + FluentAssertions 7.2.2, NodaTime 3.3.5, GitHubActionsTestLogger 3.0.5 (2.4.1 in task 3), + XunitXml.TestLogger 8.0.0 (dropped in task 3), MinVer 2.3.0. Test: build with `-warnaserror`, + 14 tests pass. +- [x] 3. `test: migrate tests to xUnit v3`: `xunit` to `xunit.v3` 3.2.2, `xunit.runner.visualstudio` 3.1.5, `OutputType` `Exe`, per the xUnit v3 migration guide. Test: - 14 tests discovered and passing (a count of 0 is a failure). + 14 tests discovered and passing (a count of 0 is a failure). GitHubActionsTestLogger goes to 2.4.1 + and XunitXml.TestLogger is dropped: their newer versions need Microsoft.Testing.Platform 2, which + xunit.v3 3.2.2 does not use. - [ ] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the reference without the Docker tasks (Cake 6 `DotNet*` API, Traversal support); add `src/build.csproj` (Microsoft.Build.Traversal 4.1.82, pinned in `global.json`); `dotnet-tools.json` cake.tool 6.3.0, diff --git a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj index 45cf750..bdf7a8e 100644 --- a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj +++ b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj @@ -2,20 +2,19 @@ net10.0 + Exe false - latest - + all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index ee006ab..14b5a69 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -7,9 +7,8 @@ - - - - + + + From df6cb0abb4849ffe83b5f90f114785a5a4589925 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 15:19:50 +0100 Subject: [PATCH 07/19] chore(build): align cake build and versioning with .NET 10 --- build.cake | 70 +++++++++++++++++++++++++++---- docs/plans/001-net10-migration.md | 2 +- dotnet-tools.json | 6 +-- global.json | 3 ++ src/Directory.Build.targets | 1 + src/build.csproj | 5 +++ 6 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 src/build.csproj diff --git a/build.cake b/build.cake index 83e0e3c..2760c05 100644 --- a/build.cake +++ b/build.cake @@ -1,7 +1,7 @@ -#addin nuget:?package=YamlDotNet&version=8.1.2 +#addin nuget:?package=YamlDotNet&version=16.2.0 #addin nuget:?package=System.Xml.XDocument&version=4.3.0 -#addin nuget:?package=Cake.MinVer&version=2.0.0 -#addin nuget:?package=Cake.Yaml&version=3.1.1 +#addin nuget:?package=Cake.MinVer&version=4.0.0 +#addin nuget:?package=Cake.Yaml&version=6.0.0 #load "./functions.cake" @@ -11,9 +11,11 @@ var artifactsPath = Context.Directory("./.artifacts"); var target = Argument("target", "Default"); var configuration = Argument("configuration", "Release"); var configFilePath = "config.yml"; +var transversalBuildFilePath = $"{basePath}/build.csproj"; var taskConfigManager = new ProjectTaskConfigurationManager(); var projectDescriptors = ProjectLoader.Load(Context, configFilePath, basePath, configuration).Projects; var version = MinVer(settings => settings + .WithMinimumMajorMinor("2.0") .WithDefaultPreReleasePhase("preview") .WithVerbosity(MinVerVerbosity.Info)); @@ -38,10 +40,15 @@ Task("Clean") Task("Restore") .Does(() => { + if (FileExists(transversalBuildFilePath)) + { + return; + } + DotNetRestore(basePath, new DotNetRestoreSettings { - Verbosity = DotNetCoreVerbosity.Minimal + Verbosity = DotNetVerbosity.Minimal }); }); @@ -49,6 +56,20 @@ Task("Build-Project") .IsDependentOn("Restore") .Does(context => { + if (FileExists(transversalBuildFilePath)) + { + context.Information("Building projects using Transversal Build"); + + DotNetBuild(transversalBuildFilePath, new DotNetBuildSettings { + Configuration = configuration, + Verbosity = DotNetVerbosity.Minimal, + MSBuildSettings = new DotNetMSBuildSettings() + .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) + }); + + return; + } + foreach(var projectDescriptor in projectDescriptors) { if (!taskConfigManager.CanBuild(projectDescriptor.Config)) continue; @@ -59,7 +80,7 @@ Task("Build-Project") Configuration = configuration, NoRestore = true, NoIncremental = context.HasArgument("rebuild"), - MSBuildSettings = new DotNetCoreMSBuildSettings() + MSBuildSettings = new DotNetMSBuildSettings() .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) }); } @@ -69,6 +90,24 @@ Task("Test") .IsDependentOn("Build-Project") .Does(context => { + if (FileExists(transversalBuildFilePath)) + { + context.Information("Testing projects using Transversal Build"); + + DotNetTest(transversalBuildFilePath, new DotNetTestSettings { + Configuration = configuration, + NoRestore = true, + NoBuild = true, + TestAdapterPath = ".", + Loggers = new string[] { + "GitHubActions;report-warnings=false" + }, + Verbosity = DotNetVerbosity.Quiet + }); + + return; + } + foreach(var projectDescriptor in projectDescriptors) { if (!taskConfigManager.CanTest(projectDescriptor.Config)) continue; @@ -81,7 +120,6 @@ Task("Test") NoBuild = true, TestAdapterPath = ".", Loggers = new string[] { - // $"xunit;LogFilePath={MakeAbsolute(artifactsPath).FullPath}/xunit-{projectDescriptor.Config.Name}.xml", "GitHubActions;report-warnings=false" }, Verbosity = DotNetVerbosity.Quiet @@ -93,6 +131,22 @@ Task("Package") .IsDependentOn("Test") .Does(context => { + if (FileExists(transversalBuildFilePath)) + { + context.Information("Packing projects using Transversal Build"); + + context.DotNetPack(transversalBuildFilePath, new DotNetPackSettings { + Configuration = configuration, + NoRestore = true, + NoBuild = true, + OutputDirectory = artifactsPath, + MSBuildSettings = new DotNetMSBuildSettings() + .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) + }); + + return; + } + foreach(var projectDescriptor in projectDescriptors) { if (!taskConfigManager.CanPack(projectDescriptor.Config)) continue; @@ -104,7 +158,7 @@ Task("Package") NoRestore = true, NoBuild = true, OutputDirectory = artifactsPath, - MSBuildSettings = new DotNetCoreMSBuildSettings() + MSBuildSettings = new DotNetMSBuildSettings() .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) }); } @@ -163,7 +217,7 @@ Task("Publish-Package-NuGet") context.Information("Publishing {0} to Nuget", nugetPkgFilePath); - DotNetCoreNuGetPush(nugetPkgFilePath, new DotNetCoreNuGetPushSettings + DotNetNuGetPush(nugetPkgFilePath, new DotNetNuGetPushSettings { Source = "https://api.nuget.org/v3/index.json", ApiKey = apiKey, diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 9258bb2..3dbe755 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -43,7 +43,7 @@ Each task is one commit. The `!` marks the breaking change. 14 tests discovered and passing (a count of 0 is a failure). GitHubActionsTestLogger goes to 2.4.1 and XunitXml.TestLogger is dropped: their newer versions need Microsoft.Testing.Platform 2, which xunit.v3 3.2.2 does not use. -- [ ] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the +- [x] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the reference without the Docker tasks (Cake 6 `DotNet*` API, Traversal support); add `src/build.csproj` (Microsoft.Build.Traversal 4.1.82, pinned in `global.json`); `dotnet-tools.json` cake.tool 6.3.0, minver-cli 2.3.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as diff --git a/dotnet-tools.json b/dotnet-tools.json index d3de183..507eff5 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -3,19 +3,19 @@ "isRoot": true, "tools": { "cake.tool": { - "version": "2.2.0", + "version": "6.3.0", "commands": [ "dotnet-cake" ] }, "minver-cli": { - "version": "4.1.0", + "version": "2.3.0", "commands": [ "minver" ] }, "gpr": { - "version": "0.1.281", + "version": "0.1.294", "commands": [ "gpr" ] diff --git a/global.json b/global.json index f72210c..866c081 100644 --- a/global.json +++ b/global.json @@ -2,5 +2,8 @@ "sdk": { "version": "10.0.100", "rollForward": "latestFeature" + }, + "msbuild-sdks": { + "Microsoft.Build.Traversal": "4.1.82" } } \ No newline at end of file diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 4b6ff93..4ae68d8 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,6 +1,7 @@ + 2.0 preview normal diff --git a/src/build.csproj b/src/build.csproj new file mode 100644 index 0000000..101d66b --- /dev/null +++ b/src/build.csproj @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From 8b93395f639c735744825117b534fb36138985b3 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 15:28:30 +0100 Subject: [PATCH 08/19] feat(packages): enable package validation against 1.1.0 --- docs/plans/001-net10-migration.md | 2 +- src/Appy.Parsing/CompatibilitySuppressions.xml | 12 ++++++++++++ src/Directory.Build.targets | 9 +++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/Appy.Parsing/CompatibilitySuppressions.xml diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 3dbe755..ee41b7b 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -50,7 +50,7 @@ Each task is one commit. The `!` marks the breaking change. the reference). `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets` and `WithMinimumMajorMinor("2.0")` in `build.cake`. Test: `dotnet cake` prints the same version as the `.nupkg` file name. -- [ ] 5. `feat(packages): enable package validation against 1.1.0`: `EnablePackageValidation`, +- [x] 5. `feat(packages): enable package validation against 1.1.0`: `EnablePackageValidation`, `PackageValidationBaselineVersion=1.1.0`, and a generated `CompatibilitySuppressions.xml` with only PKV006 for `net6.0` and `netstandard2.0`. Test: pack fails before the suppression file (red) and passes with it (green). diff --git a/src/Appy.Parsing/CompatibilitySuppressions.xml b/src/Appy.Parsing/CompatibilitySuppressions.xml new file mode 100644 index 0000000..2b52f50 --- /dev/null +++ b/src/Appy.Parsing/CompatibilitySuppressions.xml @@ -0,0 +1,12 @@ + + + + + PKV006 + .NETStandard,Version=v2.0 + + + PKV006 + net6.0 + + \ No newline at end of file diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 4ae68d8..162beda 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,4 +1,13 @@ + + true + 1.1.0 + + + + + 2.0 From 1ea986ae93dca45623891eaaaf618e919b7264ec Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 15:33:37 +0100 Subject: [PATCH 09/19] ci: update GitHub Actions for .NET 10 --- .github/workflows/ci.yaml | 20 ++++++++------------ .github/workflows/publish.yaml | 10 ++++------ docs/plans/001-net10-migration.md | 2 +- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6db2219..d4b9188 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,21 +14,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Cache packages - uses: actions/cache@v2 + uses: actions/cache@v5 with: path: ${{ env.NUGET_PACKAGES }} key: ${{ runner.os }}-nuget-${{ hashFiles('.config/dotnet-tools.json', '**/packages.lock.json') }} restore-keys: ${{ runner.os }}-nuget- - - name: Setup .NET 6.x - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.300 + - name: Setup .NET SDK (global.json) + uses: actions/setup-dotnet@v5 - name: Integration Tests shell: bash @@ -55,21 +53,19 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Cache packages - uses: actions/cache@v2 + uses: actions/cache@v5 with: path: ${{ env.NUGET_PACKAGES }} key: ${{ runner.os }}-nuget-${{ hashFiles('.config/dotnet-tools.json', '**/packages.lock.json') }} restore-keys: ${{ runner.os }}-nuget- - - name: Setup .NET 6.x - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.300 + - name: Setup .NET SDK (global.json) + uses: actions/setup-dotnet@v5 - name: Integration Tests shell: bash diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index e6b2d78..482be12 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -21,21 +21,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Cache packages - uses: actions/cache@v2 + uses: actions/cache@v5 with: path: ${{ env.NUGET_PACKAGES }} key: ${{ runner.os }}-nuget-${{ hashFiles('.config/dotnet-tools.json', '**/packages.lock.json') }} restore-keys: ${{ runner.os }}-nuget- - - name: Setup .NET 6.x - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 6.0.300 + - name: Setup .NET SDK (global.json) + uses: actions/setup-dotnet@v5 - name: Publish shell: bash diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index ee41b7b..f6143aa 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -54,7 +54,7 @@ Each task is one commit. The `!` marks the breaking change. `PackageValidationBaselineVersion=1.1.0`, and a generated `CompatibilitySuppressions.xml` with only PKV006 for `net6.0` and `netstandard2.0`. Test: pack fails before the suppression file (red) and passes with it (green). -- [ ] 6. `ci: update GitHub Actions for .NET 10`: `ci.yaml` and `publish.yaml` as the reference: +- [x] 6. `ci: update GitHub Actions for .NET 10`: `ci.yaml` and `publish.yaml` as the reference: `actions/checkout@v6`, `actions/cache@v5`, `actions/setup-dotnet@v5` reading `global.json` in every job. Triggers stay as they are; no Docker steps. Test: PR checks green on all three OSes. - [ ] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net10.0; 1.x stays From 863b0caf7baf5c6d5ad23bdd2a059685aa35b51f Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 15:39:40 +0100 Subject: [PATCH 10/19] docs: update docs for .NET 10 --- AGENTS.md | 28 ++++++++++++++++++++++------ README.md | 7 +++++++ docs/plans/001-net10-migration.md | 6 +++--- 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e1aa278..e873050 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,17 +19,24 @@ dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" ``` - The cake build treats warnings as errors. -- `config.yml` lists the projects cake builds and their role (`Package` or `Test`). A new - project not listed there is skipped by the build. +- Cake builds, tests and packs through the Traversal project `src/build.csproj`, which picks up + every project under `src/`. `config.yml` lists the projects and their role (`Package` or + `Test`); the publish targets push only the `Package` projects. +- Package versions live in `src/Directory.Packages.props` (central package management); a + `PackageReference` in a csproj carries no `Version`. - Never run the `Publish` cake target or `dotnet nuget push` locally; CI publishes. ## Structure | Path | Purpose | |------|---------| -| `src/Appy.Parsing/` | The library: `Builder/`, `Lexers/`, `Parsers/` | -| `src/Appy.Parsing.Tests/` | xUnit tests | -| `src/Directory.Build.*` | Shared build settings, package metadata, MinVer settings | +| `src/Appy.Parsing/` | The library (`net10.0;net8.0`): `Builder/`, `Lexers/`, `Parsers/` | +| `src/Appy.Parsing.Tests/` | xUnit v3 tests (`net10.0`) | +| `src/Directory.Build.props` | Shared build settings, package metadata | +| `src/Directory.Build.targets` | MinVer and package validation settings | +| `src/Directory.Packages.props` | Package versions | +| `src/build.csproj` | Traversal project the cake build runs | +| `global.json` | .NET 10 SDK and Traversal SDK versions | | `build.cake`, `functions.cake`, `config.yml` | Cake build | | `.github/workflows/` | `ci.yaml` on pull requests, `publish.yaml` on push to `master` or a tag | | `docs/` | Architecture and plans | @@ -38,13 +45,22 @@ dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" - [MinVer](https://github.com/adamralph/minver) derives the version from git tags (`MAJOR.MINOR.PATCH`, no `v` prefix). Untagged commits get a `-preview.0.N` suffix. +- The MinVer minimum major.minor (`2.0`) is set in both `src/Directory.Build.targets` and + `build.cake`; keep them in sync. +- Pack runs package validation against the last release: `PackageValidationBaselineVersion` in + `src/Directory.Build.targets`, suppressions in `src/Appy.Parsing/CompatibilitySuppressions.xml`. + After each release, move the baseline to that version and drop suppressions that no longer + apply. - A push to `master` that touches `src/` publishes a preview package; a tag publishes that version. Do not create tags or releases unless a maintainer asks. - Dropping a target framework or public API is a breaking change: call it out in the PR. ## Tests -- xUnit with FluentAssertions. Tests build real lexers and parsers through the builders; no mocks. +- xUnit v3 (`xunit.v3` 3.2.2, `xunit.runner.visualstudio` 3.1.5, run through VSTest, + `GitHubActionsTestLogger` 2.4.1) with FluentAssertions 7. Stay on FluentAssertions 7: 8 has a + commercial licence. +- Tests build real lexers and parsers through the builders; no mocks. - Add or update a test with every behaviour change, and write it first. ## Code Style diff --git a/README.md b/README.md index cd19b57..341d1b2 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,16 @@ It also has a number of Builders that allow you to easily define a grammar and b ## Table of Contents +- [Supported frameworks](#supported-frameworks) - [Installing](#installing) - [Usage](#usage) +## Supported frameworks + +Appy.Parsing targets `net10.0` and `net8.0`. + +Version 2.0 drops `net6.0` and `netstandard2.0`, so it no longer runs on .NET Framework. Projects on those frameworks can stay on [1.1.0](https://www.nuget.org/packages/Appy.Parsing/1.1.0). + ## Installing Install using the [Appy.Parsing NuGet package](https://www.nuget.org/packages/Appy.Parsing): diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index f6143aa..2bcd0eb 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -57,7 +57,7 @@ Each task is one commit. The `!` marks the breaking change. - [x] 6. `ci: update GitHub Actions for .NET 10`: `ci.yaml` and `publish.yaml` as the reference: `actions/checkout@v6`, `actions/cache@v5`, `actions/setup-dotnet@v5` reading `global.json` in every job. Triggers stay as they are; no Docker steps. Test: PR checks green on all three OSes. -- [ ] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net10.0; 1.x stays +- [x] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net10.0; 1.x stays available for `netstandard2.0` and `net6.0`), AGENTS.md (central package management, xUnit v3), this plan's status. The README badge moves to 2.0.0 after the release, as a `docs(readme)` commit. @@ -80,8 +80,8 @@ Each task is one commit. The `!` marks the breaking change. ``` global.json # SDK 10, Traversal SDK pin -src/Directory.Build.props # package metadata, validation settings -src/Directory.Build.targets # MinVer settings +src/Directory.Build.props # package metadata +src/Directory.Build.targets # MinVer and package validation settings src/Directory.Packages.props # (new) central package versions src/build.csproj # (new) Traversal build src/Appy.Parsing/Appy.Parsing.csproj # library TFMs From e692f33dd7716f84486d2f21963ea587c0cb9f66 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 15:42:50 +0100 Subject: [PATCH 11/19] docs(plan): record local verification --- docs/plans/001-net10-migration.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 2bcd0eb..1b93fa5 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -63,15 +63,15 @@ Each task is one commit. The `!` marks the breaking change. ## Verification -- [ ] `dotnet build src/Appy.Parsing.sln -c Release -warnaserror`: 0 warnings, 0 errors. -- [ ] `dotnet test src/Appy.Parsing.sln`: 14 passed on net10.0 (4 facts, 10 theory cases). -- [ ] `dotnet cake` (Default target) is green, and `.artifacts/Appy.Parsing.2.0.0-preview.0.N.nupkg` +- [x] `dotnet build src/Appy.Parsing.sln -c Release -warnaserror`: 0 warnings, 0 errors. +- [x] `dotnet test src/Appy.Parsing.sln`: 14 passed on net10.0 (4 facts, 10 theory cases). +- [x] `dotnet cake` (Default target) is green, and `.artifacts/Appy.Parsing.2.0.0-preview.0.N.nupkg` holds `lib/net8.0` and `lib/net10.0` only. -- [ ] Package validation runs on pack; the suppression file lists only the two PKV006 entries. -- [ ] No `net6.0`, `net9.0` or `netstandard2.0` left outside the suppression file and the docs that +- [x] Package validation runs on pack; the suppression file lists only the two PKV006 entries. +- [x] No `net6.0`, `net9.0` or `netstandard2.0` left outside the suppression file and the docs that explain the change. -- [ ] No `.cs` change under `src/Appy.Parsing/`, so the public API is unchanged. -- [ ] Nothing is published or tagged from a local machine. +- [x] No `.cs` change under `src/Appy.Parsing/`, so the public API is unchanged. +- [x] Nothing is published or tagged from a local machine. - [ ] Done when: the PR is merged, a maintainer tags `2.0.0`, the publish workflow is green, and nuget.org lists Appy.Parsing 2.0.0 for net8.0 and net10.0. Merging also publishes a `2.0.0-preview.0.N` package first; that is expected. From 2778942624124b7aa9f40284e85ba8e835fe657d Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 17:23:31 +0100 Subject: [PATCH 12/19] chore(build): drop traversal build, keep config.yml --- AGENTS.md | 8 ++--- build.cake | 54 ------------------------------- docs/plans/001-net10-migration.md | 9 +++--- global.json | 3 -- src/Directory.Build.targets | 2 +- src/build.csproj | 5 --- 6 files changed, 8 insertions(+), 73 deletions(-) delete mode 100644 src/build.csproj diff --git a/AGENTS.md b/AGENTS.md index e873050..0c773df 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,9 +19,8 @@ dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" ``` - The cake build treats warnings as errors. -- Cake builds, tests and packs through the Traversal project `src/build.csproj`, which picks up - every project under `src/`. `config.yml` lists the projects and their role (`Package` or - `Test`); the publish targets push only the `Package` projects. +- `config.yml` lists the projects cake builds and their role (`Package` or `Test`). A new + project not listed there is skipped by the build. - Package versions live in `src/Directory.Packages.props` (central package management); a `PackageReference` in a csproj carries no `Version`. - Never run the `Publish` cake target or `dotnet nuget push` locally; CI publishes. @@ -35,8 +34,7 @@ dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" | `src/Directory.Build.props` | Shared build settings, package metadata | | `src/Directory.Build.targets` | MinVer and package validation settings | | `src/Directory.Packages.props` | Package versions | -| `src/build.csproj` | Traversal project the cake build runs | -| `global.json` | .NET 10 SDK and Traversal SDK versions | +| `global.json` | .NET 10 SDK version | | `build.cake`, `functions.cake`, `config.yml` | Cake build | | `.github/workflows/` | `ci.yaml` on pull requests, `publish.yaml` on push to `master` or a tag | | `docs/` | Architecture and plans | diff --git a/build.cake b/build.cake index 2760c05..692f987 100644 --- a/build.cake +++ b/build.cake @@ -11,7 +11,6 @@ var artifactsPath = Context.Directory("./.artifacts"); var target = Argument("target", "Default"); var configuration = Argument("configuration", "Release"); var configFilePath = "config.yml"; -var transversalBuildFilePath = $"{basePath}/build.csproj"; var taskConfigManager = new ProjectTaskConfigurationManager(); var projectDescriptors = ProjectLoader.Load(Context, configFilePath, basePath, configuration).Projects; var version = MinVer(settings => settings @@ -40,11 +39,6 @@ Task("Clean") Task("Restore") .Does(() => { - if (FileExists(transversalBuildFilePath)) - { - return; - } - DotNetRestore(basePath, new DotNetRestoreSettings { @@ -56,20 +50,6 @@ Task("Build-Project") .IsDependentOn("Restore") .Does(context => { - if (FileExists(transversalBuildFilePath)) - { - context.Information("Building projects using Transversal Build"); - - DotNetBuild(transversalBuildFilePath, new DotNetBuildSettings { - Configuration = configuration, - Verbosity = DotNetVerbosity.Minimal, - MSBuildSettings = new DotNetMSBuildSettings() - .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) - }); - - return; - } - foreach(var projectDescriptor in projectDescriptors) { if (!taskConfigManager.CanBuild(projectDescriptor.Config)) continue; @@ -90,24 +70,6 @@ Task("Test") .IsDependentOn("Build-Project") .Does(context => { - if (FileExists(transversalBuildFilePath)) - { - context.Information("Testing projects using Transversal Build"); - - DotNetTest(transversalBuildFilePath, new DotNetTestSettings { - Configuration = configuration, - NoRestore = true, - NoBuild = true, - TestAdapterPath = ".", - Loggers = new string[] { - "GitHubActions;report-warnings=false" - }, - Verbosity = DotNetVerbosity.Quiet - }); - - return; - } - foreach(var projectDescriptor in projectDescriptors) { if (!taskConfigManager.CanTest(projectDescriptor.Config)) continue; @@ -131,22 +93,6 @@ Task("Package") .IsDependentOn("Test") .Does(context => { - if (FileExists(transversalBuildFilePath)) - { - context.Information("Packing projects using Transversal Build"); - - context.DotNetPack(transversalBuildFilePath, new DotNetPackSettings { - Configuration = configuration, - NoRestore = true, - NoBuild = true, - OutputDirectory = artifactsPath, - MSBuildSettings = new DotNetMSBuildSettings() - .TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error) - }); - - return; - } - foreach(var projectDescriptor in projectDescriptors) { if (!taskConfigManager.CanPack(projectDescriptor.Config)) continue; diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 1b93fa5..9f0ba97 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -17,7 +17,7 @@ made this move. No public API or behaviour change is intended; only the supporte | Library `net10.0;net8.0`, tests `net10.0` | net10.0 and net8.0 are the supported LTS releases. net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. The code has no framework-specific paths, so one test TFM covers it. | Also `net9.0`: a short-term release that net8.0 assets already cover. Keep `netstandard2.0`: .NET Framework users can stay on 1.x. | | Release 2.0.0 | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | | MinVer as the reference (2.3.0, package and CLI), phase `preview`, minimum major.minor `2.0` | One versioning setup across both repos. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | MinVer 8: needs a workaround in `build.cake` because Cake.MinVer only exposes the phase option that MinVer 8 rejects. | -| Central package management, Traversal build, `.sln` kept | Same layout as the reference repo. | `.slnx`: the reference still uses `.sln`. | +| Central package management, `.sln` kept, no Traversal build | Cake builds the projects listed in `config.yml`, as before. | Traversal build as the reference: deferred. `.slnx`: the reference still uses `.sln`. | | xUnit v3 3.2.2 with `xunit.runner.visualstudio` 3.1.5, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode; 3.2.2 matches the sibling repos. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v3 4.x: newer, not yet used alongside. xUnit v2 as the reference: leaves a migration for later. | | CI installs only the .NET 10 SDK (from `global.json`) | The SDK builds both TFMs; tests run on net10.0 only. | Install 8/9/10 as the reference: unused runtimes. | | Package validation against 1.1.0 | Guards the API from this release on. The only expected findings are the two dropped TFMs (PKV006), suppressed explicitly. | None (the reference has none): a TFM or API drop could ship silently. | @@ -44,8 +44,8 @@ Each task is one commit. The `!` marks the breaking change. and XunitXml.TestLogger is dropped: their newer versions need Microsoft.Testing.Platform 2, which xunit.v3 3.2.2 does not use. - [x] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the - reference without the Docker tasks (Cake 6 `DotNet*` API, Traversal support); add `src/build.csproj` - (Microsoft.Build.Traversal 4.1.82, pinned in `global.json`); `dotnet-tools.json` cake.tool 6.3.0, + reference without the Docker tasks (Cake 6 `DotNet*` API; projects still come from `config.yml`, + no Traversal build); `dotnet-tools.json` cake.tool 6.3.0, minver-cli 2.3.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as the reference). `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets` and `WithMinimumMajorMinor("2.0")` in `build.cake`. Test: `dotnet cake` prints the same version as the @@ -79,11 +79,10 @@ Each task is one commit. The `!` marks the breaking change. ## Key Files ``` -global.json # SDK 10, Traversal SDK pin +global.json # SDK 10 src/Directory.Build.props # package metadata src/Directory.Build.targets # MinVer and package validation settings src/Directory.Packages.props # (new) central package versions -src/build.csproj # (new) Traversal build src/Appy.Parsing/Appy.Parsing.csproj # library TFMs src/Appy.Parsing/CompatibilitySuppressions.xml # (new) PKV006 for dropped TFMs src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj # test TFM, xUnit v3 diff --git a/global.json b/global.json index 866c081..f72210c 100644 --- a/global.json +++ b/global.json @@ -2,8 +2,5 @@ "sdk": { "version": "10.0.100", "rollForward": "latestFeature" - }, - "msbuild-sdks": { - "Microsoft.Build.Traversal": "4.1.82" } } \ No newline at end of file diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 162beda..d3d5eaf 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -1,5 +1,5 @@ - + true 1.1.0 diff --git a/src/build.csproj b/src/build.csproj deleted file mode 100644 index 101d66b..0000000 --- a/src/build.csproj +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From 198fb347607ed2879c20304ba6d2056f03063053 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Wed, 30 Sep 2026 17:46:36 +0100 Subject: [PATCH 13/19] chore(build): migrate the solution to slnx --- .editorconfig | 4 ++-- .gitignore | 2 -- AGENTS.md | 4 ++-- CLAUDE.md | 2 +- docs/plans/001-net10-migration.md | 7 +++--- src/Appy.Parsing.sln | 39 ------------------------------- src/Appy.Parsing.slnx | 10 ++++++++ 7 files changed, 19 insertions(+), 49 deletions(-) delete mode 100644 src/Appy.Parsing.sln create mode 100644 src/Appy.Parsing.slnx diff --git a/.editorconfig b/.editorconfig index 380d16d..49a4fb8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,8 +8,8 @@ indent_size = 4 insert_final_newline = false trim_trailing_whitespace = true -[*.sln] -indent_style = tab +[*.slnx] +indent_size = 2 [*.{csproj,vbproj,vcxproj,vcxproj.filters}] indent_size = 2 diff --git a/.gitignore b/.gitignore index 286d5f7..4d0e373 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ dotnet-install.sh* .vs/ .vscode/ launchSettings.json -*.sln.ide/ # Rider src/.idea/**/workspace.xml @@ -41,7 +40,6 @@ src/.idea/**/uiDesigner.xml # User-specific files *.suo *.user -*.sln.docstates *.userprefs *.GhostDoc.xml *StyleCop.Cache diff --git a/AGENTS.md b/AGENTS.md index 0c773df..94b9210 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,8 +14,8 @@ fluent builders define the grammar. Usage lives in [README.md](README.md), desig ```bash dotnet tool restore # cake, minver-cli, gpr dotnet cake # Default target: clean, build, test, pack into .artifacts/ -dotnet test src/Appy.Parsing.sln # tests only -dotnet test src/Appy.Parsing.sln --filter "FullyQualifiedName~CalculatorTest" +dotnet test src/Appy.Parsing.slnx # tests only +dotnet test src/Appy.Parsing.slnx --filter "FullyQualifiedName~CalculatorTest" ``` - The cake build treats warnings as errors. diff --git a/CLAUDE.md b/CLAUDE.md index 2c18207..e7d9fe5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ```bash dotnet tool restore dotnet cake # clean, build, test, pack into .artifacts/ -dotnet test src/Appy.Parsing.sln # tests only +dotnet test src/Appy.Parsing.slnx # tests only ``` Never run the `Publish` cake target or `dotnet nuget push`; publishing happens in CI only. diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 9f0ba97..8c166c6 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -17,7 +17,7 @@ made this move. No public API or behaviour change is intended; only the supporte | Library `net10.0;net8.0`, tests `net10.0` | net10.0 and net8.0 are the supported LTS releases. net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. The code has no framework-specific paths, so one test TFM covers it. | Also `net9.0`: a short-term release that net8.0 assets already cover. Keep `netstandard2.0`: .NET Framework users can stay on 1.x. | | Release 2.0.0 | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | | MinVer as the reference (2.3.0, package and CLI), phase `preview`, minimum major.minor `2.0` | One versioning setup across both repos. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | MinVer 8: needs a workaround in `build.cake` because Cake.MinVer only exposes the phase option that MinVer 8 rejects. | -| Central package management, `.sln` kept, no Traversal build | Cake builds the projects listed in `config.yml`, as before. | Traversal build as the reference: deferred. `.slnx`: the reference still uses `.sln`. | +| Central package management, `.slnx`, no Traversal build | `.slnx` is the SDK 10 solution format. Cake builds the projects listed in `config.yml`, as before. | Keep `.sln` as the reference. Traversal build as the reference: deferred. | | xUnit v3 3.2.2 with `xunit.runner.visualstudio` 3.1.5, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode; 3.2.2 matches the sibling repos. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v3 4.x: newer, not yet used alongside. xUnit v2 as the reference: leaves a migration for later. | | CI installs only the .NET 10 SDK (from `global.json`) | The SDK builds both TFMs; tests run on net10.0 only. | Install 8/9/10 as the reference: unused runtimes. | | Package validation against 1.1.0 | Guards the API from this release on. The only expected findings are the two dropped TFMs (PKV006), suppressed explicitly. | None (the reference has none): a TFM or API drop could ship silently. | @@ -63,8 +63,8 @@ Each task is one commit. The `!` marks the breaking change. ## Verification -- [x] `dotnet build src/Appy.Parsing.sln -c Release -warnaserror`: 0 warnings, 0 errors. -- [x] `dotnet test src/Appy.Parsing.sln`: 14 passed on net10.0 (4 facts, 10 theory cases). +- [x] `dotnet build src/Appy.Parsing.slnx -c Release -warnaserror`: 0 warnings, 0 errors. +- [x] `dotnet test src/Appy.Parsing.slnx`: 14 passed on net10.0 (4 facts, 10 theory cases). - [x] `dotnet cake` (Default target) is green, and `.artifacts/Appy.Parsing.2.0.0-preview.0.N.nupkg` holds `lib/net8.0` and `lib/net10.0` only. - [x] Package validation runs on pack; the suppression file lists only the two PKV006 entries. @@ -83,6 +83,7 @@ global.json # SDK 10 src/Directory.Build.props # package metadata src/Directory.Build.targets # MinVer and package validation settings src/Directory.Packages.props # (new) central package versions +src/Appy.Parsing.slnx # (new) solution file (SDK 10 format) src/Appy.Parsing/Appy.Parsing.csproj # library TFMs src/Appy.Parsing/CompatibilitySuppressions.xml # (new) PKV006 for dropped TFMs src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj # test TFM, xUnit v3 diff --git a/src/Appy.Parsing.sln b/src/Appy.Parsing.sln deleted file mode 100644 index 3dc768f..0000000 --- a/src/Appy.Parsing.sln +++ /dev/null @@ -1,39 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2002 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Appy.Parsing", "Appy.Parsing\Appy.Parsing.csproj", "{65291E12-5AE8-4AC6-A28F-F84D0C182B62}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Appy.Parsing.Tests", "Appy.Parsing.Tests\Appy.Parsing.Tests.csproj", "{D536A6AE-BF06-4BD8-860F-0E4A3AD73004}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{FB7DCD2D-E9C1-4773-8B80-BEFF8883A09B}" - ProjectSection(SolutionItems) = preProject - ..\build.cake = ..\build.cake - ..\config.yml = ..\config.yml - ..\functions.cake = ..\functions.cake - ..\global.json = ..\global.json - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {65291E12-5AE8-4AC6-A28F-F84D0C182B62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {65291E12-5AE8-4AC6-A28F-F84D0C182B62}.Debug|Any CPU.Build.0 = Debug|Any CPU - {65291E12-5AE8-4AC6-A28F-F84D0C182B62}.Release|Any CPU.ActiveCfg = Release|Any CPU - {65291E12-5AE8-4AC6-A28F-F84D0C182B62}.Release|Any CPU.Build.0 = Release|Any CPU - {D536A6AE-BF06-4BD8-860F-0E4A3AD73004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D536A6AE-BF06-4BD8-860F-0E4A3AD73004}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D536A6AE-BF06-4BD8-860F-0E4A3AD73004}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D536A6AE-BF06-4BD8-860F-0E4A3AD73004}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {4CA5C51B-B78E-4847-80FD-01A8A26EBAC7} - EndGlobalSection -EndGlobal diff --git a/src/Appy.Parsing.slnx b/src/Appy.Parsing.slnx new file mode 100644 index 0000000..26ca993 --- /dev/null +++ b/src/Appy.Parsing.slnx @@ -0,0 +1,10 @@ + + + + + + + + + + From 4a049aba3e030dacf9ecb8c1915bd7aec3aaf903 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Thu, 1 Oct 2026 10:23:54 +0100 Subject: [PATCH 14/19] chore(build): align cake and SDK pins with the reference --- build.cake | 1 + docs/plans/001-net10-migration.md | 4 ++-- dotnet-tools.json | 2 +- global.json | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build.cake b/build.cake index 692f987..b75657e 100644 --- a/build.cake +++ b/build.cake @@ -82,6 +82,7 @@ Task("Test") NoBuild = true, TestAdapterPath = ".", Loggers = new string[] { + // $"xunit;LogFilePath={MakeAbsolute(artifactsPath).FullPath}/xunit-{projectDescriptor.Config.Name}.xml", "GitHubActions;report-warnings=false" }, Verbosity = DotNetVerbosity.Quiet diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 8c166c6..45f3f5b 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -28,7 +28,7 @@ made this move. No public API or behaviour change is intended; only the supporte Each task is one commit. The `!` marks the breaking change. -- [x] 1. `feat(dotnet)!: target net10.0 and net8.0`: `global.json` SDK `10.0.100` with +- [x] 1. `feat(dotnet)!: target net10.0 and net8.0`: `global.json` SDK `10.0.103` with `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0`; remove the `Nullable` package, the `Microsoft.NETCore.App.Ref` download and the annotator properties; `PackageTags` to `NET10;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. @@ -45,7 +45,7 @@ Each task is one commit. The `!` marks the breaking change. xunit.v3 3.2.2 does not use. - [x] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the reference without the Docker tasks (Cake 6 `DotNet*` API; projects still come from `config.yml`, - no Traversal build); `dotnet-tools.json` cake.tool 6.3.0, + no Traversal build); `dotnet-tools.json` cake.tool 6.0.0, minver-cli 2.3.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as the reference). `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets` and `WithMinimumMajorMinor("2.0")` in `build.cake`. Test: `dotnet cake` prints the same version as the diff --git a/dotnet-tools.json b/dotnet-tools.json index 507eff5..60f01ea 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "cake.tool": { - "version": "6.3.0", + "version": "6.0.0", "commands": [ "dotnet-cake" ] diff --git a/global.json b/global.json index f72210c..d92a294 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.100", + "version": "10.0.103", "rollForward": "latestFeature" } } \ No newline at end of file From ebba147dd121a173c365dd52584792ea46752e13 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Thu, 1 Oct 2026 10:26:27 +0100 Subject: [PATCH 15/19] chore(build): keep cake.tool 6.3.0 --- docs/plans/001-net10-migration.md | 2 +- dotnet-tools.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 45f3f5b..597290d 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -45,7 +45,7 @@ Each task is one commit. The `!` marks the breaking change. xunit.v3 3.2.2 does not use. - [x] 4. `chore(build): align cake build and versioning with .NET 10`: port `build.cake` from the reference without the Docker tasks (Cake 6 `DotNet*` API; projects still come from `config.yml`, - no Traversal build); `dotnet-tools.json` cake.tool 6.0.0, + no Traversal build); `dotnet-tools.json` cake.tool 6.3.0, minver-cli 2.3.0, gpr 0.1.294; addins Cake.MinVer 4.0.0, Cake.Yaml 6.0.0, YamlDotNet 16.2.0 (as the reference). `MinVerMinimumMajorMinor=2.0` in `Directory.Build.targets` and `WithMinimumMajorMinor("2.0")` in `build.cake`. Test: `dotnet cake` prints the same version as the diff --git a/dotnet-tools.json b/dotnet-tools.json index 60f01ea..507eff5 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "cake.tool": { - "version": "6.0.0", + "version": "6.3.0", "commands": [ "dotnet-cake" ] From ccd55f31ba1525dda3db20621928fcfaa7484c89 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Thu, 1 Oct 2026 11:18:06 +0100 Subject: [PATCH 16/19] ci: fix the NuGet cache key paths --- .github/workflows/ci.yaml | 4 ++-- .github/workflows/publish.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d4b9188..a037a62 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -22,7 +22,7 @@ jobs: uses: actions/cache@v5 with: path: ${{ env.NUGET_PACKAGES }} - key: ${{ runner.os }}-nuget-${{ hashFiles('.config/dotnet-tools.json', '**/packages.lock.json') }} + key: ${{ runner.os }}-nuget-${{ hashFiles('dotnet-tools.json', 'src/Directory.Packages.props') }} restore-keys: ${{ runner.os }}-nuget- - name: Setup .NET SDK (global.json) @@ -61,7 +61,7 @@ jobs: uses: actions/cache@v5 with: path: ${{ env.NUGET_PACKAGES }} - key: ${{ runner.os }}-nuget-${{ hashFiles('.config/dotnet-tools.json', '**/packages.lock.json') }} + key: ${{ runner.os }}-nuget-${{ hashFiles('dotnet-tools.json', 'src/Directory.Packages.props') }} restore-keys: ${{ runner.os }}-nuget- - name: Setup .NET SDK (global.json) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 482be12..d8f0aef 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -29,7 +29,7 @@ jobs: uses: actions/cache@v5 with: path: ${{ env.NUGET_PACKAGES }} - key: ${{ runner.os }}-nuget-${{ hashFiles('.config/dotnet-tools.json', '**/packages.lock.json') }} + key: ${{ runner.os }}-nuget-${{ hashFiles('dotnet-tools.json', 'src/Directory.Packages.props') }} restore-keys: ${{ runner.os }}-nuget- - name: Setup .NET SDK (global.json) From 68613aa3e018fc5a0b6b8efc6fdd113ba5a3abe1 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Thu, 1 Oct 2026 11:18:47 +0100 Subject: [PATCH 17/19] test: run the tests on net8.0 too --- .github/workflows/ci.yaml | 10 ++++++++-- .github/workflows/publish.yaml | 5 ++++- AGENTS.md | 2 +- docs/plans/001-net10-migration.md | 8 ++++---- src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj | 2 +- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a037a62..b511f7d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -25,8 +25,11 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('dotnet-tools.json', 'src/Directory.Packages.props') }} restore-keys: ${{ runner.os }}-nuget- - - name: Setup .NET SDK (global.json) + - name: Setup .NET SDK (global.json + .NET 8 for tests) uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + dotnet-version: 8.0.x - name: Integration Tests shell: bash @@ -64,8 +67,11 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('dotnet-tools.json', 'src/Directory.Packages.props') }} restore-keys: ${{ runner.os }}-nuget- - - name: Setup .NET SDK (global.json) + - name: Setup .NET SDK (global.json + .NET 8 for tests) uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + dotnet-version: 8.0.x - name: Integration Tests shell: bash diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index d8f0aef..144de40 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -32,8 +32,11 @@ jobs: key: ${{ runner.os }}-nuget-${{ hashFiles('dotnet-tools.json', 'src/Directory.Packages.props') }} restore-keys: ${{ runner.os }}-nuget- - - name: Setup .NET SDK (global.json) + - name: Setup .NET SDK (global.json + .NET 8 for tests) uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + dotnet-version: 8.0.x - name: Publish shell: bash diff --git a/AGENTS.md b/AGENTS.md index 94b9210..c4aa7db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -30,7 +30,7 @@ dotnet test src/Appy.Parsing.slnx --filter "FullyQualifiedName~CalculatorTest" | Path | Purpose | |------|---------| | `src/Appy.Parsing/` | The library (`net10.0;net8.0`): `Builder/`, `Lexers/`, `Parsers/` | -| `src/Appy.Parsing.Tests/` | xUnit v3 tests (`net10.0`) | +| `src/Appy.Parsing.Tests/` | xUnit v3 tests (`net10.0;net8.0`, one run per library TFM) | | `src/Directory.Build.props` | Shared build settings, package metadata | | `src/Directory.Build.targets` | MinVer and package validation settings | | `src/Directory.Packages.props` | Package versions | diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 597290d..df9dff0 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -6,7 +6,7 @@ ## Summary Move Appy.Parsing from `net6.0;netstandard2.0` to `net10.0;net8.0` on the .NET 10 SDK, with tests -on `net10.0`, and release it as 2.0.0. The build, packages, test stack and GitHub Actions line up +on `net10.0` and `net8.0`, and release it as 2.0.0. The build, packages, test stack and GitHub Actions line up with [Appy.Configuration](https://github.com/YellowLineParking/Appy.Configuration), which already made this move. No public API or behaviour change is intended; only the supported frameworks change. @@ -14,12 +14,12 @@ made this move. No public API or behaviour change is intended; only the supporte | Decision | Context | Alternatives Considered | |----------|---------|------------------------| -| Library `net10.0;net8.0`, tests `net10.0` | net10.0 and net8.0 are the supported LTS releases. net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. The code has no framework-specific paths, so one test TFM covers it. | Also `net9.0`: a short-term release that net8.0 assets already cover. Keep `netstandard2.0`: .NET Framework users can stay on 1.x. | +| Library `net10.0;net8.0`, tests `net10.0;net8.0` | net10.0 and net8.0 are the supported LTS releases. net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. Tests run once per shipped library asset. | Also `net9.0`: a short-term release that net8.0 assets already cover. Keep `netstandard2.0`: .NET Framework users can stay on 1.x. | | Release 2.0.0 | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | | MinVer as the reference (2.3.0, package and CLI), phase `preview`, minimum major.minor `2.0` | One versioning setup across both repos. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | MinVer 8: needs a workaround in `build.cake` because Cake.MinVer only exposes the phase option that MinVer 8 rejects. | | Central package management, `.slnx`, no Traversal build | `.slnx` is the SDK 10 solution format. Cake builds the projects listed in `config.yml`, as before. | Keep `.sln` as the reference. Traversal build as the reference: deferred. | | xUnit v3 3.2.2 with `xunit.runner.visualstudio` 3.1.5, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode; 3.2.2 matches the sibling repos. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v3 4.x: newer, not yet used alongside. xUnit v2 as the reference: leaves a migration for later. | -| CI installs only the .NET 10 SDK (from `global.json`) | The SDK builds both TFMs; tests run on net10.0 only. | Install 8/9/10 as the reference: unused runtimes. | +| CI installs the .NET 10 SDK (from `global.json`) plus .NET 8.0.x | The SDK builds both TFMs; 8.0.x provides the runtime for the net8.0 test run. | Install 8/9/10 as the reference: net9 is unused. | | Package validation against 1.1.0 | Guards the API from this release on. The only expected findings are the two dropped TFMs (PKV006), suppressed explicitly. | None (the reference has none): a TFM or API drop could ship silently. | | Drop `Microsoft.SourceLink.GitHub`, `Nullable`, unused `Moq` | Source Link ships in the .NET 8+ SDK; the polyfill and `Moq` are unused on net8+. | Keep them as the reference does: dead dependencies. | | Nullable reference types stay off | Annotating the public API is a separate change. | Enable now: widens a framework-only PR. | @@ -64,7 +64,7 @@ Each task is one commit. The `!` marks the breaking change. ## Verification - [x] `dotnet build src/Appy.Parsing.slnx -c Release -warnaserror`: 0 warnings, 0 errors. -- [x] `dotnet test src/Appy.Parsing.slnx`: 14 passed on net10.0 (4 facts, 10 theory cases). +- [x] `dotnet test src/Appy.Parsing.slnx`: 14 passed on net10.0 and 14 on net8.0 (4 facts, 10 theory cases). - [x] `dotnet cake` (Default target) is green, and `.artifacts/Appy.Parsing.2.0.0-preview.0.N.nupkg` holds `lib/net8.0` and `lib/net10.0` only. - [x] Package validation runs on pack; the suppression file lists only the two PKV006 entries. diff --git a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj index bdf7a8e..2359d81 100644 --- a/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj +++ b/src/Appy.Parsing.Tests/Appy.Parsing.Tests.csproj @@ -1,7 +1,7 @@  - net10.0 + net10.0;net8.0 Exe false From a032d1504b18875d72426f04ccc7003f0663f3cc Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Thu, 1 Oct 2026 11:19:39 +0100 Subject: [PATCH 18/19] build: restore from nuget.org only --- AGENTS.md | 3 ++- docs/plans/001-net10-migration.md | 2 ++ nuget.config | 7 +++++++ src/Directory.Build.props | 2 +- 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 nuget.config diff --git a/AGENTS.md b/AGENTS.md index c4aa7db..c64cba3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,7 +22,8 @@ dotnet test src/Appy.Parsing.slnx --filter "FullyQualifiedName~CalculatorTest" - `config.yml` lists the projects cake builds and their role (`Package` or `Test`). A new project not listed there is skipped by the build. - Package versions live in `src/Directory.Packages.props` (central package management); a - `PackageReference` in a csproj carries no `Version`. + `PackageReference` in a csproj carries no `Version`. The repo `nuget.config` restores from + nuget.org only. - Never run the `Publish` cake target or `dotnet nuget push` locally; CI publishes. ## Structure diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index df9dff0..8696694 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -17,6 +17,7 @@ made this move. No public API or behaviour change is intended; only the supporte | Library `net10.0;net8.0`, tests `net10.0;net8.0` | net10.0 and net8.0 are the supported LTS releases. net6.0 is out of support; `netstandard2.0` only needed the `Nullable` polyfill. Tests run once per shipped library asset. | Also `net9.0`: a short-term release that net8.0 assets already cover. Keep `netstandard2.0`: .NET Framework users can stay on 1.x. | | Release 2.0.0 | Dropping `net6.0` and `netstandard2.0` breaks .NET Framework, net6 and net7 users: a SemVer major. | 1.2.0, as Appy.Configuration did for the same drop: undersells the break. | | MinVer as the reference (2.3.0, package and CLI), phase `preview`, minimum major.minor `2.0` | One versioning setup across both repos. With the minimum set, the preview published on merge reads `2.0.0-preview.0.N`, not `1.1.1-preview`. | MinVer 8: needs a workaround in `build.cake` because Cake.MinVer only exposes the phase option that MinVer 8 rejects. | +| Repo `nuget.config` restores from nuget.org only | Central package management warns (NU1507) when a contributor's machine has more than one package source; a single cleared source avoids that without suppressing the warning. | Suppress NU1507: hides real source mix-ups. | | Central package management, `.slnx`, no Traversal build | `.slnx` is the SDK 10 solution format. Cake builds the projects listed in `config.yml`, as before. | Keep `.sln` as the reference. Traversal build as the reference: deferred. | | xUnit v3 3.2.2 with `xunit.runner.visualstudio` 3.1.5, FluentAssertions 7.2.2 | xUnit v2 is in maintenance mode; 3.2.2 matches the sibling repos. FluentAssertions 8 has a commercial licence; 7.x is the last Apache-2.0 line. | xUnit v3 4.x: newer, not yet used alongside. xUnit v2 as the reference: leaves a migration for later. | | CI installs the .NET 10 SDK (from `global.json`) plus .NET 8.0.x | The SDK builds both TFMs; 8.0.x provides the runtime for the net8.0 test run. | Install 8/9/10 as the reference: net9 is unused. | @@ -80,6 +81,7 @@ Each task is one commit. The `!` marks the breaking change. ``` global.json # SDK 10 +nuget.config # (new) nuget.org as the only package source src/Directory.Build.props # package metadata src/Directory.Build.targets # MinVer and package validation settings src/Directory.Packages.props # (new) central package versions diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..4d736c1 --- /dev/null +++ b/nuget.config @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index cdc2e0d..cba6c58 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -28,7 +28,7 @@ - 1571;1572;1573;1574;1591;NU1507 + 1571;1572;1573;1574;1591 From 0b21d9406ce2021a03026141076237af62ae7168 Mon Sep 17 00:00:00 2001 From: Jorge Rodriguez Galan Date: Thu, 1 Oct 2026 11:26:07 +0100 Subject: [PATCH 19/19] docs(plan): align tasks with the net8.0 test run --- docs/plans/001-net10-migration.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/plans/001-net10-migration.md b/docs/plans/001-net10-migration.md index 8696694..eb91218 100644 --- a/docs/plans/001-net10-migration.md +++ b/docs/plans/001-net10-migration.md @@ -30,7 +30,7 @@ made this move. No public API or behaviour change is intended; only the supporte Each task is one commit. The `!` marks the breaking change. - [x] 1. `feat(dotnet)!: target net10.0 and net8.0`: `global.json` SDK `10.0.103` with - `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0`; remove the + `rollForward: latestFeature` (drop `projects`); library TFMs; test TFM `net10.0` (later net10.0;net8.0, from review); remove the `Nullable` package, the `Microsoft.NETCore.App.Ref` download and the annotator properties; `PackageTags` to `NET10;NET8;parsing;lexer`. Test: the existing 14 tests pass on net10.0. - [x] 2. `chore(deps): adopt central package management and upgrade packages`: add @@ -57,7 +57,7 @@ Each task is one commit. The `!` marks the breaking change. passes with it (green). - [x] 6. `ci: update GitHub Actions for .NET 10`: `ci.yaml` and `publish.yaml` as the reference: `actions/checkout@v6`, `actions/cache@v5`, `actions/setup-dotnet@v5` reading `global.json` in - every job. Triggers stay as they are; no Docker steps. Test: PR checks green on all three OSes. + every job (later plus .NET 8.0.x for the net8.0 tests, from review). Triggers stay as they are; no Docker steps. Test: PR checks green on all three OSes. - [x] 7. `docs: update docs for .NET 10`: README supported frameworks (net8.0, net10.0; 1.x stays available for `netstandard2.0` and `net6.0`), AGENTS.md (central package management, xUnit v3), this plan's status. The README badge moves to 2.0.0 after the release, as a `docs(readme)` commit.