Skip to content

feat(globaltool): add in-tool build runner (PR-A of bootstrapper deprecation)#201

Merged
ChrisonSimtian merged 2 commits into
mainfrom
feat/globaltool-runner
May 26, 2026
Merged

feat(globaltool): add in-tool build runner (PR-A of bootstrapper deprecation)#201
ChrisonSimtian merged 2 commits into
mainfrom
feat/globaltool-runner

Conversation

@ChrisonSimtian

Copy link
Copy Markdown
Collaborator

Re-opened from #200, which closed because GitHub Actions wouldn't trigger workflows on its branch (`feat/global-tool-in-tool-runner`) despite multiple pushes, an empty-commit nudge, and a close/reopen cycle. Same code, fresh branch.

Summary

First of three PRs that deprecate the per-repo `build.cmd`/`build.sh`/`build.ps1` bootstrappers in favour of `Fallout.GlobalTool` (`fallout`) as the canonical entry point for running builds. This one is purely additive — no behaviour change for any repo with existing bootstrappers committed.

Three-PR sequence:

  • PR-A (this one) — Add in-tool build runner. `fallout ` runs `dotnet build` + `dotnet run --no-build` directly instead of spawning `./build.sh`.
  • PR-B — Switch this repo to thin shims, delete `build.cmd`, update the `[GitHubActions]` generator + workflows, update `:setup` scaffolder.
  • PR-C — Docs cleanup (already tracked under Docs CLI cleanup: replace stale nuke references with fallout across docs/ #198).

What's in this PR

New files:

  • `src/Fallout.GlobalTool/BuildProjectResolver.cs` — resolves the build project (`.csproj`) from optional `BuildProjectFile` field in `.fallout/parameters.json`, falling back to convention `build/_build.csproj`. Six unit tests cover convention default, explicit override, missing files (both cases), and empty override values.
  • `src/Fallout.GlobalTool/Program.Run.cs` — new in-tool runner. Resolves `dotnet` (PATH first; shim-provisioned `.fallout/temp/dotnet-{unix,win}` as fallback), seeds the same env vars the shim sets, then runs `dotnet build` + `dotnet run --project --no-build -- ` as subprocesses with inherited stdio (colours/progress pass through).
  • `tests/Fallout.GlobalTool.Tests/BuildProjectResolverTests.cs` — 6 new tests, all green.

Modified:

  • `src/Fallout.GlobalTool/Program.cs` — `Handle`'s no-`:` fallback now calls `Run(args, rootDirectory, BuildProjectResolver.Resolve(rootDirectory))` instead of `Build(buildScript, ...)`. The `buildScript == null` branch of the "Could not find" prompt is removed — we can run without a shim now — but the `rootDirectory == null` branch stays for empty repos.

What this PR does NOT do (so PR-B has something to do)

  • Doesn't delete `Build()` — still called from `Program.Complete.cs` as a bootstrap path for the first-time completion request. Removed in PR-B alongside the shim deletion.
  • Doesn't touch the shim scripts (`build.sh`/`build.ps1`/`build.cmd`) — they continue to work directly via their own `dotnet build` + `dotnet run --project` invocations, independent of the global tool.
  • Doesn't touch the `[GitHubActions]` generator — it still emits `run: ./{BuildCmdPath} {targets}`, which still works because the shims are still in place. The generator and the four `.github/workflows/*.yml` files get the three-step `setup-dotnet` + `tool restore` + `dotnet fallout` shape in PR-B.
  • Doesn't add `BuildProjectFile` to `build.schema.json` — the schema is regenerated by `HandleShellCompletionAttribute` on every build run, so manual edits don't stick. The schema-generation update belongs to PR-B. The resolver works without schema support because `parameters.json` accepts arbitrary fields (JSON Schema default allows additional properties).

Backwards compatibility

Scenario Behaviour
Existing repo, old fat bootstrapper, run `./build.sh Compile` Unchanged — bootstrapper does its own `dotnet build` + `dotnet run --project`, doesn't touch the global tool.
Existing repo, old fat bootstrapper, run `fallout Compile` Now uses the new in-tool runner. Same end result (`dotnet build` + `dotnet run --no-build`), one fewer subprocess hop. The shim's env-var exports are bypassed; the new runner sets them itself to compensate.
Existing repo, no `_build.csproj` (somehow) Resolver throws with a helpful message pointing at `fallout :setup` or `BuildProjectFile` in `parameters.json`.
Empty directory, no `.fallout/` Prompt for `:setup` as before.

Verification

  • `dotnet build src/Fallout.GlobalTool/Fallout.GlobalTool.csproj` — green (0 errors; only pre-existing warnings unrelated to this PR).
  • `dotnet test tests/Fallout.GlobalTool.Tests/` — 17/17 passed (11 existing + 6 new).
  • Dogfood: `dotnet run --project src/Fallout.GlobalTool -- --help` — exercises full new path; outputs build help identical to `./build.sh --help`.

Test plan

  • CI green on `ubuntu-latest` (the only PR gate).
  • `Fallout.GlobalTool.Tests` green on all three release runners post-merge — though note: `windows-latest` is currently broken on `main` due to a separate pre-existing issue with `Nuke.Common.Shim.Tests` having no discoverable test methods (filing a separate PR for that).

Refs

…ecation)

