Skip to content

ci: pin the .NET SDK and harden the release gates - #167

Merged
VPDPersonal merged 1 commit into
mainfrom
ci/release-pipeline-hardening
Aug 6, 2026
Merged

ci: pin the .NET SDK and harden the release gates#167
VPDPersonal merged 1 commit into
mainfrom
ci/release-pipeline-hardening

Conversation

@VPDPersonal

Copy link
Copy Markdown
Owner

Summary

  • 🔧 Add a root global.json pinning the .NET SDK to 10.0.300 (rollForward: disable) so CI and the local machine build the Roslyn DLLs with the identical toolchain; both workflows now install it via setup-dotnet global-json-file (6.0.x kept alongside for the net6.0 test runtime).
  • release.yml now runs the Generators and Analyzers test suites before tagging — Debug on purpose, so a test run can never touch the shipped Release DLLs.
  • 🛡️ Replace the "generator DLL is non-empty" check with a real freshness gate: rebuild both Roslyn projects in Release (Directory.Build.targets re-deploys the DLLs into the package) and fail on git diff --exit-code over both DLLs. This also finally covers Aspid.FastTools.Analyzers.dll, which the release workflow never verified after the analyzer merge (chore(analyzers): fold the analyzer submodule into the main repo #152).
  • 📝 Guard that the package CHANGELOG.md, once it exists, is byte-identical to the root CHANGELOG.md; the step skips while the package copy doesn't exist.

Notes for review

  • ⚠️ Merge order: after build/release-gate-deterministic-dlls. Without <Deterministic> + <ContinuousIntegrationBuild> a rebuild is not byte-reproducible, so the freshness gate would fail on every release (verified locally: today's rebuild produces binary-different DLLs of identical size). After that branch lands, the DLLs need one rebuild + commit with the pinned SDK.
  • 📝 The CHANGELOG sync guard stays dormant until docs/changelog-catchup adds the package CHANGELOG.md, then activates automatically.
  • 🔧 Why rollForward: disable: setup-dotnet installs exactly the version from global.json, while a silent local patch roll-forward (e.g. 10.0.301) would produce byte-different DLLs and a confusing gate failure at release time — better to fail fast at dotnet startup.
  • ✅ Step order matters: on current main the generator deploy is not yet Release-only, so a Debug test run overwrites the package DLL — the subsequent Release rebuild overwrites it again before the diff, keeping the gate correct either way.
  • 🧪 tests.yml is intentionally still not triggered by tags: release.yml now runs both suites itself.
🇷🇺 Описание на русском

Кратко

  • 🔧 Корневой global.json пинит .NET SDK 10.0.300 (rollForward: disable) — CI и локальная машина собирают Roslyn-DLL одним тулчейном; оба workflow ставят его через setup-dotnet global-json-file (6.0.x остаётся для net6.0-рантайма тестов).
  • release.yml теперь гоняет тесты Generators и Analyzers до тегирования — намеренно в Debug, чтобы прогон тестов не мог затронуть поставляемые Release-DLL.
  • 🛡️ Проверка «DLL генератора непустая» заменена настоящим гейтом свежести: Release-пересборка обоих Roslyn-проектов (Directory.Build.targets сам разворачивает DLL в пакет) и git diff --exit-code по обеим DLL. Заодно впервые проверяется Aspid.FastTools.Analyzers.dll, который релизный workflow не верифицировал после вливания анализаторов (chore(analyzers): fold the analyzer submodule into the main repo #152).
  • 📝 Guard синхронности: CHANGELOG.md пакета, как только появится, обязан быть байт-в-байт равен корневому; пока файла нет — шаг пропускается.

Заметки для ревью

  • ⚠️ Порядок merge: после build/release-gate-deterministic-dlls. Без <Deterministic> + <ContinuousIntegrationBuild> пересборка не воспроизводима байт-в-байт, и гейт свежести падал бы на каждом релизе (проверено локально: сегодняшняя пересборка даёт бинарно другие DLL того же размера). После merge той ветки DLL нужно один раз пересобрать и закоммитить пиненым SDK.
  • 📝 Guard changelog «спит», пока docs/changelog-catchup не добавит CHANGELOG.md в пакет, затем включается сам.
  • 🔧 Почему rollForward: disable: setup-dotnet ставит ровно версию из global.json, а тихий локальный roll-forward патча дал бы байт-различие DLL и невнятное падение гейта на релизе — лучше падать сразу при запуске dotnet.
  • ✅ Порядок шагов важен: на текущем main деплой генератора ещё не Release-only, и Debug-тесты затирают DLL пакета — последующая Release-пересборка перезаписывает её снова до diff, так что гейт корректен в обоих случаях.
  • 🧪 tests.yml по-прежнему намеренно не триггерится тегами: release.yml теперь сам гоняет оба набора тестов.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LsVLAxv4eia9yv4TjSaP3G

- Add root global.json pinning SDK 10.0.300 (rollForward: disable) so CI
  and the local machine build the Roslyn DLLs with the same toolchain;
  both workflows now install it via setup-dotnet global-json-file.
- release.yml: run the Generators and Analyzers test suites (Debug, so a
  test run can never touch the shipped Release DLLs).
- release.yml: replace the "generator DLL is non-empty" check with a real
  freshness gate — rebuild both solutions in Release (Directory.Build.targets
  re-deploys the DLLs into the package) and fail on git diff, covering the
  analyzer DLL that the workflow never verified before.
- release.yml: guard that the package CHANGELOG.md, once it exists, stays
  byte-identical to the root CHANGELOG.md.
- tests.yml: build with the pinned SDK from global.json (6.0.x kept for
  the net6.0 test runtime).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsVLAxv4eia9yv4TjSaP3G
@VPDPersonal VPDPersonal added type: ci CI / build pipeline changes status: blocked Blocked by another change or external factor area: ci CI / GitHub Actions workflows labels Aug 6, 2026
@VPDPersonal
VPDPersonal marked this pull request as ready for review August 6, 2026 18:43
@VPDPersonal
VPDPersonal merged commit 6742380 into main Aug 6, 2026
@VPDPersonal
VPDPersonal deleted the ci/release-pipeline-hardening branch August 6, 2026 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI / GitHub Actions workflows status: blocked Blocked by another change or external factor type: ci CI / build pipeline changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant