feat(ci): Phase 3-4 — parallel tests, GitVersion, hotfix workflow, branch protection#9
Conversation
…protection - Add dev branch trigger to ci.yml + GitVersion step for SemVer stamping - Create squad-test.yml: 3 parallel test jobs (Architecture, Unit, Integration) with coverage aggregation and sticky PR comment - Create hotfix-backport-reminder.yml: auto-comment on hotfix merges to main - Fix squad-issue-assign.yml: hardcode 'dev' as base branch GitVersion.yml already present at repo root (main/dev/squad/feature configured). Branch protection applied: main (strict, 1 approval), dev (CI required). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
CI/CD modernization to support the repo’s dev-based branch strategy, add GitVersion-based versioning, and introduce parallelized test execution with coverage reporting.
Changes:
- Extend CI triggers to include
devand add GitVersion setup/execution for version stamping. - Add a new parallel test workflow splitting Architecture/Unit/Integration tests and aggregating coverage into a PR comment.
- Add a hotfix merge reminder workflow and update issue assignment workflow to target
devas the base branch.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| .github/workflows/squad-test.yml | New parallel test workflow + coverage aggregation/commenting. |
| .github/workflows/ci.yml | Adds dev triggers and GitVersion-based version stamping in CI build. |
| .github/workflows/hotfix-backport-reminder.yml | New workflow to auto-comment on merged hotfix PRs into main. |
| .github/workflows/squad-issue-assign.yml | Hardcodes dev as the base branch for agent assignment routing. |
Prevents job failure when coverage files aren't generated (e.g., when build fails upstream). Sticky comment step also needs continue-on-error since it depends on the coverage markdown file existing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Remove deprecated 'mode' key (renamed to 'workflow' in v6, not needed per-branch) - Rename 'is-main-branch' to 'is-mainline' (v6 breaking change) - Remove 'is-main-branch: false' entries (false is default, no need to specify) - GitVersion 6.x cannot parse v5 config and emits non-JSON causing action failure Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…t.yml Test jobs don't consume version outputs - they only need dotnet restore + test. Removing the dependency prevents all tests from being SKIPPED when GitVersion fails. The version job is removed entirely since squad-test.yml is test-only; GitVersion runs in ci.yml for the build step. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SummarySummary
CoverageAppHost - 0%
Domain - 93.4%
ServiceDefaults - 0%
Web - 68.9%
|
…n, coverage comments - Replace dotnet-version/dotnet-quality with global-json-file: global.json (respects pin allowPrerelease: false from global.json) - Use nuGetVersion for /p:Version (preserves prerelease labels e.g. 1.0.0-alpha.1) - Add InformationalVersion for full metadata stamping Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…h trigger, continue-on-error scope - Replace dotnet-version/dotnet-quality with global-json-file: global.json in all 3 jobs - Remove push trigger (PR-only workflow; ci.yml handles push events) - Remove continue-on-error from download-artifact and report generation steps - Keep continue-on-error only on PR comment step (comment posting is optional) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace "Get the default branch name (main, master, etc.)" comment with "Base branch for squad PRs" — accurately reflects that 'dev' is hardcoded intentionally per MyBlog branch strategy. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
GitVersion.yml:8
mode: ContinuousDeliverywas removed from the root/branch configs, which makes GitVersion behavior depend on the tool’s defaults. Since this repo’s docs indicate ContinuousDelivery is the intended strategy, please re-add an explicitmode(either globally or per-branch) so upgrading GitVersion doesn’t silently change versioning semantics.
assembly-versioning-scheme: MajorMinorPatch
assembly-file-versioning-scheme: MajorMinorPatch
tag-prefix: '[vV]'
major-version-bump-message: '\+semver:\s?(breaking|major)'
minor-version-bump-message: '\+semver:\s?(feature|minor)'
patch-version-bump-message: '\+semver:\s?(fix|patch)'
no-bump-message: '\+semver:\s?(none|skip)'
- Add continue-on-error to Install GitVersion and Determine Version steps - Add Set Version fallback step to provide safe defaults if GitVersion fails - Update Build solution to use NUGET_VER env var with fallback to 0.0.0-ci - Set fail-on-empty: false on dorny/test-reporter so missing TRX files (when GitVersion/build fails) don't double-fail the job Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GitVersion v6 changed prevent-increment syntax. The of-merged-branch key causes GitVersion to output a deprecation warning to stdout which breaks the gittools action JSON parsing, silently skipping all build and test steps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| continue-on-error: true | ||
| with: | ||
| versionSpec: '6.x' | ||
|
|
||
| - name: Determine Version | ||
| id: gitversion | ||
| uses: gittools/actions/gitversion/execute@v3 | ||
| continue-on-error: true |
There was a problem hiding this comment.
continue-on-error: true on the GitVersion setup step can silently downgrade version stamping (the job will proceed even if GitVersion can’t be installed). Since the workflow later consumes GitVersion outputs for /p:Version, this step should fail the job on error (remove continue-on-error or gate it behind an explicit opt-out flag).
| continue-on-error: true | |
| with: | |
| versionSpec: '6.x' | |
| - name: Determine Version | |
| id: gitversion | |
| uses: gittools/actions/gitversion/execute@v3 | |
| continue-on-error: true | |
| with: | |
| versionSpec: '6.x' | |
| - name: Determine Version | |
| id: gitversion | |
| uses: gittools/actions/gitversion/execute@v3 |
| - name: Determine Version | ||
| id: gitversion | ||
| uses: gittools/actions/gitversion/execute@v3 | ||
| continue-on-error: true |
There was a problem hiding this comment.
continue-on-error: true on the GitVersion execute step can hide config/repo issues and cause the build to proceed with fallback versions, undermining the SemVer stamping this PR adds. Consider letting this step fail the workflow (and optionally adding a clear error message) so versioning problems are caught immediately.
| continue-on-error: true |
| continue-on-error: true | ||
| with: | ||
| versionSpec: '6.x' | ||
|
|
||
| - name: Determine Version | ||
| id: gitversion | ||
| uses: gittools/actions/gitversion/execute@v3 | ||
| continue-on-error: true | ||
| with: | ||
| useConfigFile: true | ||
|
|
||
| - name: Set Version Variables | ||
| id: version | ||
| run: | | ||
| echo "nuGetVersion=${{ steps.gitversion.outputs.nuGetVersion || '0.0.0-ci' }}" >> "$GITHUB_OUTPUT" | ||
| echo "assemblySemVer=${{ steps.gitversion.outputs.assemblySemVer || '0.0.0' }}" >> "$GITHUB_OUTPUT" | ||
| echo "assemblySemFileVer=${{ steps.gitversion.outputs.assemblySemFileVer || '0.0.0.0' }}" >> "$GITHUB_OUTPUT" | ||
| echo "informationalVersion=${{ steps.gitversion.outputs.informationalVersion || '0.0.0-ci' }}" >> "$GITHUB_OUTPUT" | ||
|
|
There was a problem hiding this comment.
The fallback defaults written to $GITHUB_OUTPUT (e.g., 0.0.0-ci) mean CI can succeed while producing incorrectly stamped assemblies if GitVersion fails or outputs are missing. If version stamping is required, it would be safer to explicitly validate the outputs are present and fail fast when they aren’t (or restrict fallback behavior to non-release contexts).
| continue-on-error: true | |
| with: | |
| versionSpec: '6.x' | |
| - name: Determine Version | |
| id: gitversion | |
| uses: gittools/actions/gitversion/execute@v3 | |
| continue-on-error: true | |
| with: | |
| useConfigFile: true | |
| - name: Set Version Variables | |
| id: version | |
| run: | | |
| echo "nuGetVersion=${{ steps.gitversion.outputs.nuGetVersion || '0.0.0-ci' }}" >> "$GITHUB_OUTPUT" | |
| echo "assemblySemVer=${{ steps.gitversion.outputs.assemblySemVer || '0.0.0' }}" >> "$GITHUB_OUTPUT" | |
| echo "assemblySemFileVer=${{ steps.gitversion.outputs.assemblySemFileVer || '0.0.0.0' }}" >> "$GITHUB_OUTPUT" | |
| echo "informationalVersion=${{ steps.gitversion.outputs.informationalVersion || '0.0.0-ci' }}" >> "$GITHUB_OUTPUT" | |
| with: | |
| versionSpec: '6.x' | |
| - name: Determine Version | |
| id: gitversion | |
| uses: gittools/actions/gitversion/execute@v3 | |
| with: | |
| useConfigFile: true | |
| - name: Set Version Variables | |
| id: version | |
| run: | | |
| nuGetVersion="${{ steps.gitversion.outputs.nuGetVersion }}" | |
| assemblySemVer="${{ steps.gitversion.outputs.assemblySemVer }}" | |
| assemblySemFileVer="${{ steps.gitversion.outputs.assemblySemFileVer }}" | |
| informationalVersion="${{ steps.gitversion.outputs.informationalVersion }}" | |
| if [ -z "$nuGetVersion" ] || [ -z "$assemblySemVer" ] || [ -z "$assemblySemFileVer" ] || [ -z "$informationalVersion" ]; then | |
| echo "::error::GitVersion did not produce all required version outputs." | |
| exit 1 | |
| fi | |
| echo "nuGetVersion=$nuGetVersion" >> "$GITHUB_OUTPUT" | |
| echo "assemblySemVer=$assemblySemVer" >> "$GITHUB_OUTPUT" | |
| echo "assemblySemFileVer=$assemblySemFileVer" >> "$GITHUB_OUTPUT" | |
| echo "informationalVersion=$informationalVersion" >> "$GITHUB_OUTPUT" |
| - name: Code Coverage Summary | ||
| uses: irongut/CodeCoverageSummary@v1.3.0 | ||
| if: always() | ||
| continue-on-error: true |
There was a problem hiding this comment.
continue-on-error: true on the coverage summary step can mask broken/missing coverage generation and still report a successful CI run. If coverage is intended to be a required signal (especially with branch protection), consider removing continue-on-error and letting this step fail when it can’t produce a summary.
| continue-on-error: true |
## Summary Closes the decisions inbox — merges `boromir-pr9-review-fixes.md` into `.squad/decisions.md` as **Decision #4: CI Workflow Conventions**. Working as **Scribe** (Documentation & Knowledge Management) ### What changed - `.squad/decisions.md` — Added Decision #4 with 5 CI conventions from PR #9 Copilot review - `.squad/decisions/inbox/boromir-pr9-review-fixes.md` — Marked as merged (tombstone comment) ### Decision #4 covers 1. Always use `global-json-file: global.json` in `setup-dotnet` 2. Use `nuGetVersion` for `/p:Version` in dotnet build (not `assemblySemVer`) 3. `squad-test.yml` must only trigger on `pull_request`, not `push` 4. Surgical use of `continue-on-error: true` 5. Comments must not contradict the code they describe These conventions apply to all future workflow files.
…s inbox - Merge boromir-sprint-1-1.md into decisions.md as Decision #9 - Add orchestration log entry for Sprint 1.1 hook hardening - Update Boromir's history.md with latest learning entry - Delete merged inbox file Boromir completed Sprint 1.1 (hook hardening): strict squad/{issue}-{slug} branch naming enforcement (Gate 0) + post-checkout hook auto-bootstrap. All 5 pre-push gates pass. Ready for PR review. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- routing.md: Add Guardrails #9 (Gimli parallel), #10 (no-verify prohibition), #11 (rubber duck for new patterns); strengthen Rule #6 to name Gimli+Frodo+Pippin - ceremonies.md: Add Feature Work Kickoff ceremony; harden Retrospective with coverage-gate trigger and closure requirement - pre-push-process.md: Add hard block on git push --no-verify at top of file with SDK mismatch fix instructions - pr-merge-process.md: Step 3 now explicitly checks coverage gate (not just tests passing); adds 'Tests authored' gate for Gimli coverage - gimli/charter.md: Fix Critical Rule #1 paths from IssueTracker to MyBlog (tests/Unit.Tests, tests/Architecture.Tests); add coverage gate (89%); add Rule #9 enforcing parallel spawn Closes #68 (retrospective action items) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CI/CD Phase 3-4
Closes the remaining CI/CD modernization work.
Changes
devbranch trigger + GitVersion step for SemVer stampingdevas base branch (was using dynamic default_branch)Branch Protection Applied
main: strict checks, 1 approval requireddev: CI required, flexible reviewsGitVersion
GitVersion.ymlalready configured at repo root. GitVersion setup step added to CI workflows.Working as Boromir (DevOps)