First of three PRs that deprecate the per-repo bootstrappers in favour of
`Fallout.GlobalTool` as the entry point for running builds.

Today the global tool's no-`:` fallback in Program.Handle spawned
`bash ./build.sh` (or `powershell ./build.ps1`), letting the shim do
`dotnet build` + `dotnet run --project --no-build -- $@`. This PR moves
that work into the tool itself.

New files:

- BuildProjectResolver.cs — resolves the build project (.csproj) from
  the optional `BuildProjectFile` field in `.fallout/parameters.json`,
  falling back to the convention `build/_build.csproj`. The schema
  itself is regenerated by HandleShellCompletionAttribute on every
  build run; teaching that generator about the new field belongs in
  PR-B. The resolver works without schema support because
  parameters.json accepts arbitrary fields.

- Program.Run.cs — new in-tool runner. Resolves dotnet (PATH first,
  shim-provisioned .fallout/temp/dotnet-{unix,win} as fallback), seeds
  the same env vars the shim sets (DOTNET_CLI_TELEMETRY_OPTOUT,
  DOTNET_NOLOGO, DOTNET_ROLL_FORWARD, FALLOUT_TELEMETRY_OPTOUT, plus
  the existing FALLOUT_GLOBAL_TOOL_* markers), then runs the same two
  subprocesses the shim runs — `dotnet build` then
  `dotnet run --project --no-build -- <args>` — with inherited stdio so
  colours and progress pass through. Argument forwarding uses
  ProcessStartInfo.ArgumentList so cross-platform quoting is handled
  by the framework.

Program.cs change:

