Repository navigation
On CPython 3.13.15+, a declaration failure in an imported model reports one line, not a traceback #1854
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
| # One job per concern, selected by the dependency graph. Shared core feeds | |
| # cadgen's runtime, UI, web and docs; UI feeds web. Apps never feed another | |
| # app. Policy checks run for changed shared contracts without also running | |
| # every skill suite. Runtime outputs are built only where needed. | |
| # | |
| # Check names are the jobs' concerns: `core-js` tests packages/core, `web` tests | |
| # packages/ui and apps/web and drives the bundled viewer, `mcp` tests apps/mcp. | |
| # main's required checks name the eight jobs before `mcp`. | |
| # Prose-only root changes run Version Check only; skill/package Markdown remains | |
| # test input. | |
| name: Test | |
| on: | |
| workflow_dispatch: | |
| pull_request: | |
| branches: | |
| - main | |
| - build-test | |
| push: | |
| branches: | |
| - main | |
| - build-test | |
| concurrency: | |
| group: test-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| # Each job's timeout is about twice its slowest recent run. A job that runs Python | |
| # test files also leaves room for unittest_files.py's per-file hang guard (15 min) | |
| # to fire first and name the file. A hang fails in minutes, not at GitHub's | |
| # six-hour default. | |
| # | |
| # What changed, as the classes above. Every other job's `if:` reads these. | |
| changes: | |
| name: Changed paths | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| outputs: | |
| cadgen: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.cadgen == 'true' }} | |
| core: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.core == 'true' }} | |
| ui: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.ui == 'true' }} | |
| web: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.web == 'true' }} | |
| mcp: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.mcp == 'true' }} | |
| skills: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.skills == 'true' }} | |
| docs: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.docs == 'true' }} | |
| infra: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.infra == 'true' }} | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - uses: dorny/paths-filter@v4 | |
| id: filter | |
| with: | |
| filters: | | |
| cadgen: | |
| - 'packages/cadgen/**' | |
| - 'tests/python/packages/**' | |
| - 'tests/python/support/**' | |
| - 'requirements*.txt' | |
| core: | |
| - 'packages/core/**' | |
| ui: | |
| - 'packages/ui/**' | |
| web: | |
| - 'apps/web/**' | |
| - 'tests/browser/**' | |
| mcp: | |
| - 'apps/mcp/**' | |
| skills: | |
| - 'skills/**' | |
| - 'tests/python/skills/**' | |
| - 'tests/python/global/**' | |
| docs: | |
| - 'apps/docs/**' | |
| infra: | |
| - 'scripts/**' | |
| - '.github/**' | |
| - 'VERSION' | |
| - '.claude-plugin/**' | |
| - '.codex-plugin/**' | |
| - '.cursor-plugin/**' | |
| - 'gemini-extension.json' | |
| - 'codex.mcp.json' | |
| - 'claude.mcp.json' | |
| - 'cursor.mcp.json' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - '.gitattributes' | |
| - '.gitignore' | |
| version: | |
| name: Version Check | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| with: | |
| # The VERSION guard below diffs against the PR base. | |
| fetch-depth: 0 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: "22" | |
| - name: Check release version | |
| run: | | |
| scripts/release/check-version.sh | |
| node scripts/release/sync-version.mjs --check | |
| # Only a release PR moves VERSION. Prepare Release opens those from `release/X.Y.Z` | |
| # and stamps the metadata and the skill pins with the same commit; a hand-made bump | |
| # would ship a version whose pins, wheel and tag do not line up. | |
| - name: Only release/* branches may change VERSION | |
| if: github.event_name == 'pull_request' | |
| env: | |
| HEAD_REF: ${{ github.head_ref }} | |
| BASE_REF: ${{ github.base_ref }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha }} | |
| run: bash scripts/release/check-pr-version.sh "$BASE_REF" "$HEAD_REF" "$HEAD_SHA" | |
| # The shipping contract's tree rules hold for every change, docs and models | |
| # included, and need no runtime: no symlink, no LFS or other rewriting | |
| # .gitattributes rule, every file under 5 MiB, no skill reaching into a repo root. | |
| - name: Check the tracked tree | |
| run: scripts/github-workflows/check-builds.sh --tree-only | |
| # The cadgen package suite, CAD Viewer backend included, on both platforms. Core | |
| # is in the condition because it is bundled into the runtime these tests execute. | |
| cadgen-linux: | |
| name: cadgen (Linux) | |
| needs: changes | |
| if: needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| env: | |
| # Test files at a time: each is a kernel-loading interpreter (~450 MB). | |
| CADGEN_TEST_JOBS: "4" | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| npm: packages/core | |
| - name: Run the cadgen package suite | |
| run: scripts/test/test-python.sh --select cadgen --print-weights | |
| # Why Windows runs at all: four of the last five user-reported bugs were Windows-only | |
| # (#260, #266, #267, #269) and every one passed CI -- the coverage existed, the runner | |
| # did not. The platform risk is file I/O: locks, paths, subprocesses, file URLs, the | |
| # daemon, the viewer backend. That is this suite, and only this suite. | |
| cadgen-windows: | |
| name: cadgen (Windows) | |
| needs: changes | |
| if: needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: windows-latest | |
| timeout-minutes: 45 | |
| env: | |
| # Four, the core count. Six was measured: every file slowed by ~40% and the | |
| # run failed on timeouts -- the spawn-bound tail is not idle CPU to fill. | |
| CADGEN_TEST_JOBS: "4" | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| npm: packages/core | |
| # --keep-going: report every failing suite in one round trip rather than one per | |
| # run; the Linux job keeps the fail-fast default. | |
| - name: Run the cadgen package suite | |
| run: scripts/test/test-python.sh --keep-going --select cadgen --print-weights | |
| shell: bash | |
| core-js: | |
| name: core-js | |
| needs: changes | |
| if: needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| python: "false" | |
| playwright: "false" | |
| npm: packages/core | |
| - name: Run shared core tests | |
| run: scripts/test/test-js.sh --select core | |
| # The client is platform-agnostic JS, so Linux only. It runs on a cadgen change too: | |
| # the launch step serves the bundled client through the real backend and draws it in | |
| # Playwright's Chromium, which is why this job keeps the Playwright install. | |
| web: | |
| name: web | |
| needs: changes | |
| if: needs.changes.outputs.web == 'true' || needs.changes.outputs.ui == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| npm: packages/core packages/ui apps/web apps/mcp | |
| ui-browser: "true" | |
| - name: Run shared UI tests | |
| if: needs.changes.outputs.ui == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' | |
| # One browser spec at a time: each renders WebGL in software here (SwiftShader), and | |
| # several at once saturate the runner's four cores until clicks time out. | |
| env: | |
| UI_BROWSER_TEST_CONCURRENCY: "1" | |
| run: scripts/test/test-js.sh --select ui | |
| - name: Run the CAD Viewer client tests | |
| if: needs.changes.outputs.web == 'true' || needs.changes.outputs.ui == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' | |
| run: scripts/test/test-js.sh --select web | |
| - name: Bundle production outputs | |
| run: scripts/bundle/bundle.sh | |
| - name: Launch the bundled CAD Viewer through the backend | |
| run: scripts/test/test-viewer-launch.sh | |
| - name: Exercise the bundled viewer in Chromium | |
| env: | |
| VIEWER_TEST_DIAGNOSTICS_DIR: ${{ runner.temp }}/viewer-browser | |
| run: scripts/test/test-viewer-browser.sh | |
| - name: Upload failed viewer diagnostics | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: viewer-browser-diagnostics | |
| path: ${{ runner.temp }}/viewer-browser | |
| if-no-files-found: ignore | |
| retention-days: 3 | |
| # The CAD app an agent host renders: its host adapter's units in jsdom, and the one-file | |
| # build it ships as (a build that would leave anything outside index.html fails). | |
| mcp: | |
| name: mcp | |
| needs: changes | |
| if: needs.changes.outputs.mcp == 'true' || needs.changes.outputs.ui == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| python: "false" | |
| npm: packages/core packages/ui apps/mcp | |
| - name: Run the CAD app tests and build it | |
| run: scripts/test/test-js.sh --select mcp | |
| # The policy gates read the repo's markdown and manifests; the skill suites run the | |
| # cadgen CLIs. Repository properties, so Linux only. | |
| skills: | |
| name: skills | |
| needs: changes | |
| if: needs.changes.outputs.skills == 'true' || needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' || needs.changes.outputs.ui == 'true' || needs.changes.outputs.web == 'true' || needs.changes.outputs.mcp == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| env: | |
| CADGEN_TEST_JOBS: "4" | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| npm: packages/core | |
| - name: Run the policy gates | |
| run: scripts/test/test-global.sh | |
| - name: Run every skill suite | |
| if: needs.changes.outputs.skills == 'true' || needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.infra == 'true' | |
| run: scripts/test/test-python.sh --select skills --print-weights | |
| # The docs site mirrors the skills' frontmatter, renders through core and | |
| # documents cadgen's commands, so it runs on any of those changing. | |
| docs: | |
| name: docs | |
| needs: changes | |
| if: needs.changes.outputs.docs == 'true' || needs.changes.outputs.skills == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| python: "false" | |
| playwright: "false" | |
| npm: packages/core apps/docs | |
| - name: Run documentation checks | |
| run: scripts/test/test-docs.sh | |
| # The tree as it ships: the production bundle from clean, the published-tree contract, | |
| # the wheel's package data, and the CLIs as a user gets them (pip-installed, outside | |
| # this repo). Properties of the tree, not of an operating system, so Linux only. | |
| packaging: | |
| name: packaging | |
| needs: changes | |
| if: needs.changes.outputs.cadgen == 'true' || needs.changes.outputs.core == 'true' || needs.changes.outputs.web == 'true' || needs.changes.outputs.ui == 'true' || needs.changes.outputs.mcp == 'true' || needs.changes.outputs.infra == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v7 | |
| - name: Set up dependencies | |
| uses: ./.github/actions/setup-deps | |
| with: | |
| npm: packages/core packages/ui apps/web apps/mcp | |
| - name: Bundle production outputs from clean | |
| run: scripts/bundle/bundle.sh --clean | |
| - name: Check production bundle layout | |
| run: scripts/github-workflows/check-builds.sh --skip-bundle-check | |
| # cadgen ships the JS it executes as package data. A package-data glob that stops | |
| # matching produces a wheel that imports fine and fails on a user's machine, so the | |
| # wheel is built and inspected here rather than trusted. | |
| - name: Check cadgen wheel contents | |
| env: | |
| CADGEN_KEEP_WHEEL: "1" | |
| CADGEN_WHEEL_OUT_DIR: ${{ runner.temp }}/cadgen-wheel-check | |
| run: | | |
| python -m pip install build | |
| scripts/release/check-wheel-contents.sh | |
| # The CLIs the way a user gets them -- pip-installed, from a directory that is not | |
| # this repo -- which is the only place a missing package-data glob or an accidental | |
| # repo-relative path shows up. | |
| - name: Run installed-mode checks against the verified wheel | |
| run: | | |
| shopt -s nullglob | |
| wheels=("$RUNNER_TEMP/cadgen-wheel-check/"*.whl) | |
| [ "${#wheels[@]}" -eq 1 ] || { echo "Expected one verified wheel" >&2; exit 1; } | |
| scripts/test/test-installed.sh --wheel "${wheels[0]}" | |