Skip to content

On CPython 3.13.15+, a declaration failure in an imported model reports one line, not a traceback #1854

On CPython 3.13.15+, a declaration failure in an imported model reports one line, not a traceback

On CPython 3.13.15+, a declaration failure in an imported model reports one line, not a traceback #1854

Workflow file for this run

# 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]}"