Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
87d8941
docs(squad): Aragorn Sprint 3 PR gate review findings (#60, #62, #63)
mpaulosky Apr 20, 2026
fc7cddd
ci: enable squad-test workflow for sprint/* branches (closes #69)
mpaulosky Apr 20, 2026
96b73ef
Refactor code structure for improved readability and maintainability
mpaulosky Apr 20, 2026
e79112e
chore: update SDK version to 10.0.202 in global.json
mpaulosky Apr 20, 2026
6dff59f
chore: update build output and add detailed build log
mpaulosky Apr 20, 2026
ba902db
chore: merge worktree changes into dev (SDK update, build log)
mpaulosky Apr 20, 2026
0854b0f
docs(squad): log Sprint 3 release v1.0.0-sprint3 — Aragorn history + …
mpaulosky Apr 20, 2026
3f66cc3
docs(squad): record versioning decision—sprint tags → pure semver
mpaulosky Apr 20, 2026
e8a5189
chore: v1.0.1 release — first pure-semver release (#87)
mpaulosky Apr 20, 2026
038ae76
ci: add GitVersion tag creation and push on main branch
mpaulosky Apr 20, 2026
341b46a
ci: enable automatic GitVersion tag creation on main (#88)
mpaulosky Apr 20, 2026
cbe952c
ci: fix GitVersion action parameter (useConfigFile → configFilePath)
mpaulosky Apr 20, 2026
3fa6de9
ci: fix GitVersion action deprecated parameter (#89)
mpaulosky Apr 20, 2026
6d3cd60
ci: grant write permissions for tag creation
mpaulosky Apr 20, 2026
290ed81
ci: grant write permissions for tag creation (#90)
mpaulosky Apr 20, 2026
c4194a5
ci: use majorMinorPatch for tag format instead of semVer
mpaulosky Apr 20, 2026
33a1048
ci: use majorMinorPatch for clean semver tags (#91)
mpaulosky Apr 20, 2026
989f13b
docs: add release process documentation
mpaulosky Apr 20, 2026
14f85fe
docs: add release process documentation (#92)
mpaulosky Apr 20, 2026
27d1e47
refactor: rename ci.yml to squad-ci.yml for naming consistency
mpaulosky Apr 20, 2026
5a2bddb
refactor: rename ci.yml to squad-ci.yml (#93)
mpaulosky Apr 20, 2026
5f57e8b
chore: promote dev → main (v1.1.0) - Sprint 4 release
Apr 24, 2026
0edf4fd
feat(ci): auto-move Done → Released on GitHub Release publish
Apr 24, 2026
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
95 changes: 95 additions & 0 deletions .github/workflows/squad-mark-released.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Squad Mark Released

on:
release:
types: [published, released]

permissions:
repository-projects: write

env:
PROJECT_ID: PVT_kwHOA5k0b84BVFTy
STATUS_FIELD_ID: PVTSSF_lAHOA5k0b84BVFTyzhQjgPk
DONE_OPTION_ID: "98236657"
RELEASED_OPTION_ID: "8e246b27"

jobs:
mark-released:
# Skip pre-releases (insider builds) and drafts — only real releases move items
if: ${{ !github.event.release.prerelease && !github.event.release.draft }}
runs-on: ubuntu-latest

steps:
- name: Move Done → Released on project board
uses: actions/github-script@v9
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const PROJECT_ID = process.env.PROJECT_ID;
const STATUS_FIELD_ID = process.env.STATUS_FIELD_ID;
const DONE_OPTION_ID = process.env.DONE_OPTION_ID;
const RELEASED_OPTION_ID = process.env.RELEASED_OPTION_ID;

let cursor = null;
let moved = 0;

do {
const result = await github.graphql(`
query($projectId: ID!, $cursor: String) {
node(id: $projectId) {
... on ProjectV2 {
items(first: 100, after: $cursor) {
pageInfo { hasNextPage endCursor }
nodes {
id
fieldValues(first: 50) {
nodes {
... on ProjectV2ItemFieldSingleSelectValue {
optionId
field {
... on ProjectV2SingleSelectField { id }
}
}
}
}
}
}
}
}
}
`, { projectId: PROJECT_ID, cursor });

const items = result.node.items;
cursor = items.pageInfo.hasNextPage ? items.pageInfo.endCursor : null;

for (const item of items.nodes) {
// Match by field ID (not name) to avoid brittleness on renames
const isDone = item.fieldValues.nodes.some(
fv => fv.field?.id === STATUS_FIELD_ID && fv.optionId === DONE_OPTION_ID
);
if (!isDone) continue;

await github.graphql(`
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
updateProjectV2ItemFieldValue(input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: { singleSelectOptionId: $optionId }
}) {
projectV2Item { id }
}
}
`, {
projectId: PROJECT_ID,
itemId: item.id,
fieldId: STATUS_FIELD_ID,
optionId: RELEASED_OPTION_ID,
});

moved++;
core.info(`✅ Item ${item.id} → Released`);
Comment on lines +72 to +91

Copilot AI Apr 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The per-item updateProjectV2ItemFieldValue call isn’t wrapped in error handling. As written, a single mutation failure (rate limit, transient network error, 403 due to project permissions, etc.) will fail the entire job mid-loop and leave subsequent Done items unmoved. Consider wrapping the mutation in a try/catch that logs a warning and continues, and optionally provide a specific hint for 403s (similar to other project-board workflows) so operators know how to remediate.

Suggested change
await github.graphql(`
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
updateProjectV2ItemFieldValue(input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: { singleSelectOptionId: $optionId }
}) {
projectV2Item { id }
}
}
`, {
projectId: PROJECT_ID,
itemId: item.id,
fieldId: STATUS_FIELD_ID,
optionId: RELEASED_OPTION_ID,
});
moved++;
core.info(`✅ Item ${item.id} → Released`);
try {
await github.graphql(`
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $optionId: String!) {
updateProjectV2ItemFieldValue(input: {
projectId: $projectId
itemId: $itemId
fieldId: $fieldId
value: { singleSelectOptionId: $optionId }
}) {
projectV2Item { id }
}
}
`, {
projectId: PROJECT_ID,
itemId: item.id,
fieldId: STATUS_FIELD_ID,
optionId: RELEASED_OPTION_ID,
});
moved++;
core.info(`✅ Item ${item.id} → Released`);
} catch (error) {
const message = error?.message ?? String(error);
core.warning(`⚠️ Failed to move item ${item.id} to Released: ${message}`);
if (error?.status === 403 || message.includes('403')) {
core.warning(
'Hint: received a 403 while updating the project item. ' +
'Ensure GITHUB_TOKEN or the workflow app installation has ' +
'permission to edit this GitHub Project and its fields.'
);
}
}

Copilot uses AI. Check for mistakes.
}
} while (cursor);

core.notice(`🎉 Moved ${moved} item(s) from Done → Released for ${context.payload.release.tag_name}`);
5 changes: 4 additions & 1 deletion .github/workflows/squad-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ jobs:
run: dotnet build MyBlog.slnx --configuration Release --no-restore -p:TreatWarningsAsErrors=true

- name: Run unit tests
run: dotnet test MyBlog.slnx --configuration Release --no-build --verbosity normal
run: |
dotnet test tests/Architecture.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
Comment on lines 28 to +32

Copilot AI Apr 24, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The step name says "Run unit tests", but it now runs Architecture + Web + Integration tests and no longer runs the other test projects that dotnet test MyBlog.slnx would cover (e.g., AppHost.Tests and Web.Tests.Bunit). Either update the step name and add an inline comment explaining why those projects are intentionally excluded, or include the missing test projects so the workflow continues to validate the full test suite on dev.

Copilot uses AI. Check for mistakes.
1 change: 1 addition & 0 deletions .squad/agents/aragorn/history.md
Original file line number Diff line number Diff line change
Expand Up @@ -441,3 +441,4 @@ Triaged Issue #18 ("Branch clean-up" / orphan local-repo changes) against draft
**Tag push gate exception:** The pre-push hook blocks direct `dev` branch pushes but cannot distinguish a tag push from a branch push. Tag pushes for releases require `--no-verify` since they target a specific commit SHA (not advancing a branch), making the branch-protection check semantically inapplicable. This is documented here for future release operators.

**Release ownership (per Decision #13):** Aragorn validates scope and approves the release contents; Boromir owns operational CI/CD execution. For sprint releases where CI is already confirmed green, Aragorn may proceed directly without a separate Boromir handoff.

Loading