- Handle's no-`:` fallback now calls `Run(args, rootDirectory,
  BuildProjectResolver.Resolve(rootDirectory))` instead of
  `Build(buildScript, ...)`. The `buildScript == null` branch of the
  "Could not find" prompt is removed — we can run without a shim now —
  but the `rootDirectory == null` branch stays for empty repos.

What this PR does NOT do:

- Delete `Build()` — still called from Program.Complete.cs as a
  bootstrap path for the first-time completion request. Removed in
  PR-B alongside the bootstrapper deletion.
- Touch the shim scripts (`build.sh`/`build.ps1`/`build.cmd`) — they
  continue to work directly via their own `dotnet build` +
  `dotnet run --project` invocations, independent of the global tool.
- Touch the `[GitHubActions]` generator or CI workflows — they still
  call `./build.cmd Test Pack`, which still works. The generator and
  workflow shape change in PR-B.

Backwards compatibility: existing repos with fat bootstrappers are
unaffected — `./build.sh Compile` runs unchanged. The only behavioural
delta is that `fallout Compile` no longer hops through `bash ./build.sh`
before running `dotnet build` + `dotnet run`; it does that directly.
Same end result, one fewer subprocess.

Tests: BuildProjectResolverTests covers convention default, explicit
override, missing files (both convention and configured), and empty
override values — 6 new tests, all green alongside the existing 11
in Fallout.GlobalTool.Tests.

Dogfooded locally via `dotnet run --project src/Fallout.GlobalTool --
--help`, which exercises the full new path: tool → Resolver →
dotnet build → dotnet run --no-build -- --help. Output matches
`./build.sh --help`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ChrisonSimtian

Copy link
Copy Markdown
Collaborator Author

Tracked under umbrella issue #203 — bootstrapper deprecation plan. Pick-up checklist for tomorrow lives there.

@ChrisonSimtian
ChrisonSimtian merged commit 960528a into main May 26, 2026
1 check passed
@ChrisonSimtian
ChrisonSimtian deleted the feat/globaltool-runner branch May 26, 2026 20:59
ChrisonSimtian added a commit that referenced this pull request May 26, 2026
…PR-B of #203) (#204)

Second of three PRs that make `Fallout.GlobalTool` (`fallout`) the canonical
entry point for running builds. PR-A (#201) shipped the in-tool runner.
This PR cuts THIS repo over to thin shims, regenerates the workflows, and
updates the framework so downstream consumers re-generating with v11+ also
get the new shape.

## Breaking changes

- **`[GitHubActions]` generator now emits 3 steps** instead of one
  `./{BuildCmdPath} {targets}` line:
    1. `actions/setup-dotnet@v4` with `global-json-file: global.json`
    2. `dotnet tool restore`
    3. `dotnet fallout {targets}`
  Downstream consumers' next `--generate-configuration` run will produce
  the new shape. They need `.config/dotnet-tools.json` with `Fallout.GlobalTool`
  pinned, or `dotnet tool restore` fails in CI.

- **`build.cmd` deleted** from this repo (both root and from the `:setup`
  scaffolder template). Was a one-line dispatcher to `build.ps1`; no longer
  needed now that `dotnet fallout` is the entry point everywhere.

## This repo's cutover

- `.config/dotnet-tools.json` — new, pins `Fallout.GlobalTool` 10.3.37 (the
  version just published from #201).
- `build.sh` / `build.ps1` — thin (~60 lines each): keep the dotnet
  provisioning block verbatim (for the rare case `dotnet` isn't installed),
  end with `tool restore` + `dotnet fallout "$@"`.
- `.github/workflows/{ubuntu,windows,macos}-latest.yml` — regenerated to the
  3-step shape.
- `.github/workflows/release.yml` — hand-written (kept that way per its
  header comment); updated to the same 3-step shape with the existing
  `NuGetApiKey` / `GITHUB_TOKEN` env mapping preserved.

## Framework changes

- `Fallout.Common/CI/GitHubActions/Configuration/GitHubActionsRunStep.cs`:
  rewritten to emit 3 steps; drops the `BuildCmdPath` field.
- `Fallout.Common/CI/GitHubActions/GitHubActionsAttribute.cs`: stops passing
  `BuildCmdPath` to the run step.
- `Fallout.Build/CICD/ConfigurationAttributeBase.cs`: softens `BuildCmdPath`
  to fall back to `"build.cmd"` instead of asserting when no file is found —
  keeps the legacy CI providers (AzurePipelines, AppVeyor, TeamCity,
  SpaceAutomation) functional for consumers who still have `build.cmd`,
  without forcing this repo to keep one.
- `Fallout.Build/Utilities/SchemaUtility.cs`: injects a synthetic
  `BuildProjectFile` (optional string) into the `FalloutBuild` base schema
  so editors offer IntelliSense for the `BuildProjectFile` field the
  in-tool runner reads from `.fallout/parameters.json`.
- `Fallout.GlobalTool/Program.Setup.cs` (`WriteBuildScripts`): drops the
  `build.cmd` emission, emits the thin `build.sh` / `build.ps1` templates,
  and creates `.config/dotnet-tools.json` (skipped if one already exists —
  consumer may have other tools pinned).
- New template `Fallout.GlobalTool/templates/dotnet-tools.json` with a
  `_FALLOUT_GLOBAL_TOOL_VERSION_` placeholder filled at `:setup` time from
  the running tool's own assembly version.

## Test updates

- `SchemaUtilityTest.Test*.verified.json` (×4): add `BuildProjectFile`
  property after `Verbosity`.
- `CompletionUtilityTest.TestGetCompletionItems{Target,Parameter}Build.verified.txt`:
  add `BuildProjectFile: []` in alphabetical position.
- `ConfigurationGenerationTest.Test_testName={simple,detailed}-triggers_attribute=GitHubActionsAttribute.verified.txt`:
  expect the new 3-step shape.
- `.fallout/build.schema.json` regenerated by the build's own
  `HandleShellCompletionAttribute`.

All affected test projects pass locally (`Fallout.Build.Tests`,
`Fallout.Common.Tests`, `Fallout.GlobalTool.Tests`).

## Not in scope (follow-up)

- `Program.cs` `Build()` method is still alive — called once from
  `Program.Complete.cs` for the bootstrap completion path. Now that shims
  are thin (themselves calling `dotnet fallout`), this is just a slightly
  longer subprocess hop than necessary; safe but redundant. Removal can
  follow once we're confident nothing else depends on the shim shape.
- Docs sweep tracked in #198 (PR-C).
- `Fallout.Common.targets` could surface `.config/dotnet-tools.json` in the
  IDE "boot" link group alongside `build.sh`/`build.ps1`; cosmetic, deferred.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 26, 2026
Closes #198 and completes PR-C of #203.

## Scope

Two related sweeps in one PR:

1. **CLI/brand rebrand (closes #198)**: replace stale `nuke` CLI command
   examples with `fallout` across `docs/`, switch `.nuke` directory-marker
   references to `.fallout`, rebrand "NUKE provides/comes/has/integrates"
   phrasing to "Fallout …" where it describes the current product (not the
   historical project), update namespace examples (`Nuke.Common.Tools.*` →
   `Fallout.Common.Tools.*`, `Nuke.GlobalTool` → `Fallout.GlobalTool`),
   and update MSBuild property names (`NukeRootDirectory` →
   `FalloutRootDirectory`, with the legacy names called out as still-honoured).
2. **New shim shape (PR-C of #203)**: update CONTRIBUTING.md, CLAUDE.md,
   `docs/01-getting-started/02-setup.md`, `docs/01-getting-started/03-execution.md`,
   and `docs/05-cicd/github-actions.md` to describe the thin shims +
   local-tool-manifest pattern PR-B introduced: drop `build.cmd` from
   examples, document the new 3-step GitHub Actions shape (`actions/setup-dotnet`
   → `dotnet tool restore` → `dotnet fallout`), describe `.config/dotnet-tools.json`.

## What's NOT touched

- `docs/rebrand-plan.md` — intentionally NUKE-named throughout (it's the
  rebrand plan).
- `docs/migration/from-nuke.md` — migration framing needs both names.
- The `Nuke.<X>` namespace mentions inside `docs/rebrand-plan.md`'s mapping
  tables and the bridge-package strategy section.
- Historical references like "upstream NUKE issue #822" and "the original
  NUKE key was matkoch-owned" — these cite the upstream project and need
  to stay accurate.
- `CHANGELOG.md`, `src/Fallout.Migrate.Analyzers/README.md`, and other
  package READMEs that reference the historical NUKE project for migration
  context.

## Files changed

22 docs + CONTRIBUTING.md + CLAUDE.md.

Most edits are mechanical text substitutions; the substantive rewrites are:

- `docs/01-getting-started/02-setup.md`: new file structure example
  (drops `build.cmd`, adds `.config/dotnet-tools.json` and `.fallout/`),
  new note explaining the thin-shim role, MSBuild property names updated.
- `docs/01-getting-started/03-execution.md`: thin-shim explanation in the
  Global Tool / Windows / Linux tab block; all `nuke <target>` /
  `nuke --help` / `nuke --plan` / etc. switched to `fallout`.
- `docs/05-cicd/github-actions.md`: generated-output YAML examples updated
  to the 3-step shape; cache-step `actions/cache@v2` bumped to `@v4` with
  the current key files; upload-artifact `@v1` bumped to `@v5` to match
  the actual generator output; new note explaining the `dotnet-tools.json`
  requirement.
- `docs/06-global-tool/00-shell-completion.md`: shell completion scripts
  rebranded (command name + function names: `_nuke_zsh_complete` →
  `_fallout_zsh_complete`, etc.).
- `docs/06-global-tool/03-navigation.md`: navigation function names
  rebranded (`nuke.` → `fallout.`, etc.).

## Verification

- Edits don't change link targets, only prose and code examples.
- Docusaurus `onBrokenLinks: 'throw'` will catch any regression at deploy
  time. PR-C is docs-only and hits the noop `ubuntu-latest-docs.yml`
  workflow so the GitHub PR check stays green.

## Refs

- Closes #198 (docs CLI cleanup).
- Completes PR-C of #203 (bootstrapper-deprecation plan). PR-A (#201) and
  PR-B (#204) are already merged.
- Companion issue #199 (CLI alias bridge guide for migrating users) is a
  separate enhancement, not in scope here.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant