Files
2026-07-13 13:18:33 +08:00

122 lines
6.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Test-selection — implementation state / handoff
Working notes for the diff-based CI test-selection system, so the work can be
resumed without re-deriving context. For *how the system works / how to use it*,
see [`TEST_SELECTION.md`](TEST_SELECTION.md); this file is only about the **state
of the implementation**.
_Last updated: 2026-06-18._
## Status: complete & locally verified; in review on PR #8077
The system is implemented end-to-end and passes local checks. Opened as
[deepspeedai/DeepSpeed#8077](https://github.com/deepspeedai/DeepSpeed/pull/8077)
(scoped to `modal-torch-latest` first; replicate to other workflows if accepted).
It has **not** yet run a live `subset`/`deploy` on modal, so the first real runs
should be watched.
### Review fixes applied (Codex bot, PR #8077)
- **P1 — run the selector from trusted code.** `collect-tests` now restores `ci/`
from the base branch before running the selector + self-tests, so a PR can't
rewrite `tests_fetcher.py` to emit `mode=none` and skip the Required check. (A
PR's `ci/` changes still show in the diff and force a full run via `ci/**`.)
Includes a bootstrap fallback: if base has no `tests_fetcher.py` yet, run all.
- **P1 — hidden-file artifact.** `actions/upload-artifact@v4` skips dot-prefixed
paths by default; `ci/.test_selection/` is one. Added `include-hidden-files:
true` so `deploy`'s download doesn't fail.
> Reminder: under `pull_request_target`, `deploy` restores `ci/` from the base
> branch, so changes under `ci/*` (the fetcher included) only take effect once
> **merged**. To validate the live behavior before merge, trigger via a
> `pull_request`-based run or the `modal` CLI.
## What was built
A diff-driven selector that, on a PR, runs only the `tests/unit/v1` tests impacted
by the changed files, with a fail-safe fallback to the full suite. Driven by the
`modal-torch-latest` workflow.
### Files
| File | State | Notes |
| --- | --- | --- |
| `ci/tests_fetcher.py` | new/rewritten | Config-driven `TestSelector` class; import-graph selector. |
| `ci/test_tests_fetcher.py` | new | 12 stdlib self-tests over synthetic git repos. |
| `ci/torch_latest.py` | modified | Reads `DS_TEST_LIST_FILE`, runs pytest on the selected targets (falls back to full `tests/unit/v1`). |
| `.github/workflows/modal-torch-latest.yml` | rewritten | `collect-tests` (fetcher) gates `deploy` (modal). |
| `.github/workflows/TEST_SELECTION.md` | new | Full design + usage doc. |
| `.github/workflows/TEST_SELECTION_STATE.md` | new | This file. |
| `CONTRIBUTING.md` | modified | "Diff-based CI test selection" section + link. |
| `.gitignore` | modified | Ignores `ci/.test_selection/`. |
## Key design decisions (and why)
- **Always-runs Required job, selects instead of skips.** `modal-torch-latest` is a
Required check, so path filters can't skip it. `collect-tests` decides
`all|subset|none`; `none` skips `deploy` while still satisfying the Required
status.
- **`deploy` tests PR code but restores `ci/` from base.** Selection must reflect
PR code, but the orchestration that holds modal/HF secrets must not be
PR-controlled. (Security trade-off accepted earlier in the work.)
- **Opaque hub modules + curated run-all globs.** `deepspeed`, `deepspeed.comm`,
`deepspeed.accelerator` are opaque in the graph to stop universal fan-out; core
hubs (`deepspeed/__init__.py`, `runtime/engine.py`, `comm/**`, `accelerator/**`,
…) instead live in the run-all globs. (Coarseness fix accepted earlier.)
- **Fail-safe to `all`, never `none`.** Every uncertain case (no base, no
merge-base, parse error, unexpected exception) widens to the full suite.
### Improvements implemented in the latest pass (items #3#11)
- **#3** Degrade to `all` on any selector error (top-level guard in `main()`).
- **#4** `DYNAMIC_EDGES` map for runtime/dynamic deps the AST can't see
(seeded: `deepspeed/module_inject/** → tests/unit/v1/moe/**`).
- **#5** Deleted `.py` only forces `all` when a *surviving* file still imports it
(dangling import); clean deletions no longer over-trigger.
- **#6** GitHub job summary (`$GITHUB_STEP_SUMMARY`) with mode/reason/file list;
`reason` also on `$GITHUB_OUTPUT`.
- **#7** `--explain` prints import chains from changed files to selected tests.
- **#8** Escape hatches documented in `CONTRIBUTING.md` + `TEST_SELECTION.md`.
- **#9** Self-tests in `ci/test_tests_fetcher.py`, also run in `collect-tests`.
- **#10** Robust merge-base: explicit check, `all` if missing; workflow keeps
`fetch-depth: 0` with rationale.
- **#11** Multi-workflow config: `WORKFLOWS` registry + `WorkflowConfig` +
`--workflow` flag.
## Verification done locally
- `python ci/tests_fetcher.py` self-tests: **12/12 pass**
(narrowing, shared importers, core/comm/fixture run-all, commit tag, docs-only →
none, new test file, clean vs. dangling delete, dynamic edge, missing base).
- Real-repo smoke: `--base`, `--explain`, `--workflow` validation all behave.
- Confirmed `$GITHUB_OUTPUT` + `$GITHUB_STEP_SUMMARY` emission and the #3
error-fallback path directly.
- No linter errors.
Re-run the core check any time:
```bash
python ci/test_tests_fetcher.py
python ci/tests_fetcher.py --base origin/master --explain
```
## Open items / possible follow-ups
- **Live validation:** watch the first real PR; confirm `collect-tests` artifact
hand-off and `deploy` gating behave on Actions + modal.
- **`DYNAMIC_EDGES` is minimal.** Only one seeded edge. Expand as blind spots are
found (tests that fail on `master`'s full run but weren't selected on their PR
are the signal).
- **Single workflow wired.** The engine is config-driven (#11) but only
`modal-torch-latest` is registered/wired. Other GPU workflows could adopt it by
adding a `WorkflowConfig` and mirroring the `collect-tests` job.
- **Run-all glob tuning.** The core-hub list is a conservative first cut; revisit
if it proves too coarse (full runs on minor edits) or too narrow (missed impact).
- **No telemetry.** Consider logging selection stats over time to tune
globs/opaque-modules against real false-positive/negative rates.