IPublish multi-target in order to allow us to publish both GH and Nuget.org at the same time (plus gating)#342
Merged
Conversation
ChrisonSimtian
force-pushed
the
promote/multichannel-publish-to-main
branch
from
June 9, 2026 08:29
3e5fb74 to
906828c
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Promotes the experimental multi-channel publishing feature onto main by introducing routable publish targets (PublishTarget + PublishPackageRouter), extending IPublish with an [Experimental("FALLOUT001")] multi-target publish surface, and dogfooding it in the preview/experimental GitHub Actions workflows.
Changes:
- Add
PublishTarget+PublishPackageRouterrouting (glob include/exclude, skip-duplicate) with a newFallout.Components.Testsproject covering the routing behavior. - Extend
IPublishwith[Experimental("FALLOUT001")] PublishTargetsand--publish-to, and updatebuild/Build.csto definegithub-packagesandnuget.orgchannels with package-ID routing. - Update workflows/docs to use the new GitHub Packages feed URL (
Fallout-build) and switch preview/experimental lanes todotnet fallout Publish.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Fallout.SourceGenerators.Tests/StronglyTypedSolutionGeneratorTest.Test#Solution.g.verified.cs | Updates verified generator output to include the new Fallout.Components.Tests project. |
| tests/Fallout.Components.Tests/PublishPackageRouterTests.cs | Adds unit tests for glob matching and include/exclude routing behavior. |
| tests/Fallout.Components.Tests/Fallout.Components.Tests.csproj | Introduces the new test project for Fallout.Components. |
| src/Shims/Nuke.Components/README.md | Updates GitHub Packages feed URL for shim consumption. |
| src/Shims/Nuke.Common/README.md | Updates GitHub Packages feed URL references and examples. |
| src/Shims/Nuke.Build/README.md | Updates GitHub Packages feed URL for shim consumption. |
| src/Fallout.Components/PublishTarget.cs | Adds the publish target model and pure routing helper used by IPublish. |
| src/Fallout.Components/IPublish.cs | Implements experimental multi-target publish selection and per-target push behavior. |
| fallout.slnx | Adds the new Fallout.Components.Tests project to the solution. |
| docs/migration/from-nuke.md | Updates migration documentation to the new GitHub Packages feed URL. |
| docs/experimental-apis.md | Registers FALLOUT001 and documents the experimental surface. |
| docs/agents/release-and-versioning.md | Updates release/publish documentation to the new GitHub Packages feed URL. |
| CHANGELOG.md | Updates the shim feed URL reference in historical notes. |
| build/Build.cs | Wires real publish channels via IPublish.PublishTargets and relaxes prior publish gating. |
| .github/workflows/release.yml | Updates the GitHub Packages feed URL used for shim pushes. |
| .github/workflows/preview.yml | Switches preview publishing to dotnet fallout Publish --publish-to github-packages and fixes token env usage. |
| .github/workflows/experimental.yml | Switches experimental publishing to dotnet fallout Publish --publish-to github-packages and fixes token env usage. |
| .github/CODEOWNERS | Updates code ownership to the @Fallout-build/maintainers team for src/ and tests/. |
…he lanes (#333) (#339) * feat(publish): multi-channel, package-ID-aware publishing surface (#333, FALLOUT001) IPublish gains [Experimental("FALLOUT001")] PublishTargets + a --publish-to selector; Publish now routes one Pack output across multiple feeds via the pure, unit-tested PublishPackageRouter (glob include/exclude by package name). Existing single-source members stay as a back-compat default target. Build.cs wires the two real channels: github-packages (every package incl Nuke.*, keyed by the GitHub token) and nuget.org (Fallout.* only, never Nuke.*, keyed by NUGET_API_KEY) — replacing the legacy single-feed push. - src/Fallout.Components/PublishTarget.cs — PublishTarget record + PublishPackageRouter - tests/Fallout.Components.Tests — 10 router tests (added to fallout.slnx) - docs/experimental-apis.md — FALLOUT001 registered Framework compiles clean (0 errors); router tests green. Workflow rewire to `dotnet fallout Publish --publish-to …` follows once experimental is synced with main. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * ci(publish): dogfood `dotnet fallout Publish` on the alpha/preview lanes (#333) experimental.yml and preview.yml now publish via `dotnet fallout Publish --publish-to github-packages` instead of a hand-rolled `dotnet nuget push` loop. Publish depends on Test + Pack, so one invocation runs Restore → Compile → Test → Pack → Publish as NUKE stages; package routing (Fallout.* + Nuke.* → GitHub Packages) lives in Build.cs IPublish.PublishTargets. The GitHub token is passed via the GitHubToken env. Also restore IPublish.PackagePushSettings + PushSettingsBase (kept for back-compat) so the multi-channel reshape stays additive — the new PublishTargets/PublishTo surface is the only opt-in change, behind [Experimental("FALLOUT001")]. release.yml's publish jobs still use raw nuget push (they're coupled to the artifact handoff + nuget-org approval gate) — dogfooding those is folded into #336. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(publish): make PublishTarget a sealed class so the shim generator skips it CI caught CS0509: the TransitionShimGenerator tried to derive a Nuke.Components shim from the sealed *record* PublishTarget. Sealed classes are skipped by design (SHIM001), but the sealed-record shape slipped past that guard. PublishTarget is a new type with no pre-rename consumers, so skipping its shim is correct; switching record→sealed class hits the documented skip path. We don't use record equality/`with`. Verified: Nuke.Components builds 0 errors (SHIM001 warning only). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(generators): accept solution-generator snapshot for new Fallout.Components.Tests Adding tests/Fallout.Components.Tests to fallout.slnx makes the StronglyTypedSolution generator emit a Fallout_Components_Tests accessor; update the Verify snapshot to match (one added line — the new project's strongly-typed Solution property). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… (#340) The dogfood `dotnet fallout Publish` run failed with "Publish target 'github-packages' has no API key". The github-packages target resolves its key via From<ICreateGitHubRelease>().GitHubToken → GitHubActions.Token, which reads the GITHUB_TOKEN env var (EnvironmentInfo.GetVariable("GITHUB_TOKEN")). The lane workflows set `GitHubToken` instead, which didn't match (ICreateGitHubRelease is also [ParameterPrefix]-ed, so the unprefixed name wouldn't bind anyway). Set GITHUB_TOKEN. Caught by letting the post-merge experimental publish actually run. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This promotion branch was cherry-picked before the repo transfer, so it still carried the old ChrisonSimtian GitHub Packages feed URL + CODEOWNERS. Align it with the post-transfer main/experimental so merging it doesn't re-introduce the dead feed: feed → Fallout-build, CODEOWNERS → @Fallout-build/maintainers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot Autofix (86aa4b6) removed `using System.Diagnostics.CodeAnalysis;` as apparently-unused, but IPublish still applies [Experimental("FALLOUT001")] on PublishTargets/PublishTo — so the build broke with CS0246 (ExperimentalAttribute could not be found) on the PR validation lanes. Re-add the using; framework compiles clean, router tests green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChrisonSimtian
force-pushed
the
promote/multichannel-publish-to-main
branch
from
June 14, 2026 01:12
db43cf9 to
7547fc7
Compare
Restore a defense-in-depth guard on the Fallout build's Publish target and fail fast on misconfigured publish targets. - Build.cs: require Host is GitHubActions on Publish. GitHubToken binds from the GITHUB_TOKEN env var, which developers commonly export, so without a guard a stray local `dotnet fallout Publish` (no --publish-to selects all targets) would push to GitHub Packages. The CI guard blocks local pushes while still allowing every CI lane (experimental/preview/release). - IPublish.Publish: hoist the per-target API-key check out of the push loop into the pre-flight validation block. A missing key is a config error knowable before any push, so we now fail fast instead of pushing some feeds and breaking half-way. Per-push failures stay independent (PushCompleteOnFailure). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChrisonSimtian
added a commit
that referenced
this pull request
Jun 14, 2026
## Problem The post-merge **preview CD on `main`** (from #342) went red. The target summary tells the real story — the feature works, a *different* target failed: | Target | Result | |---|---| | Test | ✅ Passed: 470, Skipped: 7 | | Pack | ✅ Packages: 22 | | **Publish** | ✅ **0:07 — pushed 22 packages to GitHub Packages** | | CreateGitHubRelease | ❌ `NotFoundException: Not Found` | So `dotnet fallout Publish --publish-to github-packages` (the #333 dogfooding) did exactly its job. The job failed on `CreateGitHubRelease` getting dragged into the run. ## Root cause `ICreateGitHubRelease.CreateGitHubRelease` is `.TriggeredBy<IPublish>()` and was gated only on `.OnlyWhenStatic(() => GitRepository.IsOnMainBranch())`. Before #333, `Publish` ran **only in the release workflow** (its old `.Requires` gated on `Workflow == ReleaseWorkflow`). #333 replaced that with `.Requires(Host is GitHubActions)` so the preview/experimental lanes could dogfood `Publish`. Because **preview pushes to `main`**, the `IsOnMainBranch()` gate now passes and a GitHub Release is attempted on every preview push. (Experimental is unaffected — not on `main`, so the `OnlyWhen` skips it.) GitHub Releases are **production-only** in the channel model. `release.yml` hand-rolls them via `gh release create` (the `publish-github-releases` job) and doesn't invoke this C# target at all. ## Fix Gate `CreateGitHubRelease` to the release workflow (`GitHubActions?.Workflow == ReleaseWorkflow`) instead of just `IsOnMainBranch()`, so it stays dormant on preview/experimental publishes. ## Validation `dotnet build build/_build.csproj` clean. Merging this re-triggers the preview lane on `main`, which should now go green (Publish succeeds, CreateGitHubRelease skipped). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Promotes #333 from
experimental→main(the-previewtrunk) for human review ahead of becoming an RC feature. Curated cherry-pick of the feature commits (#339 + #340) — deliberately not a branch merge, somain'sversion.jsonstays-preview(experimental's-alphaidentity is left behind).What's promoted
PublishTarget+ purePublishPackageRouter(10 unit tests,Fallout.Components.Tests)IPublish[Experimental("FALLOUT001")]PublishTargets+--publish-to— fans onePackacross feedsBuild.cschannels:github-packages(all, incl.Nuke.*) +nuget.org(Fallout.*only)experimental.yml/preview.ymlnow dogfooddotnet fallout Publishinstead of hand-rolleddotnet nuget pushWhy it's safe to promote
[Experimental("FALLOUT001")]-gated, and the legacy single-feed members are retained.experimental: full Test+Pack green, and the post-mergeexperimentalpublish ran for real —dotnet fallout Publish --publish-to github-packagespublished-alphapackages successfully (the token-env fix fix(ci): publish token env var GitHubToken → GITHUB_TOKEN (#333) #340 came out of that live run).Reviewer notes
[Experimental]attribute stays until the surface is promoted to stable (attribute removed) once the CD model (First-class ReleaseChannel / DeploymentTarget / Environment model #334) settles — this is the preview/RC staging step, not stabilization.release.ymlstill uses rawdotnet nuget push(coupled to the artifact handoff +nuget-orgapproval gate) → folded into [GitHubActions] generator: emit CD pipelines (or a thin shell delegating to dotnet fallout Deploy) #336.Part of epic #332. Issue #333 stays open until this merges to
main.🤖 Generated with Claude Code