Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions .github/workflows/milestone-blog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,45 +62,45 @@ jobs:
run: |
BODY="## Milestone Review: ${MILESTONE_TITLE}

Ralph, **${MILESTONE_TITLE}** has been closed with **${ISSUE_COUNT} issues** completed.
Current latest release: \`${LAST_TAG}\`
Ralph, **${MILESTONE_TITLE}** has been closed with **${ISSUE_COUNT} issues** completed.
Current latest release: \`${LAST_TAG}\`

### Closed Issues (${ISSUE_COUNT} total)
${ISSUES_LIST}
### Closed Issues (${ISSUE_COUNT} total)
${ISSUES_LIST}

---
---

## 🔍 Release Candidate Checklist
## 🔍 Release Candidate Checklist

Review these criteria to decide between a full release or a blog-only post:
Review these criteria to decide between a full release or a blog-only post:

| Criteria | Check |
|----------|-------|
| Contains user-facing features or enhancements? | (${FEATURE_COUNT} enhancement-labeled issues) |
| Contains breaking changes or schema migrations? | Review issues above |
| Significant enough to warrant a version bump? | Your call |
| All CI gates green on \`main\`? | Check GitHub Actions |
| Blog post needed either way? | **Yes — always** |
| Criteria | Check |
|----------|-------|
| Contains user-facing features or enhancements? | (${FEATURE_COUNT} enhancement-labeled issues) |
| Contains breaking changes or schema migrations? | Review issues above |
| Significant enough to warrant a version bump? | Your call |
| All CI gates green on \`main\`? | Check GitHub Actions |
| Blog post needed either way? | **Yes — always** |

---
---

## ✅ Your Decision
## ✅ Your Decision

**Option A — Release Candidate** (tag + GitHub Release + release blog post):
> Add the label **\`release-candidate\`** to this issue.
> Then choose the version bump type in the comment below (major / minor / patch).
**Option A — Release Candidate** (tag + GitHub Release + release blog post):
> Add the label **\`release-candidate\`** to this issue.
> Then choose the version bump type in the comment below (major / minor / patch).

**Option B — Blog Only** (milestone summary blog post, no release):
> Add the label **\`blog-only\`** to this issue.
**Option B — Blog Only** (milestone summary blog post, no release):
> Add the label **\`blog-only\`** to this issue.

Either choice will automatically:
- Trigger Bilbo to write the blog post
- Update \`docs/blog/index.md\` (the blog page)
- Sync \`README.md\` via the blog-readme-sync workflow
Either choice will automatically:
- Trigger Bilbo to write the blog post
- Update \`docs/blog/index.md\` (the blog page)
- Sync \`README.md\` via the blog-readme-sync workflow

---
---

*Triggered by milestone close at ${PUBLISH_DATE}. Workflow: \`milestone-blog.yml\`*"
*Triggered by milestone close at ${PUBLISH_DATE}. Workflow: \`milestone-blog.yml\`*"

gh issue create \
--title "📋 Milestone Review: ${MILESTONE_TITLE} — release or blog?" \
Expand Down
50 changes: 25 additions & 25 deletions .github/workflows/milestone-release-decision.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ jobs:
run: |
gh issue comment "$ISSUE_NUMBER" --body "✅ **Release flow triggered.**

- Version bump: \`${BUMP}\`
- \`squad-milestone-release.yml\` dispatched — this will create the tag, push it, and publish a GitHub Release.
- \`release-blog.yml\` will fire automatically on release publish and create a \`squad:bilbo\` blog brief.
- Once Bilbo's PR merges, \`blog-readme-sync.yml\` will update \`README.md\` (the Page).
- Version bump: \`${BUMP}\`
- \`squad-milestone-release.yml\` dispatched — this will create the tag, push it, and publish a GitHub Release.
- \`release-blog.yml\` will fire automatically on release publish and create a \`squad:bilbo\` blog brief.
- Once Bilbo's PR merges, \`blog-readme-sync.yml\` will update \`README.md\` (the Page).

Closing this review issue."
Closing this review issue."

gh issue close "$ISSUE_NUMBER" --reason completed

Expand Down Expand Up @@ -109,25 +109,25 @@ Closing this review issue."
run: |
BODY="## Blog Post Brief: ${MILESTONE_TITLE}

Bilbo, Ralph has reviewed the **${MILESTONE_TITLE}** milestone and decided: **blog post only** (no release).
Bilbo, Ralph has reviewed the **${MILESTONE_TITLE}** milestone and decided: **blog post only** (no release).

### Post metadata
- **Suggested filename:** \`docs/blog/${PUBLISH_DATE}-${SLUG}.md\`
- **Suggested publish date:** ${PUBLISH_DATE}
- **Review issue:** ${REVIEW_ISSUE_URL} (see for full issue list)
### Post metadata
- **Suggested filename:** \`docs/blog/${PUBLISH_DATE}-${SLUG}.md\`
- **Suggested publish date:** ${PUBLISH_DATE}
- **Review issue:** ${REVIEW_ISSUE_URL} (see for full issue list)

### Suggested post structure
1. **Summary** — what this milestone accomplished (2–3 sentences)
2. **What was built** — key features, fixes, or improvements with context
3. **Technical highlights** — architecture decisions, tricky problems solved, patterns introduced
4. **What's next** — follow-up work planned
### Suggested post structure
1. **Summary** — what this milestone accomplished (2–3 sentences)
2. **What was built** — key features, fixes, or improvements with context
3. **Technical highlights** — architecture decisions, tricky problems solved, patterns introduced
4. **What's next** — follow-up work planned

### Instructions
- Write the post to \`docs/blog/${PUBLISH_DATE}-${SLUG}.md\`
- Update \`docs/blog/index.md\` to add the new post at the top of the Recent Posts table
- Follow existing post style (see \`docs/blog/2026-04-04-release-v0-7-0.md\`)
- Open a PR targeting \`main\` when complete
- Close both this issue and the review issue (#${REVIEW_ISSUE_NUMBER}) in the PR description"
### Instructions
- Write the post to \`docs/blog/${PUBLISH_DATE}-${SLUG}.md\`
- Update \`docs/blog/index.md\` to add the new post at the top of the Recent Posts table
- Follow existing post style (see \`docs/blog/2026-04-04-release-v0-7-0.md\`)
- Open a PR targeting \`main\` when complete
- Close both this issue and the review issue (#${REVIEW_ISSUE_NUMBER}) in the PR description"

gh issue create \
--title "Blog post: ${MILESTONE_TITLE} — milestone recap" \
Expand All @@ -141,10 +141,10 @@ Bilbo, Ralph has reviewed the **${MILESTONE_TITLE}** milestone and decided: **bl
run: |
gh issue comment "$ISSUE_NUMBER" --body "📝 **Blog-only path selected.**

A \`squad:bilbo\` blog brief issue has been created. Once Bilbo's PR merges:
- \`docs/blog/index.md\` will be updated (the blog page)
- \`blog-readme-sync.yml\` will update \`README.md\` (the Page)
A \`squad:bilbo\` blog brief issue has been created. Once Bilbo's PR merges:
- \`docs/blog/index.md\` will be updated (the blog page)
- \`blog-readme-sync.yml\` will update \`README.md\` (the Page)

Closing this review issue."
Closing this review issue."

gh issue close "$ISSUE_NUMBER" --reason completed
42 changes: 21 additions & 21 deletions .github/workflows/release-blog.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,31 +46,31 @@ jobs:
run: |
BODY="## Blog Post Brief: ${RELEASE_NAME}

Bilbo, a new GitHub Release has been published. Please write a dev blog post for **${RELEASE_NAME}**.
Bilbo, a new GitHub Release has been published. Please write a dev blog post for **${RELEASE_NAME}**.

### Post metadata
- **Suggested filename:** \`docs/blog/${PUBLISH_DATE}-release-${SLUG}.md\`
- **Suggested publish date:** ${PUBLISH_DATE}
- **Release:** [${TAG}](${RELEASE_URL})
- **Changelog range:** [\`${PREV_TAG}...${TAG}\`](https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${TAG})
### Post metadata
- **Suggested filename:** \`docs/blog/${PUBLISH_DATE}-release-${SLUG}.md\`
- **Suggested publish date:** ${PUBLISH_DATE}
- **Release:** [${TAG}](${RELEASE_URL})
- **Changelog range:** [\`${PREV_TAG}...${TAG}\`](https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${TAG})

### Release notes
$(gh api "repos/${{ github.repository }}/releases/tags/${TAG}" --jq '.body // "No release notes provided."')
### Release notes
$(gh api "repos/${{ github.repository }}/releases/tags/${TAG}" --jq '.body // "No release notes provided."')

### Suggested post structure
1. **Summary** — what this release delivers in 2–3 sentences
2. **What's New** — feature sections with code snippets and context
3. **Bug Fixes / Improvements** — notable fixes
4. **How to Upgrade** — any steps required (migrations, config changes)
5. **Stats** — test counts, coverage numbers, PR count
6. **What's Next** — upcoming work
### Suggested post structure
1. **Summary** — what this release delivers in 2–3 sentences
2. **What's New** — feature sections with code snippets and context
3. **Bug Fixes / Improvements** — notable fixes
4. **How to Upgrade** — any steps required (migrations, config changes)
5. **Stats** — test counts, coverage numbers, PR count
6. **What's Next** — upcoming work

### Instructions
- Write the post to \`docs/blog/${PUBLISH_DATE}-release-${SLUG}.md\`
- Update \`docs/blog/index.md\` to add the new post at the top of the Recent Posts table
- Follow existing post style (see \`docs/blog/2026-04-04-release-v0-7-0.md\`)
- Open a PR targeting \`main\` when complete
- Close this issue in the PR description with \`Closes #<this-issue>\`"
### Instructions
- Write the post to \`docs/blog/${PUBLISH_DATE}-release-${SLUG}.md\`
- Update \`docs/blog/index.md\` to add the new post at the top of the Recent Posts table
- Follow existing post style (see \`docs/blog/2026-04-04-release-v0-7-0.md\`)
- Open a PR targeting \`main\` when complete
- Close this issue in the PR description with \`Closes #<this-issue>\`"

gh issue create \
--title "Blog post: ${RELEASE_NAME} — release recap" \
Expand Down
14 changes: 9 additions & 5 deletions .github/workflows/squad-insider-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,16 @@ jobs:
-p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }} \
-p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }}

- name: Run unit tests
- name: Run tests
run: |
dotnet test tests/Unit.Tests/Unit.Tests.csproj --configuration Release --no-build --no-restore
dotnet test tests/Unit.Tests/Unit.Tests.csproj --configuration Release --no-build --no-restore
dotnet test tests/Architecture.Tests --configuration Release --no-build --no-restore
dotnet test tests/Unit.Tests/Unit.Tests.csproj --configuration Release --no-build --no-restore
dotnet test tests/Architecture.Tests --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=arch-results.trx"
dotnet test tests/Domain.Tests --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=domain-results.trx"
dotnet test tests/Web.Tests --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=web-results.trx"
dotnet test tests/Web.Tests.Integration --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=web-integration-results.trx"

- name: Create pre-release tag and GitHub Release
env:
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/squad-mark-released.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Squad Mark Released
on:
release:
types: [published, released]
workflow_dispatch: {}

permissions:
repository-projects: write
Expand All @@ -15,8 +16,8 @@ env:

jobs:
mark-released:
# Skip pre-releases (insider builds) and drafts — only real releases move items
if: ${{ !github.event.release.prerelease && !github.event.release.draft }}
# Skip pre-releases and drafts on release events; always run on manual dispatch
if: ${{ github.event_name == 'workflow_dispatch' || (!github.event.release.prerelease && !github.event.release.draft) }}
runs-on: ubuntu-latest

steps:
Expand Down Expand Up @@ -92,4 +93,5 @@ jobs:
}
} while (cursor);

core.notice(`🎉 Moved ${moved} item(s) from Done → Released for ${context.payload.release.tag_name}`);
const tagName = context.payload.release?.tag_name ?? 'manual dispatch';
core.notice(`🎉 Moved ${moved} item(s) from Done → Released for ${tagName}`);
1 change: 1 addition & 0 deletions .github/workflows/squad-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@ jobs:
- name: Run unit tests
run: |
dotnet test tests/Architecture.Tests --configuration Release --no-build --verbosity normal
dotnet test tests/Domain.Tests --configuration Release --no-build --verbosity normal
dotnet test tests/Web.Tests --configuration Release --no-build --verbosity normal
dotnet test tests/Web.Tests.Integration --configuration Release --no-build --verbosity normal
14 changes: 7 additions & 7 deletions .github/workflows/squad-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,16 @@ jobs:
-p:AssemblyVersion=${{ steps.gitversion.outputs.assemblySemVer }} \
-p:FileVersion=${{ steps.gitversion.outputs.assemblySemFileVer }}

- name: Run unit tests
- name: Run tests
run: |
dotnet test tests/Unit.Tests/Unit.Tests.csproj --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=domain-results.trx"
dotnet test tests/Unit.Tests/Unit.Tests.csproj --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=web-results.trx"
dotnet test tests/Architecture.Tests --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=arch-results.trx"
dotnet test tests/Unit.Tests/Unit.Tests.csproj --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=bunit-results.trx"
dotnet test tests/Domain.Tests --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=domain-results.trx"
dotnet test tests/Web.Tests --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=web-results.trx"
dotnet test tests/Web.Tests.Integration --configuration Release --no-build --no-restore \
--logger "trx;LogFileName=web-integration-results.trx"

- name: Create GitHub Release
env:
Expand Down
67 changes: 66 additions & 1 deletion .github/workflows/squad-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,66 @@ jobs:
name: architecture-test-results
path: test-results

test-domain:
name: "Domain.Tests (xUnit v3 pilot)"
runs-on: ubuntu-latest
timeout-minutes: 10
needs: build

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
global-json-file: global.json

- name: Cache NuGet packages
uses: actions/cache@v5
with:
path: ${{ github.workspace }}/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }}
restore-keys: |
${{ runner.os }}-nuget-

- name: Restore dependencies
run: dotnet restore

- name: Build Domain Tests
run: dotnet build tests/Domain.Tests --configuration Release --no-restore

- name: Run Domain Tests
id: domain-tests
run: |
mkdir -p test-results
if [ ! -d "tests/Domain.Tests" ]; then
echo "::notice::Domain test project not found at tests/Domain.Tests - skipping"
exit 0
fi

# xUnit v3 is fully compatible with dotnet test + XPlat Code Coverage + TRX logger
dotnet test tests/Domain.Tests \
--configuration Release \
--no-build \
--logger "trx;LogFileName=domain.trx" \
--results-directory "$GITHUB_WORKSPACE/test-results" \
--collect:"XPlat Code Coverage" \
-- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura
exit_code=$?

if [ $exit_code -ne 0 ]; then
echo "::error::Domain tests failed"
fi
exit $exit_code

- name: Upload Domain Test Results
uses: actions/upload-artifact@v7
if: always()
with:
name: domain-test-results
path: test-results

test-bunit:
name: "Web.Tests.Bunit"
runs-on: ubuntu-latest
Expand Down Expand Up @@ -430,6 +490,7 @@ jobs:
needs:
- test-web
- test-architecture
- test-domain
- test-bunit
- test-integration
- test-apphost
Expand Down Expand Up @@ -500,6 +561,7 @@ jobs:
- build
- test-web
- test-architecture
- test-domain
- test-bunit
- test-integration
- test-apphost
Expand Down Expand Up @@ -533,6 +595,7 @@ jobs:
echo "- **Build:** ${{ needs.build.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Web.Tests:** ${{ needs.test-web.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Architecture.Tests:** ${{ needs.test-architecture.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Domain.Tests (xUnit v3 pilot):** ${{ needs.test-domain.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Web.Tests.Bunit:** ${{ needs.test-bunit.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Web.Tests.Integration:** ${{ needs.test-integration.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **AppHost.Tests (Aspire + Playwright E2E):** ${{ needs.test-apphost.result }}" >> $GITHUB_STEP_SUMMARY
Expand All @@ -546,12 +609,14 @@ jobs:
build_status="${{ needs.build.result }}"
web_status="${{ needs.test-web.result }}"
arch_status="${{ needs.test-architecture.result }}"
domain_status="${{ needs.test-domain.result }}"
bunit_status="${{ needs.test-bunit.result }}"
integration_status="${{ needs.test-integration.result }}"
apphost_status="${{ needs.test-apphost.result }}"

if [[ "$build_status" == "failure" || "$web_status" == "failure" || \
"$arch_status" == "failure" || "$bunit_status" == "failure" || \
"$arch_status" == "failure" || "$domain_status" == "failure" || \
"$bunit_status" == "failure" || \
"$integration_status" == "failure" || "$apphost_status" == "failure" ]]; then
echo "❌ **Overall Status:** FAILED" >> $GITHUB_STEP_SUMMARY
else
Expand Down
3 changes: 2 additions & 1 deletion .squad/agents/aragorn/charter.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ Preferred: auto
// =============================================
```
`.razor` files do **NOT** get copyright headers.
7. **PR merge sequence:** CI pass → read Copilot review comments → parallel review → fix cycle if rejected → approve → squash merge → pull main. Never merge without unanimous reviewer approval.
7. **PR merge sequence:** CI pass → read Copilot review comments → check Codecov report → parallel review → fix cycle if rejected → approve → squash merge → pull main. Never merge without unanimous reviewer approval.
8. **Copilot review:** Before posting any PR review verdict, read GitHub Copilot's automated review comments (`gh pr view {N} --json reviews`). Address flagged bugs or security issues; style suggestions are discretionary.
9. **Codecov check:** After reading Copilot comments, check the Codecov bot comment on the PR (`gh pr view {N} --comments | grep -A 20 'codecov'`). Flag and investigate any coverage **decrease** ≥ 1%. Minor decreases (< 1%) are acceptable if the changed code is infrastructure/config. Coverage increases or no change are always acceptable.
Loading