Skip to content

Continuous delivery model: IPublishTarget, channels, environments (ADR-0009)#498

Draft
ChrisonSimtian wants to merge 3 commits into
Fallout-build:mainfrom
ChrisonSimtian:rfc/continuous-delivery-model
Draft

Continuous delivery model: IPublishTarget, channels, environments (ADR-0009)#498
ChrisonSimtian wants to merge 3 commits into
Fallout-build:mainfrom
ChrisonSimtian:rfc/continuous-delivery-model

Conversation

@ChrisonSimtian

Copy link
Copy Markdown
Collaborator

Draft / discussion piece. First cut of Fallout's CD domain model — for maintainer review before the provider implementations land. Builds on ADR-0001; settles the DeploymentTarget half of #334 / epic #332.

The model (ADR-0009)

A coherent vocabulary on top of ADR-0001's mechanism:

  • Release — an immutable snapshot (a v* tag), built once.
  • Artifact — what the build produces: packages, assemblies, releasenotes, symbols, source, documentation, homebrew-formula.
  • Target — a distribution endpoint (nuget.org, github-packages, github-releases, homebrew, docs) implementing IPublishTarget.
  • Environment — a promotion stage (DevStagingProduction) that groups targets and carries a gate.
  • Channel — which environments a release is eligible for (preview→Dev,Staging; release→Dev,Staging,Production).
  • Deployment — one (artifact → target) push; tracked + retryable.

Invariant: build once; promote that single immutable artifact through a channel's environments; never promote across channels (a -preview build is never re-versioned into GA). This is why "build once" and "Dev→Staging→Prod" are both true — maturity is fixed at build time; environments only control distribution reach.

Two layers: the domain model is provider-neutral; the GitHub realization maps each target to a GitHub Environment (per-target Deployment records) with a single production env as the promotion gate. Full rationale + mermaid diagram in docs/adr/0009-continuous-delivery-model.md.

Code in this cut (all [Experimental("FALLOUT005")])

  • IPublishTarget — generalizes the NuGet-feed-shaped PublishTarget (which now implements it and owns its own DeployAsync). IPublish.PublishTargetsIEnumerable<IPublishTarget>; Publish builds one Artifact and fans it out.
  • Artifact/ArtifactKind, Channel, DeploymentEnvironment, DeploymentContext.
  • GitHubReleaseTarget — a second implementation (stub; deploy path builds on GitHubReleaseTasks from ADR-0001, tracked by First-class ReleaseChannel / DeploymentTarget / Environment model #334).
  • TransitionShimGenerator now skips [Experimental] types — new opt-in surface has no Nuke.* consumers to bridge, and shimming it leaked the experimental diagnostic into generated code.

Decisions captured

  1. Green-field off main (v10.4 bridge); model is version-scheme-agnostic.
  2. Environment = target-group; GitHub realization = per-target envs + one production gate.
  3. github-packages spans Staging + Production; github-releases is Production (optional pre-release in Staging).
  4. Cross-repo targets (docs, homebrew) start in-pipeline, evolve to downstream-owned via repository_dispatch.

Deferred to refinement passes (weekend work)

  • GitHub provider implementations: GitHubReleaseTasks, GitHubEnvironment sync (ADR-0001 patterns).
  • The reusable publish-{artifact}-{target} workflows + build-once release orchestrator.
  • Homebrew + docs (Docusaurus) targets.
  • Generating the promotion diagram from the model.

Verification

  • dotnet fallout Test Pack → green; all relevant specs pass (incl. new PublishTargetSpecs, all shim specs). The 3 GitRepositoryWorktreeSpecs failures are pre-existing and environment-specific (reproduce on a clean base), unrelated to this change.
  • Existing Verify snapshots unaffected (the generator skip only applies to new experimental types).

ChrisonSimtian and others added 2 commits July 17, 2026 14:55
Complements ADR-0001 (CD mechanism: attributes/tasks/hybrid) with the domain
model our release flow reasons in: release → channel → environment → target →
deployment, and the build-once/promote-within-a-channel invariant. Records the
decisions on environments-as-target-groups, the GitHub realization (per-target
environments + a single production gate), targets spanning environments, and
cross-repo targets. Settles the DeploymentTarget half of Fallout-build#334 / epic Fallout-build#332.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generalize the NuGet-feed-shaped PublishTarget into an IPublishTarget interface
so a single build fans out to many kinds of destination (feeds, GitHub Releases,
Homebrew, docs) — the DeploymentTarget of Fallout-build#334, per ADR-0009.

- New experimental types (FALLOUT005): IPublishTarget, Artifact/ArtifactKind,
  Channel, DeploymentEnvironment, DeploymentContext, and a GitHubReleaseTarget
  stub (deploy path builds on GitHubReleaseTasks from ADR-0001, tracked by Fallout-build#334).
- PublishTarget now implements IPublishTarget: it is the NuGet-feed provider and
  owns its own DeployAsync (the push logic moved off IPublish.Publish onto the
  target). IPublish.PublishTargets returns IEnumerable<IPublishTarget>; Publish
  builds one immutable artifact and deploys it to each accepting target.
- TransitionShimGenerator now skips [Experimental] types — they are new, opt-in
  surface with no pre-rename Nuke.* consumers to bridge, and shimming them leaked
  the error-by-default experimental diagnostic into generated code.
- Register FALLOUT005 in the experimental-API registry.

First cut for a draft/discussion PR. Deferred to refinement: the GitHub provider
implementations (GitHubReleaseTasks, GitHubEnvironment sync), the reusable
publish workflows, Homebrew/docs targets, and diagram generation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChrisonSimtian ChrisonSimtian added enhancement New feature or request target/vCurrent Targets the current version labels Jul 17, 2026
- Consolidate the six behavioural partials (CodeGeneration, PublicApi,
  Licenses, Contributors, Stargazers, GlobalSolution) into a single
  Build.Maintenance.cs, and drop the Build.RunTargetInDockerTest.cs demo
  target. The attribute-bearing partials (Build.CI.GitHubActions,
  Build.Terminal) stay separate — class-level attributes can't be merged.
  build/ goes from 10 .cs files to 4.
- Fix .editorconfig end_of_line crlf -> lf so it matches the repo (all LF
  via .gitattributes); crlf made dotnet format rewrite the whole tree and
  unusable. Build files now pass dotnet format cleanly.
- Sort usings, drop a stray private modifier, normalize attribute spacing,
  and replace legacy new string[0] with [].
- Correct conventions.md + CONTRIBUTING.md: they claimed .editorconfig /
  *.DotSettings were removed, but both exist and are actively curated.

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

Labels

enhancement New feature or request target/vCurrent Targets the current version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant