Skip to content

chore(ci): roll-up of #10, #11, #12 into develop#13

Merged
ChrisonSimtian merged 4 commits into
developfrom
chore/drop-qodana
May 18, 2026
Merged

chore(ci): roll-up of #10, #11, #12 into develop#13
ChrisonSimtian merged 4 commits into
developfrom
chore/drop-qodana

Conversation

@ChrisonSimtian

Copy link
Copy Markdown
Collaborator

Summary

Roll-up PR. The previous stacked PRs (#10, #11, #12) were merged into their immediate base branches but never propagated up to `develop`. This brings them onto develop in one move.

Squashes onto develop

What ships with this merge

Area Change
Branch model Trunk-based — `main` is the only long-lived branch
CI providers GitHub Actions only (Qodana also gone)
PR validation Ubuntu only, with `paths-ignore` for docs/images/markdown
Post-merge validation Ubuntu + Windows + macOS on push to main
Release pipeline Inert — restored by the upcoming Nerdbank PR

Cutover ceremony — manual steps after this merges

  1. Rename `develop` → `main` on GitHub. Auto-retargets remaining open PR (chore(deps): patch vulnerable transitives (CVE-2026-33116, Scriban) #4). `main` becomes default branch automatically.
  2. Delete the now-orphan intermediate branches: `chore/ci-purge-non-github`, `feat/trunk-migration`, `chore/drop-qodana`, `chore/ci-linux-only-on-prs`.
  3. The validation workflows on the renamed branch will trigger again once a PR is opened against `main`.

Test plan

🤖 Generated with Claude Code

ChrisonSimtian and others added 4 commits May 18, 2026 15:37
Replaces the GitFlow branch model (develop/release/*/master/hotfix/*)
with trunk-based — single `main` branch, short-lived feature/bugfix/
chore branches off main, every merge can publish a release.

Build code:
- Build.cs: drop MasterBranch/DevelopBranch/ReleaseBranchPrefix/
  HotfixBranchPrefix constants, replace with MainBranch = "main".
  Update IsPublicRelease and IPublish.Publish.Requires logic to check
  IsOnMainBranch instead of master/release/develop.
- Build.cs: absorb MajorMinorPatchVersion + MilestoneTitle + Major
  parameter from the deleted Build.GitFlow.cs.
- Build.CodeGeneration.cs, Build.Announce.cs: master → main references.
- Build.GitFlow.cs: DELETED. Contained Milestone/Changelog/Release/
  Hotfix targets that were entirely GitFlow-specific.
- Build.CI.GitHubActions.cs: branch filters main-ified, paths-ignore
  added for docs/images/markdown. Alpha-deployment workflow attribute
  removed; AlphaDeployment constant retained with a comment because
  several code paths (Test.OnlyWhen, Pack.PackSettings, Publish.Requires,
  DeletePackages) still reference it — they evaluate to false until the
  follow-up Nerdbank/release PR brings a workflow back under a new name.

Workflows:
- ubuntu/windows/macos-latest.yml: regenerated to match attributes.
  `branches-ignore: [main]` for push, `branches: [main]` + paths-ignore
  for pull_request.
- alpha-deployment.yml: removed.

Docs:
- CLAUDE.md: updated branching section to describe trunk-based.

Sequencing note: the default branch on GitHub (develop) has NOT been
renamed yet. Recommended ceremony:
  1. Merge any in-flight PRs against develop (so their CI runs cleanly)
  2. Merge this PR into develop
  3. Rename develop → main on GitHub (auto-retargets remaining PRs)
  4. Set main as default branch (automatic with the rename)

Between steps 2 and 3 no CI will trigger for new PRs, because the
workflows on develop now point at main. Keep the gap short.

Public release publishing is currently inert (no workflow invokes
Publish). The next PR adds Nerdbank.GitVersioning and a real release
workflow.

Refs #7

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the JetBrains Qodana static-analysis workflow and its
artifacts. It has been failing on every run on this fork because the
QODANA_TOKEN secret belonged to the previous maintainer's account.

Files removed:
- .github/workflows/code-quality.yml — the JetBrains/qodana-action job
- qodana.yml — local Qodana config
- qodana.sarif.json — 6.9MB baseline of suppressed findings from the
  previous maintainer's scans

The security-scanning gap will be filled by CodeQL — see
#8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously every push to a non-main branch and every PR triggered
Test+Pack on Ubuntu, Windows, and macOS in parallel — 3x the runtime
and credits per change. Cross-OS coverage matters more on what's
actually shipping, less on every in-flight branch.

New behavior:
- ubuntu-latest.yml: triggers as before (push to non-main, PRs to main,
  paths-ignore for docs/images/markdown) — fast Linux feedback loop.
- windows-latest.yml, macos-latest.yml: trigger only on push to main
  (post-merge / release pipeline).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore(ci): Linux-only validation on PRs; full matrix only on main
@ChrisonSimtian ChrisonSimtian merged commit 8734570 into develop May 18, 2026
1 check passed
@ChrisonSimtian ChrisonSimtian deleted the chore/drop-qodana branch May 18, 2026 04:02
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
#268)

Auto-publish on every push to main has been firing a Fallout.* release on
every merge — about 20 patch versions in recent days for what was mostly
internal cleanup (license-header strip, doc updates, etc). That generates a
Dependabot upgrade PR in every downstream consumer repo, every morning.

The proper restructure (tag-triggered publishes on release/vN branches with
three GitHub Environments — nuget-org / github-packages / github-releases)
is tracked under milestone #13 / RFC #267. Until that lands, this stopgap
disables the auto-trigger and switches the release workflow to manual
workflow_dispatch only.

What changes for maintainers:
- Releases no longer happen automatically on merge to main.
- To cut a release: Actions → "release" → "Run workflow" → pick the ref.
- Cherry-pick + tag flow on release/vN branches arrives with the full
  restructure under #13.

What changes for consumers: dependabot stops screaming.

Refs #267, milestone #13.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
…ease/vN (#270) (#278)

Updates docs/agents/release-and-versioning.md to reflect the new branching
model now that release/v11 has been cut (#269) and the auto-publish stopgap
landed (#268).

Branching section:
- main is now the integration trunk (PRs target here), no longer auto-publishes
- release/vN is the release channel per major (release/v11 exists; release/v12
  will follow when v12 ships)
- Hotfix flow noted as "cherry-pick from main"
- Stale "No release/* branches" line removed

New "Branch protection on release/vN" subsection captures the policy that
gets applied to every release/vN at cut time:
- Required ubuntu-latest status check
- Linear history
- CODEOWNER review required
- Stale-approval dismissal
- Direct pushes / force-pushes / deletions blocked
- Conversation resolution required
- Admins can bypass in emergencies

Release pipeline section updated to acknowledge the workflow_dispatch
stopgap and reference the pending tag-triggered shape under #274, and the
NUGET_API_KEY move-to-environment-secret under #273.

Closes #270 (the API-level branch protection on release/v11 was already
applied; this PR is the documentation half of the acceptance criteria).

Refs milestone #13, RFC #267.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
Branch protection on `release/v11` (applied in #270) requires the
`ubuntu-latest` status check, but `.github/workflows/ubuntu-latest.yml`
and `.github/workflows/ubuntu-latest-docs.yml` only fired on PRs
targeting `main`. Net effect: PRs against `release/v11` had no CI and
got BLOCKED by branch protection waiting for a check that never reported
— a chicken-and-egg that surfaced when #290 (the NB.GV publicReleaseRefSpec
tweak) couldn't merge.

Changes:

- Both workflows now list `main` AND `release/v*` under `pull_request.branches:`.
- `build/Build.cs` gains a `ReleaseBranchPattern = "release/v*"` constant
  alongside `MainBranch`.
- `build/Build.CI.GitHubActions.cs` extends `OnPullRequestBranches` on the
  ubuntu-latest `[GitHubActions]` attribute to include both branches, so
  next time the auto-generator runs it produces the same YAML.

Out of scope: `windows-latest` and `macos-latest` stay `OnPushBranches`
only (post-merge / release validation). They run after merge regardless
of base branch via the push trigger.

After this lands on main, the same workflow files need to be brought
across to `release/v11` (separate PR — same chicken-and-egg until release/v11
also has the updated workflows; will be admin-bypass-merged once).

Refs milestone #13. Unblocks #290.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
Refactors .github/workflows/release.yml from the workflow_dispatch-only
stopgap (#268) into the proper release-branch model shape per RFC #267
and milestone #13.

## Trigger

- push: tags 'v*' is the primary trigger. The new validate-ref job
  verifies the tag is reachable from a release/v* branch and fails fast
  otherwise.
- workflow_dispatch with a required `tag` input remains as a fallback
  for re-runs after a transient API failure. --skip-duplicate on each
  publish step keeps re-runs idempotent.

## Job graph

  validate-ref (skipped on workflow_dispatch)
      ↓
  test-and-pack (Test + Pack via `dotnet fallout`, uploads
                 output/packages/*.nupkg as Actions artifact)
      ↓ ↓ ↓  (fan-out)
  publish-nuget-org       (env: nuget-org,       Fallout.*.nupkg → nuget.org,    gated)
  publish-github-packages (env: github-packages, Nuke.*.nupkg → GH Packages,    unguarded)
  publish-github-releases (env: github-releases, all *.nupkg → GH Release,      unguarded)

Each publish job declares `environment:` so a per-channel deployment
record appears under the Deployments tab. The nuget-org env requires
approval (set in #272); the other two are unguarded.

## Channel routing

- nuget.org gets ONLY Fallout.* — Nuke.* shim IDs belong to the
  original NUKE maintainer on nuget.org (#47).
- GitHub Packages gets the Nuke.* shims — preserves the existing
  behaviour from the previous workflow.
- GitHub Releases gets all *.nupkg attached to the tag's release page,
  with auto-generated notes via `gh release create --generate-notes`.
  Idempotent — if the release already exists (workflow_dispatch retry),
  uploads/replaces assets via --clobber.

## Tag protection ruleset (applied separately via API)

A repository ruleset now blocks creation/deletion/update of tags
matching v* for non-admins. Bypass actors: RepositoryRole 5 (admin).
Combined with the env approval gate on nuget-org, this gates
production releases at two layers.

The ruleset is configured via API rather than in this YAML
(ruleset:17017817). It was created in the same change but lives in
repo Settings → Rules, not in the workflow file.

## Build.cs not touched

The existing `IPublish.Publish` target and `ICreateGitHubRelease` from
Build.cs are bypassed by this workflow — CI now calls `dotnet nuget
push` and `gh release create` directly. The targets are still available
for local invocation; consolidating or removing them is a follow-up.

## Docs

docs/agents/release-and-versioning.md "Release pipeline" section
rewritten to describe the new shape (trigger, jobs, channel routing,
tag protection, fallback dispatch).

CHANGELOG entry deferred to the umbrella docs PR #276 per the pattern
set in earlier sub-issues — one consolidated v11-restructure entry
rather than fragmented per-PR entries.

Refs #274, milestone #13.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
Branch protection on `release/v11` (applied in #270) requires the
`ubuntu-latest` status check, but `.github/workflows/ubuntu-latest.yml`
and `.github/workflows/ubuntu-latest-docs.yml` only fired on PRs
targeting `main`. Net effect: PRs against `release/v11` had no CI and
got BLOCKED by branch protection waiting for a check that never reported
— a chicken-and-egg that surfaced when #290 (the NB.GV publicReleaseRefSpec
tweak) couldn't merge.

Changes:

- Both workflows now list `main` AND `release/v*` under `pull_request.branches:`.
- `build/Build.cs` gains a `ReleaseBranchPattern = "release/v*"` constant
  alongside `MainBranch`.
- `build/Build.CI.GitHubActions.cs` extends `OnPullRequestBranches` on the
  ubuntu-latest `[GitHubActions]` attribute to include both branches, so
  next time the auto-generator runs it produces the same YAML.

Out of scope: `windows-latest` and `macos-latest` stay `OnPushBranches`
only (post-merge / release validation). They run after merge regardless
of base branch via the push trigger.

After this lands on main, the same workflow files need to be brought
across to `release/v11` (separate PR — same chicken-and-egg until release/v11
also has the updated workflows; will be admin-bypass-merged once).

Refs milestone #13. Unblocks #290.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
Per NB.GV validation (#275 finding), release/v11 was producing
git-sha-suffixed versions like `11.0.19-g4b19a8c1` instead of clean
`11.0.19` because the branch wasn't in `publicReleaseRefSpec`. With
#274 about to make tag-triggered releases fire from this branch, the
suffix would land on nuget.org under what looks like a clean v11.0.X
tag — confusing for consumers and not what the tag implies.

Adds `^refs/heads/release/v11$` to publicReleaseRefSpec. This branch
now produces clean version strings on commits + tag heights.

Lands directly on release/v11 (not main) because:
- main is still 11.0 and adding release/v11 to main's publicReleaseRefSpec
  would create a height collision (both branches public-mapped to the
  same version).
- The setting is intentionally branch-specific to how release/v11
  generates versions — not something that needs to propagate forward
  to main / future release/v12.

main's publicReleaseRefSpec is unchanged. When #271 lands and bumps
main to 12.0, the equivalent edit will happen on release/v12 (or
whatever the next major's release branch is named).

Refs #275, milestone #13.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
Per NB.GV validation (#275 finding), release/v11 was producing
git-sha-suffixed versions like `11.0.19-g4b19a8c1` instead of clean
`11.0.19` because the branch wasn't in `publicReleaseRefSpec`. With
#274 about to make tag-triggered releases fire from this branch, the
suffix would land on nuget.org under what looks like a clean v11.0.X
tag — confusing for consumers and not what the tag implies.

Adds `^refs/heads/release/v11$` to publicReleaseRefSpec. This branch
now produces clean version strings on commits + tag heights.

Lands directly on release/v11 (not main) because:
- main is still 11.0 and adding release/v11 to main's publicReleaseRefSpec
  would create a height collision (both branches public-mapped to the
  same version).
- The setting is intentionally branch-specific to how release/v11
  generates versions — not something that needs to propagate forward
  to main / future release/v12.

main's publicReleaseRefSpec is unchanged. When #271 lands and bumps
main to 12.0, the equivalent edit will happen on release/v12 (or
whatever the next major's release branch is named).

Refs #275, milestone #13.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
…book + ADR (#276, #277) (#295)

Closes #276 and #277. Captures the full milestone #13 outcome in three
places now that all the moving parts are in production:

CONTRIBUTING.md
- "Where to start" updated: PRs target main, releases ship from
  release/vN, hotfix flow noted.
- "After opening a PR" updated to reflect ubuntu-latest now firing on
  release/v* PRs too (post #291/#292), with the windows/macos parity
  follow-up linked (#293).
- New "Releases" section pointing contributors at the maintainer
  runbook.

docs/branching-and-release.md (new)
- Maintainer reference: branches at a glance, channel taxonomy, full
  step-by-step for cutting a release (gh release create + the env
  approval-gate prompt), hotfix workflow (cherry-pick recipe),
  workflow_dispatch fallback for re-running partial publishes, cutting
  a new release/vN, deprecating an old one, tag-protection ruleset.

docs/adr/0001-release-branch-model.md (new — seeds docs/adr/)
- Architecture Decision Record covering Context (consumer-facing noise
  from auto-release; no hotfix path), Decision (the model), and
  Consequences (positive + negative + neutral). Includes the four
  alternatives we considered and rejected.
- Cites the consumer-pain-first principle (saved as agent memory)
  that drove the cutover timing.
- Status: Accepted. Implementation already shipped.

AGENTS.md
- "Where to look next" links the new branching-and-release.md doc and
  the docs/adr/ directory so AI agents reading the brief discover them.

CHANGELOG.md
- Umbrella entry for milestone #13 under [Unreleased] — 11.0 → Process,
  summarising all sub-issues that landed: #269, #270, #272, #273, #274,
  #275, #291, #292. Per the pattern set in #269's closing comment — one
  consolidated entry rather than nine fragmented per-sub-issue entries.

Refs milestone #13, RFC #267.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
Closes #293. Parity follow-up to #291 (which extended PR-validation
triggers to release/v*). After this:

- windows-latest.yml — pull_request trigger unchanged (still PR-only on
  main, by design); push trigger extends to main AND release/v*.
- macos-latest.yml — same.
- build/Build.CI.GitHubActions.cs — OnPushBranches on both windows and
  macos [GitHubActions] entries gain ReleaseBranchPattern alongside
  MainBranch, so next auto-regen produces matching YAML.

Effect: a hotfix merged to release/v11 now triggers Windows + macOS
post-merge validation, same as merges to main. Cross-platform
regressions in release-branch hotfixes surface immediately as red
commits on the release branch, not later when someone tries to cut a
release.

Out of scope: extending pull_request triggers on windows/macos to fire
on release/v* PRs. The current PR gate (ubuntu-latest only) is a
deliberate cost trade-off documented in docs/agents/release-and-versioning.md.

Refs milestone #13.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
…default channel (#299)

Implements the v11-off-nuget direction. Tag pushes on release/v11 no
longer auto-publish to nuget.org — they publish to GitHub Packages +
GitHub Releases only. To publish Fallout.* to nuget.org you must
invoke workflow_dispatch with `publish-to-nugetorg=true`, an explicit
"this release is stabilised enough for nuget.org" switch.

This *modifies* the routing originally documented in milestone #13's
release.yml refactor (#288). The release-branch model, multi-channel
fan-out, and CD gating are all unchanged — only the routing policy
shifts.

## Workflow changes (`.github/workflows/release.yml`)

- New `workflow_dispatch` input `publish-to-nugetorg` (boolean, default false).
- `publish-nuget-org` job gains `if:` condition requiring both
  `github.event_name == 'workflow_dispatch'` and
  `inputs.publish-to-nugetorg == true`. Tag pushes skip this job.
- `publish-github-packages` job changes its glob from `Nuke.*.nupkg`
  to `*.nupkg` — now publishes both Fallout.* and Nuke.* to GH Packages.
  GH Packages is the v11 release channel; Nuke.* shim routing per #47
  is preserved (still goes here permanently).
- Header comment + per-job comments rewritten to describe the new
  routing policy explicitly.

Three layers of safety on the nuget.org path now:
  1. Tag protection ruleset (only repo admins can create v* tags).
  2. workflow_dispatch flag opt-in.
  3. nuget-org env approval gate.

## Doc updates

- `docs/agents/release-and-versioning.md` — Release pipeline section
  rewritten. Table updated. New "Why nuget.org is opt-in for v11"
  subsection. workflow_dispatch inputs documented.
- `docs/branching-and-release.md` — Channel taxonomy table extended
  with "Current v11 use" column. "Cutting a release" split into two
  sub-runbooks: routine (GitHub Packages only) and stabilised (with
  the opt-in flag).
- `docs/adr/0002-v11-off-nuget-by-default.md` — new ADR capturing the
  decision and three rejected alternatives.

## CHANGELOG

Entry under [Unreleased] — 11.0 → Process explicitly noting this
*modifies* the routing originally documented in the milestone #13
umbrella entry (rather than backdating that entry; preserves history
of how the decision evolved).

## Out of scope

- Unlisting existing 11.0.x on nuget.org — separate work (see worktree
  `unlist-10.3` for the parallel 10.3 unlisting).
- When/how v11 transitions to "stabilised" and opts into nuget.org by
  default — a future ADR / decision when that moment arrives.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request May 29, 2026
…13) (#298)

While v11 churns through the rebrand + plugin-foundation work, nothing
should reach the nuget.org userbase. This routes v11 releases to the GH
Packages feed instead:

- Build.cs: IPublish.NuGetSource -> GitHub Packages feed (defensive — the
  Publish target itself can no longer reach nuget.org), NuGetApiKey fed the
  GITHUB_TOKEN.
- release.yml: NuGetApiKey -> secrets.GITHUB_TOKEN; drop the nuget-org
  Environment binding (no nuget.org secret in play). Flags the lost approval
  gate + how to re-add one for GH Packages.

Also lands tools/unlist-v11.0.1-18.json — the record of the 199 existing
11.0.x (package,version) pairs being unlisted from nuget.org (cleanup of
what auto-published between the #220 major bump and the #268 stopgap).

nuget.org stays reserved for the maintenance 10.x line and a future
stabilised v11. Revisit the feed when v11 stabilises.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ChrisonSimtian added a commit that referenced this pull request Jun 3, 2026
…ts (onion step 5b)

Move the concrete CI host providers (AppVeyor, AzurePipelines, TeamCity,
GitHubActions, GitLab, TravisCI, Jenkins, Bitrise, Bitbucket, Bamboo,
SpaceAutomation) and their config generators from Fallout.Common.CI.* to
Fallout.Infrastructure.CI.*.

The Application ring uses provider-SPECIFIC capabilities (PublishTestResults,
PushArtifact, SetBuildNumber, UpdateBuildNumber, Token, …), so a generic host
abstraction can't capture them. Instead, per-provider ports in
Fallout.Application.CI — IAppVeyor/IAzurePipelines/ITeamCity/IGitHubActions —
plus a CiHost accessor that casts the detected Host.Instance to the port (null
when not running on that host). No registration needed: Host.Instance is the
existing detection seam, and the providers (subclasses of Host) implement the
ports. Components (ITest/IReportCoverage/ISignPackages/ICreateGitHubRelease) and
version/coverage attributes now call CiHost.X instead of X.Instance, so the
Application ring keeps no dependency on Fallout.Infrastructure.* — the fitness
gate still passes. The two enums the ports expose move to Fallout.Application.CI
as vocabulary. Nuke.Common CI host shims repointed to the new namespace.

(The generic CI host abstraction — ADR-0005 IBuildHost/IBuildReporter, #341 —
stays a separate additive effort.)

Tooling: OnionRewriter rules retargeted for 5b (CI → Infrastructure.CI, enums
overridden to Application.CI). Lesson #13: alias-qualified `global::Ns.Type`
refs aren't rewritten (Left includes `global::`) — hit in the shims, mopped up.

Full suite green; Application-ring fitness gate green.

Co-Authored-By: Claude Opus 4.8 <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