-
[OPIK-6980] [CI] refactor: consolidate pre-commit into one root config + unified Code Quality CI (#7165)
发布于
2026-07-05 07:36:24 +00:00 - [OPIK-6980] [INFRA] refactor: consolidate pre-commit into root config and add uv-based lint CI
Replace the custom .hooks/pre-commit bash script and three satellite
.pre-commit-config.yaml files with a single root config (SSOT for which checks
run on which paths). Add a unified uv-based lint.yml (changed-files-only: PR diff
range, push range; --all-files on manual dispatch) and delete five per-language
lint workflows. Java/FE/TS run as repo:local hooks on changed files via wrapper
scripts; Python hooks stay pinned-remote. Per-hook timing surfaces as a sticky PR
comment + run summary. tsc incremental for FE and TS SDK. Makefile drives the
framework. actionlint hook stays commented until PR #7102 lands.Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
- ci(code-quality): fan out lint into one job per linter via dynamic matrix
Replace the single lint job with detect → per-hook matrix → summary so each
linter is reported, retried, and made visible independently (addresses the
reviewer concern about lost granularity), while the root .pre-commit-config.yaml
stays the single source of truth.- detect: precommit-detect-hooks.py replays pre-commit's files:/exclude:
matching over the diff, emitting one matrix leg per hook with matching files
(no skip-spam legs for linters with no work). - lint: fail-fast:false matrix, each leg provisions only its toolchain and runs
its single hook viapre-commit run <id> --files <matched>(id+files isolates
one hook since ids recur across scopes), uploading a filtered timing fragment. - summary: if:always aggregates fragments into the one sticky comment and gates
red on any leg failure.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
- ci(code-quality): make timing 1:1 with jobs + list skipped checks
The first matrix run spawned 27 lint jobs but the timing comment showed only
11 rows: detect modeled hooks' files: but not their types:, so it over-emitted
legs (e.g. ruff on a Makefile under sdks/opik_optimizer) that Skipped at runtime
and produced empty fragments, silently dropping from the table.- detect: add TYPED_IDS so python-tool and check-* hooks gate to their content
type (.py / .yaml / .json / .toml) — no more do-nothing legs. Now jobs are
1:1 with real work. - detect: also emit a
skippedlist (hooks with no matching files, so no job). - summary: reconcile rendered rows against the spawned-job count and warn on any
shortfall, so the table can never silently under-report again. - summary: render skipped checks in a collapsible ⏭️ section (precommit-skipped-
table.sh) for coverage transparency. - smoke tests cover the types: gate, the skipped output, and the skipped table.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
- ci(code-quality): exclude deleted files from detect (ACMR)
The reconcile guard caught 3 phantom legs on the live run: detect matched paths
fromgit diff --name-only, which includes deletions. A deleted file (e.g. the
satellite .pre-commit-config.yaml this PR removes) spawned a leg whose hook then
found "no files to check" at runtime — empty fragment, 11 of 14 jobs timed.Filter the diff to --diff-filter=ACMR (added/copied/modified/renamed), mirroring
pre-commit, which only lints files present in the worktree. Legs now 1:1 with
rendered rows; no reconcile warning.Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
- ci(code-quality): add Description to skipped table + shallow non-detect jobs
- Both timing tables (ran + skipped) now show a Description column, sourced from
a single shared scripts/precommit-hook-descriptions.tsv (was duplicated awk;
now one SSOT both the awk and python renderers read). - Per-job checkout depth: detect keeps fetch-depth:0 (it computes the PR diff
base..head, which must reach a many-commit base); the lint legs and summary go
fetch-depth:1 — they lint explicit files from detect's list / only render, and
never git-diff, so they need worktree content at HEAD, not history. The
reconcile guard makes any accidental scope loss visible, not silent.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
- ci(code-quality): single shared hook-description resolver; drop dead skip branch
Addresses two Baz dedup findings:
- timing-table.sh and skipped-table.sh both reimplemented TSV-parse + substring
matching → extract one resolver (precommit-hook-desc.py) that owns the matching
logic; both tables pipe hook names through it. The TSV stays the data SSOT,
this is now the single matching SSOT. - timing-table.sh had a skipped-rendering branch that's dead in the
matrix design (filter-leg-log.sh strips Skipped hooks before they reach it;
skipped-table.sh owns the skipped list). Removed it.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com
Co-authored-by: Andres Cruz andresc@comet.com下载附件