Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

NSchema.Build is the build/release pipeline tool for NSchema, written as a .NET 10 console
app. It orchestrates `dotnet` CLI steps (clean, format, restore, build, test, pack) and the
release process (versioning, changelog, git tag, GitHub release, NuGet publish). It is run
both locally and from CI, and is also packaged/published as the `NSchema.Build` NuGet package.

## Commands

Run the pipeline locally from the repo root:

```bash
# CI build pipeline (clean → format → extract → version → changelog → restore → build → test)
dotnet run --project src/NSchema.Build/NSchema.Build.csproj -- build

# Full release pipeline (adds pack → tag → GitHub release → NuGet publish)
dotnet run --project src/NSchema.Build/NSchema.Build.csproj -- deploy
```

Plain `dotnet build` / `dotnet test` work too, but there is no test project yet — `Steps/Test.cs`
just invokes `dotnet test`. `TreatWarningsAsErrors` is on, so warnings fail the build.

Configuration comes from `appsettings.json` under the `Build` section, overridable via
environment variables using the `Build__<Key>` convention (e.g. `Build__ProjectFile`,
`Build__SkipVersion`). See `.github/workflows/cicd.yml` for the CI invocation.

## Architecture

The app is built on the **Hamelin** pipeline framework. `Program.cs` is the whole entry point:
it sets up DI, binds + validates `BuildOptions`, and dispatches the first CLI arg (`build` /
`deploy`) to an ordered chain of `.UseStep<T>()` calls. To change what a pipeline does, edit the
step chain in `Program.cs`; to change *how* a stage behaves, edit the corresponding step.

- **Steps** (`Steps/`) — each implements `Hamelin.IPipelineStep` with a single `Run(...)`
method and a `[DisplayName]`. They are registered automatically via
`AddStepsFromAssemblyContaining<Program>()`, so a new step just needs to be a class in the
assembly and then added to a chain in `Program.cs`. Dependencies (logger, options, command
runner, pipeline context) are constructor-injected.

- **State passing** — steps share data through `IPipelineContext.State` (typed get/set), not
return values. `ExtractProject` parses the csproj and `context.State.Set(projectInfo)`;
later steps (`Version`, `Changelog`, etc.) call `context.State.Get<ProjectInfo>()`. The same
context exposes `FileSystem` for file access.

- **Shelling out** — all external commands go through `ICommandRunner`
(`CliWrapCommandRunner`, backed by CliWrap). Steps never call `Process` directly; inject
`ICommandRunner` and call `commands.Run("dotnet", [...], ct)`.

- **Skip flags** — `Version` and `Changelog` honor `SkipVersion` / `SkipChangelog` on
`BuildOptions` (CI sets these to `true` since NSchema.Build versions itself manually).

- **NuGet integration** — `Version` uses the `NuGet.Protocol` API directly against the feed
to guard that the project's version is new and strictly greater than the latest published
version. `NuGetLoggerAdapter` bridges NuGet's `ILogger` to `Microsoft.Extensions.Logging`.

## Conventions

- Central package management: all versions live in `Directory.Packages.props`;
`<PackageReference>` entries in the csproj carry **no** `Version` attribute.
- `BuildOptions` is validated at startup (`ValidateOnStart`) — required config keys must be
present or the app fails fast before any step runs.
9 changes: 8 additions & 1 deletion src/NSchema.Build/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@
.UseStep<Build>()
.UseStep<Test>()
.RunWithExitCode(),
["verify"] => pipeline
.UseStep<Clean>()
.UseStep<Format>()
.UseStep<Restore>()
.UseStep<Build>()
.UseStep<Test>()
.RunWithExitCode(),
["deploy"] => pipeline
.UseStep<Clean>()
.UseStep<ExtractProject>()
Expand All @@ -53,6 +60,6 @@

static int Help()
{
Console.Error.WriteLine("Usage: nschema-build <build|deploy>");
Console.Error.WriteLine("Usage: nschema-build <build|verify|deploy>");
return 1;
}