Kaggle T4: let the Studio GPU payload share a card instead of waiting for the drain #7502
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
| # Workflow-trigger lint. Refuses two patterns that together powered the | |
| # TanStack GHSA-g7cv-rxg3-hmpx supply-chain compromise: | |
| # | |
| # 1. `pull_request_target` -- runs a fork's workflow YAML against the | |
| # base repository's secrets. There is no safe use of this trigger | |
| # for a public open-source project. | |
| # | |
| # 2. Shared cache keys between PR-triggered workflows and the publish | |
| # workflow. A fork PR can poison the cache; the publish workflow | |
| # then restores the poisoned cache on next run. | |
| # | |
| # This lives in its own workflow, not inside security-audit.yml, for one | |
| # reason: `on.pull_request` here carries NO `paths` / `paths-ignore` | |
| # filter, and must never gain one. A gate that only runs for some PRs | |
| # does not gate workflow changes, which is exactly what it exists to | |
| # review. security-audit.yml is a heavy nightly audit whose filters are | |
| # tuned for cost; coupling this lint to them once already opened that | |
| # hole. scripts/lint_workflow_triggers.py enforces the invariant on | |
| # whichever workflow runs it, so this file cannot quietly re-acquire a | |
| # filter. | |
| # | |
| # Cheap pure-Python lint, runs in seconds. Fail-closed. | |
| name: Workflow trigger lint | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}-${{ github.ref == 'refs/heads/main' && github.sha || '' }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| permissions: | |
| contents: read | |
| jobs: | |
| workflow-trigger-lint: | |
| name: workflow-trigger lint (pull_request_target / cache-poisoning) | |
| runs-on: ubuntu-latest | |
| # Raised from 5 when this job absorbed 12 more guard modules. Serial they are | |
| # 209s on a 192-core box and 119s at -n 4, which is what a GitHub runner has; | |
| # 5 minutes left no headroom for a slower runner and would have failed on | |
| # timeout rather than on anything real. | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Harden runner (egress block) | |
| uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0 | |
| with: | |
| egress-policy: block | |
| disable-sudo: true | |
| allowed-endpoints: > | |
| api.github.com:443 | |
| github.com:443 | |
| codeload.github.com:443 | |
| objects.githubusercontent.com:443 | |
| pypi.org:443 | |
| files.pythonhosted.org:443 | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.12' | |
| - name: Install PyYAML | |
| # pytest and PyYAML are pinned to the versions security-audit.yml pinned them | |
| # to when `pytest tests/security` lived there. That suite exercises | |
| # scripts/lint_workflow_triggers.py as a SUBPROCESS and asserts on its exit | |
| # semantics, so a pytest or PyYAML that resolves differently changes what it is | |
| # asserting against. xdist and vermin stay unpinned: neither is under test. | |
| run: pip install pyyaml==6.0.2 pytest==9.0.3 pytest-xdist vermin | |
| - name: Lint workflow triggers + cache keys | |
| run: python3 scripts/lint_workflow_triggers.py | |
| # What the dropped interpreter legs used to catch, as far as a static check can. | |
| # A pull request runs only the newest leg now, so nothing EXECUTES the backend on | |
| # the oldest one until the push to main. ast.parse at a feature_version covers | |
| # syntax and nothing else, which would miss the actual shape of this regression: | |
| # reaching for a stdlib name that does not exist yet, like the `anext` in | |
| # core/research_runs.py that already requires 3.10. vermin reads both, so a symbol | |
| # added after the floor fails here in seconds rather than on main in 23 minutes. | |
| # No paths filter on this workflow, so it sees every pull request. | |
| - name: Backend still runs on the oldest interpreter the matrix claims | |
| run: python3 scripts/lint_backend_python_floor.py | |
| # ONE pytest invocation, not one per file. | |
| # | |
| # These were 9 separate steps, each paying interpreter startup and collection to | |
| # run a single module -- and each new guard added a tenth, an eleventh. Collapsed | |
| # into one call, which also lets pytest share collection across them. This repo's | |
| # conftest is expensive to import, so a step per module pays that cost every time: | |
| # over the 17 modules this started with, 53.9s as one invocation against 300.8s as | |
| # one each. `-n 4` then uses the cores the runner already has: 304 tests, 128s | |
| # serial against 68s at -n 4, identical results either way. | |
| # | |
| # Pinned to 4 rather than `auto` deliberately. ubuntu-latest is a 4-core runner, so | |
| # on CI the two are the same, but `auto` scales to the host and each xdist worker | |
| # re-imports that expensive conftest. Measured on a 192-core machine: `auto` spawned | |
| # 192 workers and took 327s, worse than running serially. A fixed width is the same | |
| # everywhere and cannot be made pathological by the machine it lands on. | |
| # | |
| # tests/security rides along on the same invocation. It held its own ubuntu-latest | |
| # runner in security-audit.yml for 72s of work behind a queue measured at 11096s, | |
| # and the same argument that put the lockfile and load-orchestrator lanes into Lint | |
| # CI applies: work with a narrow trigger, moved into a job that was going to occupy | |
| # a runner on this commit anyway, can only reduce the slots a commit takes. Here the | |
| # trigger widens too, since this workflow has no paths filter and | |
| # security-audit.yml's pull_request does. | |
| # | |
| # This host and not Lint CI, where the other absorbed lanes went. Lint CI installs | |
| # shellcheck from apt, so its harden-runner has to permit escalation and an apt | |
| # mirror; a security gate moved there would run under a policy weaker than the one | |
| # it has today. This workflow's harden-runner block is byte-for-byte identical to | |
| # the one the job carried, so nothing about its isolation changes. | |
| # | |
| # The list grew as much as it shrank. Every module here reads a workflow file, so | |
| # the edit that breaks it is by definition a workflow-only edit, and this is the | |
| # only job in the repo with no paths filter. Ten guards were sitting outside it, | |
| # collected first by Backend CI's unfiltered push on main -- after the change had | |
| # already merged. tests/studio/test_workflow_guards_run_unfiltered.py keeps the | |
| # list honest so the next one is not forgotten too. | |
| - name: Workflow guard suites | |
| run: | | |
| python3 -m pytest -q -n 4 \ | |
| tests/studio/test_absorbed_lanes_still_run.py \ | |
| tests/studio/test_agent_guides_verdicts.py \ | |
| tests/studio/test_apt_steps_are_bounded.py \ | |
| tests/studio/test_backend_ci_matrix.py \ | |
| tests/studio/test_backend_ci_parallel_isolation.py \ | |
| tests/studio/test_cache_budget_discipline.py \ | |
| tests/studio/test_chat_ui_shards_cover_everything.py \ | |
| tests/studio/test_ui_shard_engines.py \ | |
| tests/studio/test_zoo_suite_parallel_isolation.py \ | |
| tests/studio/test_ci_shell_suite_coverage.py \ | |
| tests/studio/test_compile_caches_are_per_worker.py \ | |
| tests/studio/test_composer_rtl_bidi_attribute.py \ | |
| tests/studio/test_frontend_dep_removal.py \ | |
| tests/studio/test_frontend_dist_cache.py \ | |
| tests/studio/test_gguf_smoke_phases_stay_independent.py \ | |
| tests/studio/test_indicator_browsers_run_in_parallel.py \ | |
| tests/studio/test_inference_smoke_http_diagnostics.py \ | |
| tests/studio/test_install_phase_timing.py \ | |
| tests/studio/test_mac_bundled_job_phases.py \ | |
| tests/studio/test_mac_host_offload_optin.py \ | |
| tests/studio/test_settings_smoke_covers_every_tab.py \ | |
| tests/studio/test_playwright_install_avoids_with_deps.py \ | |
| tests/studio/test_macos_slots_per_commit.py \ | |
| tests/studio/test_main_runs_survive_merge_bursts.py \ | |
| tests/studio/test_pester_bootstrap_hardening.py \ | |
| tests/studio/test_playwright_suites_run_in_ci.py \ | |
| tests/studio/test_sdk_installs_are_major_bounded.py \ | |
| tests/studio/test_short_job_absorption.py \ | |
| tests/studio/test_smoke_workflows_share_one_script.py \ | |
| tests/studio/test_stt_model_search_locator_contract.py \ | |
| tests/studio/test_uv_cache_discipline.py \ | |
| tests/studio/test_version_compat_bundle.py \ | |
| tests/studio/test_windows_small_checks_stay_on_their_image.py \ | |
| tests/studio/test_windows_ui_lanes_are_isolated.py \ | |
| tests/studio/test_workflow_guards_run_unfiltered.py \ | |
| tests/security | |