From 3c0083a0e875e62d729bbec4f95e822a5605ded8 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 17:23:28 -0700 Subject: [PATCH 1/5] feat(ci): add samples build validation gate (#103) Adds samples-build job to squad-ci.yml that validates sample projects still compile when SDK source files change. Feature-flagged via vars.SQUAD_SAMPLES_CI with skip-samples-ci label escape hatch. Refs #103 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/squad-ci.yml | 123 +++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 9ae8a2f9f..837275fcf 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -241,6 +241,129 @@ jobs: if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' run: node scripts/check-exports-map.mjs + samples-build: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Check feature flag + id: flag + # Default: gate is ENABLED. Set vars.SQUAD_SAMPLES_CI to "false" + # to explicitly disable. + run: | + if [ "${{ vars.SQUAD_SAMPLES_CI }}" = "false" ]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "Samples build gate disabled via vars.SQUAD_SAMPLES_CI" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi + + - name: Check skip label + if: steps.flag.outputs.skip == 'false' + id: label + run: | + SKIP="false" + LABELS='${{ toJSON(github.event.pull_request.labels.*.name) }}' + if echo "$LABELS" | grep -q "skip-samples-ci"; then + SKIP="true" + echo "Skipping samples build gate (skip-samples-ci label present)" + fi + echo "skip=$SKIP" >> "$GITHUB_OUTPUT" + + - name: Check for SDK source changes + if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' + id: changes + run: | + BASE="${{ github.event.pull_request.base.sha }}" + HEAD="${{ github.event.pull_request.head.sha }}" + SDK_CHANGED=$(git diff --name-only "$BASE"..."$HEAD" | grep -E '^packages/squad-sdk/src/' || true) + if [ -z "$SDK_CHANGED" ]; then + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "No SDK source changes detected -- samples build not applicable" + else + echo "skip=false" >> "$GITHUB_OUTPUT" + echo "SDK source files changed:" + echo "$SDK_CHANGED" + fi + + - name: Install root dependencies and build SDK + if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' + run: npm install && npm run build + + - name: Build and test samples + if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' + run: | + FAILED=0 + PASSED=0 + SKIPPED=0 + + for sample_dir in samples/*/; do + sample=$(basename "$sample_dir") + + if [ ! -f "$sample_dir/package.json" ]; then + echo "::notice::[$sample] No package.json -- skipping" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + HAS_BUILD=$(node -e "const p=require('./$sample_dir/package.json'); process.exit(p.scripts?.build ? 0 : 1)" 2>/dev/null && echo "true" || echo "false") + HAS_TEST=$(node -e "const p=require('./$sample_dir/package.json'); process.exit(p.scripts?.test ? 0 : 1)" 2>/dev/null && echo "true" || echo "false") + + if [ "$HAS_BUILD" = "false" ] && [ "$HAS_TEST" = "false" ]; then + echo "::notice::[$sample] No build or test scripts -- skipping" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + echo "" + echo "=========================================" + echo "[$sample] Installing dependencies..." + echo "=========================================" + if ! (cd "$sample_dir" && npm install --ignore-scripts 2>&1); then + echo "::error::[$sample] npm install failed" + FAILED=$((FAILED + 1)) + continue + fi + + if [ "$HAS_BUILD" = "true" ]; then + echo "[$sample] Running build..." + if ! (cd "$sample_dir" && npm run build 2>&1); then + echo "::error::[$sample] npm run build failed" + FAILED=$((FAILED + 1)) + continue + fi + fi + + if [ "$HAS_TEST" = "true" ]; then + echo "[$sample] Running tests..." + if ! (cd "$sample_dir" && npm test 2>&1); then + echo "::error::[$sample] npm test failed" + FAILED=$((FAILED + 1)) + continue + fi + fi + + echo "::notice::[$sample] Passed" + PASSED=$((PASSED + 1)) + done + + echo "" + echo "=========================================" + echo "Samples build summary: $PASSED passed, $FAILED failed, $SKIPPED skipped" + echo "=========================================" + + if [ "$FAILED" -gt 0 ]; then + echo "::error::$FAILED sample(s) failed build/test validation" + exit 1 + fi + publish-policy: runs-on: ubuntu-latest steps: From eec60039a6f25fef611927ddb7bfa02a0ef0a7f7 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:12:11 -0700 Subject: [PATCH 2/5] fix: add timeout, npm cache, --ignore-scripts to samples-build Addresses FIDO + Challenger review findings: - Add timeout-minutes: 15 to prevent CI hang on stalled installs - Add cache: npm to setup-node for faster builds - Add --ignore-scripts to npm install for security Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/squad-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 837275fcf..5bc4eec62 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -244,6 +244,7 @@ jobs: samples-build: if: github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/checkout@v4 with: @@ -252,6 +253,7 @@ jobs: - uses: actions/setup-node@v4 with: node-version: 22 + cache: 'npm' - name: Check feature flag id: flag @@ -295,7 +297,7 @@ jobs: - name: Install root dependencies and build SDK if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' - run: npm install && npm run build + run: npm install --ignore-scripts && npm run build - name: Build and test samples if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' From 104f15f6ec4a65981ebca61ddab569e8f357af4e Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:22:35 -0700 Subject: [PATCH 3/5] fix: build only squad-sdk for samples CI (Copilot suggestion) Accept Copilot suggestion to build only packages/squad-sdk instead of full repo build. Reduces CI time and timeout risk. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/squad-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 5bc4eec62..b956793cb 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -297,7 +297,11 @@ jobs: - name: Install root dependencies and build SDK if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' - run: npm install --ignore-scripts && npm run build + run: | + npm install --ignore-scripts + cd packages/squad-sdk + npm install --ignore-scripts + npm run build - name: Build and test samples if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' From d8b816bbe64a6cc395f155f624a6843887170f05 Mon Sep 17 00:00:00 2001 From: Copilot <223556219+Copilot@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:31:11 -0700 Subject: [PATCH 4/5] fix: accept Copilot suggestions -- cache key + workspace install Accept 2 Copilot suggestions verbatim: - Add cache-dependency-path for sample lockfiles - Use npm ci at workspace root + npm run build -w for deterministic CI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/squad-ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index b956793cb..316f9aa99 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -254,6 +254,9 @@ jobs: with: node-version: 22 cache: 'npm' + cache-dependency-path: | + package-lock.json + samples/**/package-lock.json - name: Check feature flag id: flag @@ -298,10 +301,8 @@ jobs: - name: Install root dependencies and build SDK if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' run: | - npm install --ignore-scripts - cd packages/squad-sdk - npm install --ignore-scripts - npm run build + npm ci --ignore-scripts + npm run build -w packages/squad-sdk - name: Build and test samples if: steps.flag.outputs.skip == 'false' && steps.label.outputs.skip != 'true' && steps.changes.outputs.skip != 'true' From 3b38bbf2c74c3a6a0f20b93d17c645b73c837bc1 Mon Sep 17 00:00:00 2001 From: "Dina Berry (MSFT)" Date: Sat, 28 Mar 2026 18:47:00 -0700 Subject: [PATCH 5/5] Update .github/workflows/squad-ci.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/squad-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/squad-ci.yml b/.github/workflows/squad-ci.yml index 316f9aa99..f486be621 100644 --- a/.github/workflows/squad-ci.yml +++ b/.github/workflows/squad-ci.yml @@ -257,6 +257,9 @@ jobs: cache-dependency-path: | package-lock.json samples/**/package-lock.json + cache-dependency-path: | + package-lock.json + samples/**/package-lock.json - name: Check feature flag id: flag