fix(usni): extract fleet parser helpers and tighten region coords #7750
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| changes: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| pull-requests: read | |
| outputs: | |
| code: ${{ steps.diff.outputs.code }} | |
| digest: ${{ steps.diff.outputs.digest }} | |
| validation: ${{ steps.diff.outputs.validation }} | |
| steps: | |
| - id: diff | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| if [ "${{ github.event_name }}" = "push" ]; then | |
| echo "code=true" >> "$GITHUB_OUTPUT" | |
| echo "digest=true" >> "$GITHUB_OUTPUT" | |
| echo "validation=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| FILES=$(gh api "repos/${{ github.repository }}/pulls/${{ github.event.number }}/files" \ | |
| --paginate --jq '.[].filename') | |
| CODE=$(echo "$FILES" | awk ' | |
| /\.md$/ { next } | |
| /^docs\// { next } | |
| /^src-tauri\// && $0 !~ /^src-tauri\/sidecar\// { next } | |
| /^CHANGELOG\.md$/ { next } | |
| /^LICENSE$/ { next } | |
| /^\.github\/workflows\/(build-desktop|docker-publish)\.yml$/ { next } | |
| { count++ } | |
| END { print count + 0 } | |
| ') | |
| echo "code=$( [ "$CODE" -gt 0 ] && echo true || echo false )" >> "$GITHUB_OUTPUT" | |
| # digest-image job: build Dockerfile.digest-notifications when a PR | |
| # touches its inputs (scripts/, shared/, server/_shared/, api/, the | |
| # Dockerfile itself, or the root package manifest). Catches the | |
| # cross-directory-import + native-dep breakage class documented in | |
| # tests/dockerfile-digest-notifications-imports.test.mjs. | |
| DIGEST=$(echo "$FILES" | awk ' | |
| /^(scripts\/|shared\/|server\/_shared\/|api\/|Dockerfile\.digest-notifications|package\.json|package-lock\.json)/ { count++ } | |
| END { print count + 0 } | |
| ') | |
| echo "digest=$( [ "$DIGEST" -gt 0 ] && echo true || echo false )" >> "$GITHUB_OUTPUT" | |
| # resilience-validation-smoke job: run the no-secrets artifact/schema | |
| # and script-contract gate when the validation bundle, its Dockerfile, | |
| # its committed artifacts, or its focused tests change. | |
| VALIDATION=$(echo "$FILES" | awk ' | |
| /^Dockerfile\.seed-bundle-resilience-validation$/ { count++ } | |
| /^docs\/methodology\/country-resilience-index\/validation\// { count++ } | |
| /^package\.json$/ || /^package-lock\.json$/ { count++ } | |
| /^scripts\/benchmark-resilience-external\.mjs$/ { count++ } | |
| /^scripts\/backtest-resilience-outcomes\.mjs$/ { count++ } | |
| /^scripts\/validate-resilience-sensitivity\.mjs$/ { count++ } | |
| /^scripts\/seed-bundle-resilience-validation\.mjs$/ { count++ } | |
| /^scripts\/_bundle-runner\.mjs$/ { count++ } | |
| /^tests\/(resilience-validation-artifacts-schema|benchmark-resilience-external|backtest-resilience-outcomes|resilience-sensitivity-v2|seed-bundle-resilience-validation)\.test\.(mjs|mts)$/ { count++ } | |
| END { print count + 0 } | |
| ') | |
| echo "validation=$( [ "$VALIDATION" -gt 0 ] && echo true || echo false )" >> "$GITHUB_OUTPUT" | |
| docs-stats: | |
| # Always-on: guards the capability counts quoted in README / ARCHITECTURE / | |
| # docs against the code sources of truth. Runs on every PR/push (docs-only | |
| # PRs set changes.code=false and skip `unit`, so this must not gate on it). | |
| # Pure Node builtins — no npm install required. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - name: stats.json is tracked and current | |
| # `git diff --exit-code` ignores untracked paths, so a PR that deletes | |
| # the committed snapshot would regenerate it untracked and still pass. | |
| # `git status --porcelain` reports stale (` M`), deleted (` D`), and | |
| # untracked (`??`) alike, so it catches all three. | |
| run: | | |
| node scripts/docs-stats.mjs | |
| if [ -n "$(git status --porcelain -- docs/generated/stats.json)" ]; then | |
| echo '::error::docs/generated/stats.json is missing, untracked, or stale — run `npm run docs:stats` and commit it.' | |
| git status --porcelain -- docs/generated/stats.json | |
| exit 1 | |
| fi | |
| - name: Doc claims match code | |
| run: node scripts/docs-stats.mjs --check | |
| unit: | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - run: npm ci | |
| - run: npm run test:data | |
| - name: Edge function bundle check | |
| run: | | |
| # JS edge entries (existing loop, unchanged). | |
| find api/ -name "*.js" -not -name "_*" -not -name "*.test.*" | while read f; do | |
| npx esbuild "$f" --bundle --format=esm --platform=browser --outfile=/dev/null || { | |
| echo "ERROR: esbuild failed to bundle $f" | |
| exit 1 | |
| } | |
| done | |
| # TS edge entries — opt-in allowlist. Most TS endpoints pull in | |
| # loaders esbuild doesn't ship by default (e.g. @vercel/og WASM | |
| # imports under api/brief/carousel/...), so we don't auto-include | |
| # api/*.ts the way we do api/*.js. Add a new entry to this list | |
| # ONLY after confirming `npx esbuild <file> --bundle --format=esm | |
| # --platform=browser --outfile=/dev/null` succeeds locally. | |
| for f in api/mcp.ts; do | |
| npx esbuild "$f" --bundle --format=esm --platform=browser --outfile=/dev/null || { | |
| echo "ERROR: esbuild failed to bundle $f" | |
| exit 1 | |
| } | |
| done | |
| sidecar: | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - run: npm ci | |
| - run: npm run test:sidecar | |
| convex-tests: | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - run: npm ci | |
| - run: npm run test:convex | |
| variant-smoke-full: | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' | |
| runs-on: ubuntu-latest | |
| # No secrets are injected here. The smoke allows provider-level | |
| # unavailable/stale states and gates app-level boot, variant, 401, | |
| # page-error, and expected-panel invariants. | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - run: npm ci | |
| - run: npx playwright install --with-deps chromium | |
| - run: npm run test:e2e:variant-smoke:full | |
| resilience-validation-smoke: | |
| needs: changes | |
| if: needs.changes.outputs.code == 'true' || needs.changes.outputs.validation == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| cache: 'npm' | |
| - run: npm ci | |
| - run: npm run test:resilience-validation-smoke | |
| digest-image: | |
| needs: changes | |
| if: needs.changes.outputs.digest == 'true' | |
| runs-on: ubuntu-latest | |
| # docker build with the warm runner cache typically lands in ~90s. | |
| # 20min cap catches base-image-pull stalls, npm-registry flakes, and | |
| # native-dep compile failures without letting one bad PR check block | |
| # the queue for an hour. The static BFS import test in test:data | |
| # remains the load-bearing gate; this job is the integration smoke. | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build digest-notifications image (smoke) | |
| # No push, no tag publish. Catches cross-directory-import breakage | |
| # before it reaches main. Pairs with the BFS import test in | |
| # tests/dockerfile-digest-notifications-imports.test.mjs — that test | |
| # walks the import graph statically; this job actually executes the | |
| # COPY+install steps and surfaces native-dep / package-lock issues | |
| # the static walk can't see. | |
| run: docker build -f Dockerfile.digest-notifications -t wm-digest . |