wave6: retire dead ctor entries (ALLOWLIST_DISCIPLINE §495, shared-diff fold) #410
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 | |
| # Runs the full per-port CI gate set via scripts/run-ci.sh: | |
| # TEST → SIGNATURES → DRIFT → SURFACE-FRESH → NO-CHEAT → EMISSION | |
| # Mirrors `bash scripts/run-ci.sh` exactly so there's no drift between local | |
| # and CI behavior. Previously this workflow ran only `tsc --noEmit` + `npm | |
| # test`, which left the EMISSION and NO-CHEAT gates unenforced on every TS PR | |
| # — a behavioral-emission regression (wrong toValue()/to_dict() shape) could | |
| # land green. run-ci.sh closes that hole. | |
| env: | |
| # Opt into Node.js 24 ahead of GitHub's 2026-06-02 default switch. | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout signalwire-typescript | |
| uses: actions/checkout@v7 | |
| with: | |
| path: signalwire-typescript | |
| - name: Checkout porting-sdk (mock servers + audit scripts + EMISSION corpus) | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: signalwire/porting-sdk | |
| # Coordinated-pass pin: 'main' normally; set the PORTING_SDK_REF repo variable | |
| # to a wave branch to test a coordinated porting-sdk change, declared on the PR | |
| # (see porting-sdk/COORDINATED_PASS.md). No revert commit. | |
| ref: ${{ vars.PORTING_SDK_REF || 'main' }} | |
| path: porting-sdk | |
| token: ${{ secrets.PORTING_SDK_TOKEN }} | |
| # The EMISSION gate compares this port's toValue() output against the | |
| # signalwire-python oracle (FunctionResult), which pulls fastapi via | |
| # signalwire/__init__. Check it out as a sibling so the gate has its | |
| # reference. | |
| - name: Checkout signalwire-python (EMISSION oracle) | |
| uses: actions/checkout@v7 | |
| with: | |
| repository: signalwire/signalwire-python | |
| path: signalwire-python | |
| # CI-PIN (Wave 1): the reference's Wave-1 changes (PY-1..9, incl PY-7 | |
| # request_options) live on signalwire-python wave/1-aplus (PR #67), not | |
| # yet on main. REVERT to main when signalwire-python wave/1-aplus merges. | |
| ref: ${{ vars.PORTING_SDK_REF || 'main' }} | |
| # run-ci.sh's TEST/SIGNATURES/SURFACE-FRESH/EMISSION gates drive vitest / | |
| # tsx; the script expects Node 24 (it prepends a local nvm path when | |
| # present, else falls back to PATH — so set 24 here for the runner). | |
| - uses: actions/setup-node@v7 | |
| with: | |
| node-version: '24' | |
| cache: 'npm' | |
| cache-dependency-path: signalwire-typescript/package-lock.json | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.14' | |
| - name: Install Python test harnesses (mock_relay + mock_signalwire) | |
| run: | | |
| pip install -e porting-sdk/test_harness/mock_relay | |
| pip install -e porting-sdk/test_harness/mock_signalwire | |
| # scripts/run-py-lint.sh and run-py-format.sh fail LOUD when ruff is | |
| # absent rather than skipping, so PY-LINT/PY-FMT cannot pass vacuously on | |
| # a runner that lacks it — hence this explicit install rather than relying | |
| # on it being preinstalled. Without it the gates red with "ruff not found | |
| # on PATH", which is a missing CI dep, not a code finding. | |
| # | |
| # PINNED EXACT. An unbounded `pip install ruff` resolves whatever is newest | |
| # at CI time, so a ruff release that adds a rule or changes a format | |
| # heuristic turns PY-LINT/PY-FMT red on a commit that was green locally — | |
| # the VERSION changed, not the code. 0.15.21 is the fleet-wide ruff | |
| # (signalwire-python/perl/php pin the same). Bump it in every port at once, | |
| # with the resulting fixes in the same commit. | |
| - name: Install ruff (PY-LINT / PY-FMT gates) | |
| run: | | |
| pip install "ruff==0.15.21" | |
| # Assert the pin actually took: pip can satisfy a spec from an | |
| # unexpected index or cache, so verify rather than assume. | |
| ruff --version | |
| ruff --version | grep -qw '0\.15\.21' || { echo "FATAL: ruff is not the pinned 0.15.21" >&2; exit 1; } | |
| - name: Install signalwire-python (EMISSION oracle) if not importable | |
| run: | | |
| if python -c "import signalwire.core.function_result" 2>/dev/null; then | |
| echo "signalwire-python already importable; skipping install" | |
| else | |
| pip install ./signalwire-python | |
| fi | |
| # The SWAIG-HTTP-INVOKE gate (porting-sdk diff_port_swaig_http.py) builds its | |
| # oracle via starlette.testclient.TestClient. On py3.14 CI the resolved | |
| # starlette (1.x) turned the httpx-deprecation into a HARD requirement for the | |
| # package literally named `httpx2` (a real PyPI package, v2.x) — plain | |
| # `pip install httpx` (0.28) no longer satisfies it. Install httpx2 so the | |
| # TestClient imports clean and the SWAIG-HTTP oracle builds. | |
| - name: Install SWAIG-HTTP gate backend (starlette TestClient needs httpx2) | |
| run: pip install httpx2 | |
| # ACTIONLINT gate (porting-sdk actionlint_gate.py) needs the actionlint | |
| # binary and fails LOUD when it is absent (never a silent skip), so install | |
| # it before run-ci. Official installer drops the binary in the cwd; move it | |
| # onto PATH. | |
| # | |
| # VERSION PINNED. With no version argument the installer takes `latest`, so | |
| # a new actionlint release (they add checks regularly) fails the ACTIONLINT | |
| # gate on an UNCHANGED workflow file, while local dev — on whatever | |
| # `brew install actionlint` last fetched — still passes. Keep in lockstep | |
| # with SW_ACTIONLINT_VERSION in scripts/_env.sh. | |
| - name: Install actionlint (ACTIONLINT gate) | |
| run: | | |
| bash <(curl -sSfL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.12 | |
| sudo mv ./actionlint /usr/local/bin/actionlint | |
| actionlint --version | |
| actionlint --version | grep -qw '1\.7\.12' || { echo "FATAL: actionlint is not the pinned 1.7.12" >&2; exit 1; } | |
| - name: npm ci | |
| working-directory: signalwire-typescript | |
| run: npm ci | |
| # Heavy doc-execution gates (SNIPPET-COMPILE/RUN, EXAMPLES-RUN — tier=nightly) | |
| # are skipped on per-PR runs by default (they dominate run-ci wall time). But a | |
| # PR that actually TOUCHES docs/examples/snippets must still be gated at PR time, | |
| # so promote this run to the nightly tier when the diff touches those paths. | |
| - name: Select gate tier (promote to nightly if PR touches docs/examples) | |
| id: tier | |
| working-directory: signalwire-typescript | |
| run: | | |
| tier=pr | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| base="${{ github.event.pull_request.base.sha }}" | |
| # diff the PR against its base; grep the doc/example/snippet surface | |
| if git fetch --no-tags --depth=1 origin "$base" 2>/dev/null \ | |
| && git diff --name-only "$base"...HEAD 2>/dev/null \ | |
| | grep -qE '^(docs/|examples/|README|.*\.md$)'; then | |
| tier=nightly | |
| echo "PR touches docs/examples → running heavy doc gates (tier=nightly)" | |
| fi | |
| fi | |
| echo "tier=$tier" >> "$GITHUB_OUTPUT" | |
| - name: Run CI gate script (TEST → SIGNATURES → DRIFT → SURFACE-FRESH → NO-CHEAT → EMISSION) | |
| working-directory: signalwire-typescript | |
| env: | |
| PORTING_SDK: ${{ github.workspace }}/porting-sdk | |
| SW_CI_TIER: ${{ steps.tier.outputs.tier }} | |
| # COORDINATED-PASS reads the live PR body/labels via 'gh api' to see a | |
| # 'Coordinated-With:' declaration edited after the triggering push. | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: bash scripts/run-ci.sh |