Lokalni CI parity — puna komanda¶
TL;DR
Prije push-a pokreni potpuni lokalni gate (bandit +
markdownlint + sve ostalo). ruff/pylint/pytest zelen ≠
pipeline zelen — Lint & Security step u pipeline-u radi ceo
repo (uključujući tests/ + .md), ne samo changed fajlove.
Puna komanda¶
ci/syntax/validate.py &&
ci/shellcheck/lint.py . &&
ci/ruff/lint.py . &&
CI_PYLINT_JOBS=8 ci/pylint/lint.py ci/ tests/ --changed &&
ci/bandit/scan.py . &&
ci/docker/compose_validate.py deploy/schemas-mirror/docker-compose.yml &&
ci/hadolint/lint.py deploy/schemas-mirror/Dockerfile &&
ci/markdownlint/lint.py . --exclude .claude/ --exclude .planning/ &&
ci/pyright/lint.py &&
ci/pytest/test.py tests/ -n auto --dist worksteal &&
ci/bats/test.py tests/
Šta svaki alat radi (ukratko)¶
| Alat | Šta | Zašto |
|---|---|---|
syntax/validate.py |
py_compile + bash -n |
Statički syntax check, ne radi analizu |
shellcheck/lint.py |
Shell lint | Shell skripte (consumer .sh) |
ruff/lint.py |
Python lint (FATAL only) | Brz, hvata očigledne greške |
pylint/lint.py |
Python analiza | PR-strict: FAIL_UNDER=9.5 --changed |
bandit/scan.py |
Python security | B310 suppressed, medium+ severity |
compose_validate.py |
Docker Compose schema | Inode-pinning regression guard |
hadolint/lint.py |
Dockerfile lint | dockerized (no host binary) |
markdownlint/lint.py |
Markdown lint | CI ceo repo, ne samo docs/bible/ |
pyright/lint.py |
Type check | Deploy verb family, pinned npx |
pytest/test.py |
Python testovi | -n auto --dist worksteal |
bats/test.py |
Shell testovi | test_ci_download_scripts.bats |
Tri najčešća "lokalno zeleno, pipeline crveno" uzroka¶
1. Bandit B108 (hardcoded /tmp)¶
# Ovo FAIL-a bandit B108 u pipeline, lokalno možda neće:
with open("/tmp/myfile.json") as f:
data = json.load(f)
bandit radi ceo repo, uključujući test data. Čak i u
fixtures, /tmp literal pali B108. Fix: koristi tempfile.mkdtemp()
ili tmp_path pytest fixture.
2. markdownlint MD004 / MD038¶
# MD004: lista sa početkom `+` pa `*`
- item 1
* item 2
# MD038: unutrašnji backticks u postojećem code-span
Use the `\`ls\`` command.
markdownlint lintuje ceo .md tree. Locally može proći jer
editor ne prijavljuje.
3. Pylint PR-strict gate¶
Lokalni default threshold je 9.0. PR-strict je 9.5 + --changed.
# Lokalno:
ci/pylint/lint.py ci/ tests/
# PR-strict (šta pipeline radi):
CI_PYLINT_FAIL_UNDER=9.5 ci/pylint/lint.py ci/ tests/ --changed
Razlika od 0.5 izgleda mala, ali je dovoljna da te pipka.
Kada preskočiti (i zašto NE)¶
Ne postoji legitimno "preskoči gate". Ako misliš da treba:
- Ako alati imaju bug → file issue, fix alat, NE preskači.
- Ako test fajl baca false-positive →
# pylint: disable=...sa dokumentovanim razlogom inline. Bez razloga = "scope creep", review fail. - Ako je hitan hotfix → push, monitor, fix posle. Ali NE preskači lokalni gate (trenutno traje <5 min).
Vidi i¶
07-pr-process.md— discipline poslije gate-aci/CLAUDE.md(root) — "Local CI parity" + "Validation"02-systems/04-env-vars.md—CI_PYLINT_*env vars