From e40bad775232d5fc91a58bf4aeade310c7ba2d5f Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Thu, 30 Jul 2026 15:48:16 +0300 Subject: [PATCH 1/2] Migrate the build orchestrator from NUKE to Fallout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NUKE is unmaintained and its transitive dependency graph keeps producing advisories. Fallout is the maintained hard fork, so the move is mostly a namespace swap plus the change from a bootstrapped build project to Fallout's tool-manifest model. `fallout-migrate` handled the mechanical part: `Nuke.*` -> `Fallout.*`, `NukeBuild` -> `FalloutBuild`, the `` MSBuild properties, and `.nuke/` -> `.fallout/`. The rest needed hand work: - `Nuke.Common.ProjectModel` is not a 1:1 map — `Solution` and `Project` now live in `Fallout.Solutions`. - `build.ps1` / `build.sh` become thin shims. They still provision an SDK, but instead of building and running `_build.csproj` they end with `dotnet tool restore` + `dotnet fallout`, so the orchestrator version is pinned in `.config/dotnet-tools.json` (`fallout.cli`, not the unpublished `Fallout.GlobalTools` the docs name). The `NUKE_ENTERPRISE_TOKEN` feedz block is gone. - `nuke/` -> `build/`, which is where Fallout's CLI resolves `_build.csproj` by convention when `.fallout/parameters.json` does not name one. - Dropped the `NuGet.Packaging` CVE pin — Fallout 11.0.18 resolves a clean 6.14.3. The `System.Security.Cryptography.Xml` pin stays: 11.0.18 still ships 10.0.6, and the fix upstream is committed but unreleased. `build.ps1`, `build.sh` and `.gitignore` are normally synced from AngleSharp.GitBase; the migration cannot avoid touching them, so those edits need folding back upstream. Verified with `.\build.ps1 RunUnitTests -AngleSharpVersion 1.5.0`: 286 tests pass on net10.0, net462 and net472, and `-Target` plus parameter passing behave as before. Co-Authored-By: Claude Opus 5 (1M context) --- .config/dotnet-tools.json | 12 ++++++ {.nuke => .fallout}/build.schema.json | 15 ++++++-- {.nuke => .fallout}/parameters.json | 0 .gitignore | 4 +- AGENTS.md | 9 +++-- build.ps1 | 16 +++----- build.sh | 16 +++----- {nuke => build}/.editorconfig | 0 {nuke => build}/Build.cs | 38 ++++++++----------- {nuke => build}/Configuration.cs | 2 +- {nuke => build}/Directory.Build.props | 0 {nuke => build}/Directory.Build.targets | 0 .../Extensions/StringExtensions.cs | 0 {nuke => build}/ReleaseNotes.cs | 0 {nuke => build}/ReleaseNotesParser.cs | 0 {nuke => build}/SemVersion.cs | 0 build/_build.csproj | 19 ++++++++++ nuke/_build.csproj | 20 ---------- src/AngleSharp.Js.sln | 2 +- src/Directory.Build.props | 4 +- 20 files changed, 80 insertions(+), 77 deletions(-) create mode 100644 .config/dotnet-tools.json rename {.nuke => .fallout}/build.schema.json (89%) rename {.nuke => .fallout}/parameters.json (100%) rename {nuke => build}/.editorconfig (100%) rename {nuke => build}/Build.cs (88%) rename {nuke => build}/Configuration.cs (93%) rename {nuke => build}/Directory.Build.props (100%) rename {nuke => build}/Directory.Build.targets (100%) rename {nuke => build}/Extensions/StringExtensions.cs (100%) rename {nuke => build}/ReleaseNotes.cs (100%) rename {nuke => build}/ReleaseNotesParser.cs (100%) rename {nuke => build}/SemVersion.cs (100%) create mode 100644 build/_build.csproj delete mode 100644 nuke/_build.csproj diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..6a8c8a1 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "fallout.cli": { + "version": "11.0.18", + "commands": [ + "fallout" + ] + } + } +} diff --git a/.nuke/build.schema.json b/.fallout/build.schema.json similarity index 89% rename from .nuke/build.schema.json rename to .fallout/build.schema.json index 29c138d..82690d1 100644 --- a/.nuke/build.schema.json +++ b/.fallout/build.schema.json @@ -48,7 +48,7 @@ "Quiet" ] }, - "NukeBuild": { + "FalloutBuild": { "properties": { "Continue": { "type": "boolean", @@ -102,6 +102,13 @@ "Verbosity": { "description": "Logging verbosity during build execution. Default is 'Normal'", "$ref": "#/definitions/Verbosity" + }, + "BuildProjectFile": { + "type": [ + "null", + "string" + ], + "description": "Path to the build project (.csproj) relative to the repository root. Defaults to 'build/_build.csproj' when unset. Read by the Fallout global tool's in-tool runner." } } } @@ -115,11 +122,11 @@ }, "Configuration": { "type": "string", - "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)", "enum": [ "Debug", "Release" - ] + ], + "description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)" }, "ReleaseNotesFilePath": { "type": "string", @@ -132,7 +139,7 @@ } }, { - "$ref": "#/definitions/NukeBuild" + "$ref": "#/definitions/FalloutBuild" } ] } diff --git a/.nuke/parameters.json b/.fallout/parameters.json similarity index 100% rename from .nuke/parameters.json rename to .fallout/parameters.json diff --git a/.gitignore b/.gitignore index a43fa81..1079ab1 100644 --- a/.gitignore +++ b/.gitignore @@ -195,5 +195,5 @@ pip-log.txt # Mac crap .DS_Store -# Nuke build tool -.nuke/temp \ No newline at end of file +# Fallout build tool +.fallout/temp \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 5b8adc7..907e072 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,8 +10,11 @@ over AngleSharp's `[DomName]`-style attributes. ## Commands -The orchestrator is NUKE (`nuke/Build.cs`), bootstrapped by `build.ps1` / `build.sh` -(`build.cmd` forwards to either). Default target is `RunUnitTests`. +The orchestrator is [Fallout](https://fallout.build) (`build/Build.cs`), the maintained hard fork +of NUKE. `build.ps1` / `build.sh` (`build.cmd` forwards to either) provision the SDK, then +`dotnet tool restore` + `dotnet fallout`; the CLI itself is pinned in +`.config/dotnet-tools.json` and resolves `build/_build.csproj` by convention. Default target is +`RunUnitTests`. ```powershell .\build.ps1 # restore, compile, run the full test suite @@ -19,7 +22,7 @@ The orchestrator is NUKE (`nuke/Build.cs`), bootstrapped by `build.ps1` / `build .\build.ps1 -Target Package # CreatePackage Package PrePublish Publish ``` -For the normal edit/test loop use the SDK directly — much faster than the NUKE bootstrap: +For the normal edit/test loop use the SDK directly — much faster than the Fallout bootstrap: ```powershell dotnet build src/AngleSharp.Js.sln diff --git a/build.ps1 b/build.ps1 index 3cca4ef..61c6628 100644 --- a/build.ps1 +++ b/build.ps1 @@ -13,10 +13,9 @@ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent # CONFIGURATION ########################################################################### -$BuildProjectFile = "$PSScriptRoot\nuke\_build.csproj" -$TempDirectory = "$PSScriptRoot\\.nuke\temp" +$TempDirectory = "$PSScriptRoot\.fallout\temp" -$DotNetGlobalFile = "$PSScriptRoot\\global.json" +$DotNetGlobalFile = "$PSScriptRoot\global.json" $DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1" $DotNetChannel = "STS" @@ -32,7 +31,7 @@ function ExecSafe([scriptblock] $cmd) { if ($LASTEXITCODE) { exit $LASTEXITCODE } } -# If dotnet CLI is installed globally and it matches requested version, use for execution +# If dotnet CLI is installed globally, use it; otherwise provision a local copy under .fallout\temp. if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` $(dotnet --version) -and $LASTEXITCODE -eq 0) { $env:DOTNET_EXE = (Get-Command "dotnet").Path @@ -65,10 +64,5 @@ else { Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)" -if (Test-Path env:NUKE_ENTERPRISE_TOKEN) { - & $env:DOTNET_EXE nuget remove source "nuke-enterprise" > $null - & $env:DOTNET_EXE nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password $env:NUKE_ENTERPRISE_TOKEN > $null -} - -ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet } -ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } +ExecSafe { & $env:DOTNET_EXE tool restore } +ExecSafe { & $env:DOTNET_EXE fallout $BuildArguments } diff --git a/build.sh b/build.sh index a226b96..fc76bf8 100755 --- a/build.sh +++ b/build.sh @@ -9,10 +9,9 @@ SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) # CONFIGURATION ########################################################################### -BUILD_PROJECT_FILE="$SCRIPT_DIR/nuke/_build.csproj" -TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp" +TEMP_DIRECTORY="$SCRIPT_DIR/.fallout/temp" -DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" +DOTNET_GLOBAL_FILE="$SCRIPT_DIR/global.json" DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh" DOTNET_CHANNEL="STS" @@ -27,7 +26,7 @@ function FirstJsonValue { perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}" } -# If dotnet CLI is installed globally and it matches requested version, use for execution +# If dotnet CLI is installed globally, use it; otherwise provision a local copy under .fallout/temp. if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then export DOTNET_EXE="$(command -v dotnet)" else @@ -58,10 +57,5 @@ fi echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)" -if [[ ! -z ${NUKE_ENTERPRISE_TOKEN+x} && "$NUKE_ENTERPRISE_TOKEN" != "" ]]; then - "$DOTNET_EXE" nuget remove source "nuke-enterprise" &>/dev/null || true - "$DOTNET_EXE" nuget add source "https://f.feedz.io/nuke/enterprise/nuget" --name "nuke-enterprise" --username "PAT" --password "$NUKE_ENTERPRISE_TOKEN" --store-password-in-clear-text &>/dev/null || true -fi - -"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet -"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" +"$DOTNET_EXE" tool restore +exec "$DOTNET_EXE" fallout "$@" diff --git a/nuke/.editorconfig b/build/.editorconfig similarity index 100% rename from nuke/.editorconfig rename to build/.editorconfig diff --git a/nuke/Build.cs b/build/Build.cs similarity index 88% rename from nuke/Build.cs rename to build/Build.cs index f1dc816..bb06195 100644 --- a/nuke/Build.cs +++ b/build/Build.cs @@ -1,11 +1,11 @@ +using Fallout.Common; +using Fallout.Common.CI.GitHubActions; +using Fallout.Common.IO; +using Fallout.Common.Tools.DotNet; +using Fallout.Common.Tools.GitHub; +using Fallout.Common.Utilities.Collections; +using Fallout.Solutions; using Microsoft.Build.Exceptions; -using Nuke.Common; -using Nuke.Common.CI.GitHubActions; -using Nuke.Common.IO; -using Nuke.Common.ProjectModel; -using Nuke.Common.Tools.DotNet; -using Nuke.Common.Tools.GitHub; -using Nuke.Common.Utilities.Collections; using Octokit; using Octokit.Internal; using Serilog; @@ -13,26 +13,20 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using static Nuke.Common.Tools.DotNet.DotNetTasks; -using Project = Nuke.Common.ProjectModel.Project; +using static Fallout.Common.Tools.DotNet.DotNetTasks; +using Project = Fallout.Solutions.Project; -class Build : NukeBuild +class Build : FalloutBuild { - /// Support plugins are available for: - /// - JetBrains ReSharper https://nuke.build/resharper - /// - JetBrains Rider https://nuke.build/rider - /// - Microsoft VisualStudio https://nuke.build/visualstudio - /// - Microsoft VSCode https://nuke.build/vscode - public static int Main () => Execute(x => x.RunUnitTests); - [Nuke.Common.Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + [Fallout.Common.Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; - [Nuke.Common.Parameter("ReleaseNotesFilePath - To determine the SemanticVersion")] + [Fallout.Common.Parameter("ReleaseNotesFilePath - To determine the SemanticVersion")] readonly AbsolutePath ReleaseNotesFilePath = RootDirectory / "CHANGELOG.md"; - [Nuke.Common.Parameter("AngleSharp package version override (e.g. 1.0.0 for compatibility checks)")] + [Fallout.Common.Parameter("AngleSharp package version override (e.g. 1.0.0 for compatibility checks)")] readonly string AngleSharpVersion; [Solution] @@ -52,7 +46,7 @@ class Build : NukeBuild Project TargetProject { get; set; } - // Note: The ChangeLogTasks from Nuke itself look buggy. So using the Cake source code. + // Note: The built-in ChangeLogTasks (inherited from NUKE) look buggy. So using the Cake source code. IReadOnlyList ChangeLog { get; set; } ReleaseNotes LatestReleaseNotes { get; set; } @@ -244,7 +238,7 @@ protected override void OnBuildInitialized() var credentials = new Credentials(gitHubToken); GitHubTasks.GitHubClient = new GitHubClient( - new ProductHeaderValue(nameof(NukeBuild)), + new ProductHeaderValue(nameof(FalloutBuild)), new InMemoryCredentialStore(credentials)); GitHubTasks.GitHubClient.Repository.Release @@ -280,7 +274,7 @@ protected override void OnBuildInitialized() var credentials = new Credentials(gitHubToken); GitHubTasks.GitHubClient = new GitHubClient( - new ProductHeaderValue(nameof(NukeBuild)), + new ProductHeaderValue(nameof(FalloutBuild)), new InMemoryCredentialStore(credentials)); GitHubTasks.GitHubClient.Repository.Release diff --git a/nuke/Configuration.cs b/build/Configuration.cs similarity index 93% rename from nuke/Configuration.cs rename to build/Configuration.cs index 9c08b1a..75c63ea 100644 --- a/nuke/Configuration.cs +++ b/build/Configuration.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel; using System.Linq; -using Nuke.Common.Tooling; +using Fallout.Common.Tooling; [TypeConverter(typeof(TypeConverter))] public class Configuration : Enumeration diff --git a/nuke/Directory.Build.props b/build/Directory.Build.props similarity index 100% rename from nuke/Directory.Build.props rename to build/Directory.Build.props diff --git a/nuke/Directory.Build.targets b/build/Directory.Build.targets similarity index 100% rename from nuke/Directory.Build.targets rename to build/Directory.Build.targets diff --git a/nuke/Extensions/StringExtensions.cs b/build/Extensions/StringExtensions.cs similarity index 100% rename from nuke/Extensions/StringExtensions.cs rename to build/Extensions/StringExtensions.cs diff --git a/nuke/ReleaseNotes.cs b/build/ReleaseNotes.cs similarity index 100% rename from nuke/ReleaseNotes.cs rename to build/ReleaseNotes.cs diff --git a/nuke/ReleaseNotesParser.cs b/build/ReleaseNotesParser.cs similarity index 100% rename from nuke/ReleaseNotesParser.cs rename to build/ReleaseNotesParser.cs diff --git a/nuke/SemVersion.cs b/build/SemVersion.cs similarity index 100% rename from nuke/SemVersion.cs rename to build/SemVersion.cs diff --git a/build/_build.csproj b/build/_build.csproj new file mode 100644 index 0000000..647ac26 --- /dev/null +++ b/build/_build.csproj @@ -0,0 +1,19 @@ + + + + Exe + net10.0 + + CS0649;CS0169 + .. + .. + 1 + + + + + + + + + diff --git a/nuke/_build.csproj b/nuke/_build.csproj deleted file mode 100644 index 0c61074..0000000 --- a/nuke/_build.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - Exe - net10.0 - - CS0649;CS0169 - .. - .. - 1 - - - - - - - - - - diff --git a/src/AngleSharp.Js.sln b/src/AngleSharp.Js.sln index d404747..b34380a 100644 --- a/src/AngleSharp.Js.sln +++ b/src/AngleSharp.Js.sln @@ -7,7 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AngleSharp.Js", "AngleSharp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AngleSharp.Js.Tests", "AngleSharp.Js.Tests\AngleSharp.Js.Tests.csproj", "{18B0B97B-8795-4DC2-A1E7-8070255BE718}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_build", "..\nuke\_build.csproj", "{07DA52AA-8F6F-4F43-B09E-6AE899E95E43}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_build", "..\build\_build.csproj", "{07DA52AA-8F6F-4F43-B09E-6AE899E95E43}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Directory.Build.props b/src/Directory.Build.props index af56551..2eeb94f 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -6,8 +6,8 @@ Copyright 2017-2026, AngleSharp - 1.0.0 From 3984c950df39a6105974b477ce2d21165c1ae7f6 Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Thu, 30 Jul 2026 16:04:38 +0300 Subject: [PATCH 2/2] Update the CI workflow actions to their latest majors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All three actions were a major behind: `actions/checkout` v5 → v7, `actions/setup-dotnet` v5 → v6, `actions/setup-node` v5 → v7. Each of those majors is an ESM migration plus dependency upgrades, with no input changes affecting this workflow. checkout v7 additionally blocks checking out fork PRs under `pull_request_target`/`workflow_run`, which this workflow does not use — it triggers on `push` and `pull_request`. Runtime versions are deliberately left alone. `dotnet-version: 10.0.x` is already the current LTS, supported to November 2028. `node-version` stays at 20.x: it only feeds the doclet publish, whose npm dependencies are old enough that moving the runtime risks breaking them for no benefit here. Also replaced the `::set-output` workflow command, deprecated since 2022 and no longer functional, with an append to `$GITHUB_OUTPUT`. It is what feeds `needs.can_document.outputs.value`, so the documentation job's condition could not evaluate true while it stayed. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fdad75..7841368 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: id: check_job run: | echo "value: ${{ env.DOCS_PATH != null && github.ref == env.DOCS_BRANCH }}" - echo "::set-output name=value::${{ env.DOCS_PATH != null && github.ref == env.DOCS_BRANCH }}" + echo "value=${{ env.DOCS_PATH != null && github.ref == env.DOCS_BRANCH }}" >> "$GITHUB_OUTPUT" documentation: needs: [can_document] @@ -26,10 +26,10 @@ jobs: if: needs.can_document.outputs.value == 'true' steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - name: Use Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v7 with: node-version: "20.x" registry-url: 'https://registry.npmjs.org' @@ -48,9 +48,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 with: dotnet-version: | 10.0.x @@ -62,9 +62,9 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - - uses: actions/setup-dotnet@v5 + - uses: actions/setup-dotnet@v6 with: dotnet-version: | 10.0.x