Skip to content

feat(ci): add workspace integrity, prerelease guard, and export smoke gates#691

Merged
diberry merged 1 commit intobradygaster:devfrom
diberry:squad/ci-health-gates-clean
Mar 29, 2026
Merged

feat(ci): add workspace integrity, prerelease guard, and export smoke gates#691
diberry merged 1 commit intobradygaster:devfrom
diberry:squad/ci-health-gates-clean

Conversation

@diberry
Copy link
Copy Markdown
Collaborator

@diberry diberry commented Mar 29, 2026

Adds 3 CI health gates to squad-ci.yml: workspace integrity check, prerelease guard, and export smoke test.

Supersedes #688 with a clean branch from upstream/dev.
Fork PR: diberry#115.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

… gates

Adds 3 CI health gates to squad-ci.yml.

Closes #115

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 29, 2026 16:37
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds three additional CI “health gates” to the existing Squad GitHub Actions workflow to catch workspace/packaging issues earlier (especially around npm workspaces, versioning, and SDK exports).

Changes:

  • Adds new CI jobs: workspace-integrity, prerelease-version-guard, and export-smoke-test.
  • Updates existing gates to support additional skip-label behavior and adds an in-file skip-label reference section.
  • Adjusts samples-build installation behavior.

Comment on lines +535 to +542
# Prerelease Version Guard
# Purpose: Prevent prerelease version strings (-build, -alpha, -beta,
# -rc) from being committed to dev or main.
# Catches: Forgotten prerelease suffixes that break semver range
# resolution in workspace dependencies.
# Why: Added after PR #640 prerelease version incident where a
# -build.N suffix caused npm to skip the local workspace
# copy during dependency resolution.
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

The comments/error text say this guard prevents prerelease versions from merging to dev/main, but the workflow triggers on PRs targeting preview and insider too. Either update the documentation/message to match the actual behavior, or narrow the job condition (e.g., if: github.event_name == 'pull_request' && (github.base_ref == 'dev' || github.base_ref == 'main')).

Copilot uses AI. Check for mistakes.
Comment on lines +161 to +173
- name: Check skip label
if: steps.flag.outputs.skip == 'false'
id: label
run: |
LABELS=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name' 2>/dev/null || echo "")
if echo "$LABELS" | grep -q "skip-changelog"; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Skipping CHANGELOG gate (skip-changelog label present)"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ github.token }}
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

The new skip-label check uses gh pr view ... to fetch PR labels, but this workflow sets permissions: contents: read only. With those permissions, GITHUB_TOKEN typically cannot read pull request metadata, so gh pr view will fail (403) and the skip label will never be honored.

Fix by either switching back to using the event payload (contains(github.event.pull_request.labels.*.name, 'skip-changelog') / toJSON(...) + grep), or updating workflow/job permissions to include pull-requests: read (and keep the GH_TOKEN env).

Copilot uses AI. Check for mistakes.
Comment on lines +246 to +258
if: steps.flag.outputs.skip == 'false'
id: label
run: |
LABELS=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name' 2>/dev/null || echo "")
if echo "$LABELS" | grep -q "skip-exports-check"; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Skipping exports map check (skip-exports-check label present)"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ github.token }}

Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

Same issue here: gh pr view needs pull request read permissions, but the workflow-level token permissions are limited to contents: read. If gh pr view fails, skip-exports-check will never be detected and the job can't be bypassed via label.

Prefer reading labels from github.event.pull_request.labels (no API call / no extra permissions) or add pull-requests: read to the workflow/job permissions.

Suggested change
if: steps.flag.outputs.skip == 'false'
id: label
run: |
LABELS=$(gh pr view ${{ github.event.pull_request.number }} --json labels --jq '.labels[].name' 2>/dev/null || echo "")
if echo "$LABELS" | grep -q "skip-exports-check"; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Skipping exports map check (skip-exports-check label present)"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
env:
GH_TOKEN: ${{ github.token }}
if: github.event_name == 'pull_request' && steps.flag.outputs.skip == 'false'
id: label
run: |
if [[ "${{ contains(github.event.pull_request.labels.*.name, 'skip-exports-check') }}" == 'true' ]]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Skipping exports map check (skip-exports-check label present)"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi

Copilot uses AI. Check for mistakes.
echo "[$sample] Installing dependencies..."
echo "========================================="
if ! (cd "$sample_dir" && if [ -f package-lock.json ]; then npm ci; else npm install; fi 2>&1); then
if ! (cd "$sample_dir" && npm install --ignore-scripts 2>&1); then
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

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

Switching sample installs to npm install --ignore-scripts (and removing the prior patching behavior) means some samples will now install the published @bradygaster/squad-sdk instead of the local workspace copy. In this repo, at least samples/autonomous-pipeline and samples/cost-aware-router still depend on @bradygaster/squad-sdk: ^0.8.0, so SDK PR changes won’t actually be exercised by this gate.

To keep this job validating the current PR’s SDK, either restore the patch-to-local step or standardize all samples to use file:../../packages/squad-sdk (and then use npm ci --ignore-scripts when a lockfile is present for determinism).

Suggested change
if ! (cd "$sample_dir" && npm install --ignore-scripts 2>&1); then
# Ensure samples use the local workspace @bradygaster/squad-sdk instead of the published version
node -e "const fs=require('fs'); const path='./$sample_dir/package.json'; const p=require(path); let changed=false; for (const section of ['dependencies','devDependencies']) { if (p[section] && p[section]['@bradygaster/squad-sdk']) { p[section]['@bradygaster/squad-sdk']='file:../../packages/squad-sdk'; changed=true; } } if (changed) { fs.writeFileSync(path, JSON.stringify(p, null, 2)); console.log('Patched', path, 'to use local @bradygaster/squad-sdk'); }" 2>/dev/null || true
if [ -f "$sample_dir/package-lock.json" ]; then
INSTALL_CMD="npm ci --ignore-scripts"
else
INSTALL_CMD="npm install --ignore-scripts"
fi
if ! (cd "$sample_dir" && $INSTALL_CMD 2>&1); then

Copilot uses AI. Check for mistakes.
@diberry diberry merged commit 0d60bbb into bradygaster:dev Mar 29, 2026
13 checks passed
robzelt pushed a commit to robzelt/squad that referenced this pull request Apr 1, 2026
…#652) (bradygaster#691)

Adds multi-squad.ts to squad-sdk with 7 core functions: getSquadRoot, resolveSquadPath (5-step resolution chain), listSquads, createSquad, deleteSquad, switchSquad, migrateIfNeeded. Plus 3 exported types (SquadConfig, SquadEntry, MultiSquadOptions). Non-destructive migration registers legacy ~/.squad as default.

Ref bradygaster#652 (Phase 1 of 3)
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.

2 participants