Sprint 0 / #17: CI-пайплайн с гейтами (lint, unit+coverage>=70%, security, build, image-scan, push) #60

Merged
embeddevio merged 8 commits from feat/17-ci into main 2026-10-29 21:09:27 +03:00
Owner

Что

CI-пайплайн с гейтами для монорепо: .gitea/workflows/ci.yml + доки docs/ci/.

lint ─┬─ unit ───────┐
      │              ├─ build ── image-scan ── push (staging-<sha>)
      └─ security ───┘
Job Гейт
lint ruff check + ruff format + mypy strict
unit pytest, coverage < 70 % → fail
security bandit -lll (HIGH → fail) + pip-audit
build docker build -f deploy/Dockerfile → 192.168.1.111:3000/embeddevio/awg-dash:staging-<sha8>
image-scan trivy HIGH/CRITICAL → fail (образ aquasec/trivy через docker-сокет, БД-кэш)
push docker login + push тега staging-<sha> (только push-события)

build/image-scan/push активируются автоматически, когда в репозитории есть deploy/Dockerfile
(сейчас он есть только в #18 / PR #49 — поэтому на этой ветке они скипаются).

Проверено на живом runner'е (repo-scoped awg-dash-147-repo, 192.168.1.147)

Run #39 (эта ветка, от main) — http://192.168.1.111:3000/embeddevio/awg-dash/actions/runs/39
lint ✅ · unit ✅ (198 passed, coverage 96.80 %) · security ✅ (bandit 0 HIGH, pip-audit чисто) · build/image-scan/push ⏭ (нет Dockerfile)

Run #49 (feat/17-verify = эта ветка + deploy/* из #18) — http://192.168.1.111:3000/embeddevio/awg-dash/actions/runs/49
lint ✅ · unit ✅ · security ✅ · build ✅ (образ собран) · image-scan ❌ — trivy: Total: 22 (HIGH: 21, CRITICAL: 1) → push ⏭ (fail-closed: уязвимый образ не публикуется)

Гейты проверены негативными прогонами (ветка-пробник, удалена):

  • покрытие: run #51 — FAIL Required test coverage of 99% not reached. Total coverage: 96.80% → unit failure
  • HIGH в коде: run #55 — B602 Severity: High → security failure, pipeline красный
  • HIGH/CRITICAL в образе: run #49 — 22 находки → image-scan failure

Что починино в инфраструктуре runner'а (192.168.1.147)

  1. Runner был зарегистрирован instance-токеном → задачи забирались, но результаты и логи не фиксировались (runner_id: 0, вечный queued). Зарегистрирован repo-scoped runner awg-dash-147-repo (id 2, online).
  2. Duplicate mount point: /var/run/docker.sock — убран лишний container.options.
  3. all predefined address pools have been fully subnetted — вычищены 23 висячие сети GITEA-ACTIONS-*, job'ы переведены на container.network: host.
  4. В /etc/docker/daemon.json на .147 добавлен insecure-registries: ["192.168.1.111:3000"] (применено systemctl reload docker, контейнеры не перезапускались).

Известные ограничения (раскрыты в issue)

  • Gitea git-http отдаёт пустой pack → actions/checkout падает; в ci.yml fallback на archive/<sha>.tar.gz (issue #59, нужен доступ к хосту Gitea).
  • Артефакты: upload-artifact@v3 рапортует успех, но Gitea их не публикует; @v4 зависает → сводки дублируются в лог job (coverage-таблица, bandit, trivy).
  • Образ из #18 содержит 21 HIGH + 1 CRITICAL (Go stdlib v1.25.14, golang.org/x/crypto v0.42.0) — гейт правильно блокирует публикацию; после бампа Go/crypto image-scan и push пойдут зелёными без правок CI.
  • Registry push требует секрет REGISTRY_TOKEN с write:package (сейчас fallback на GITHUB_TOKEN; PAT агента такого права не имеет — проверено вручную: 401).

Порядок merge

  1. #18 (PR #49) — даёт deploy/Dockerfile, после него build включается автоматически.
  2. Этот PR.

Refs #17, Refs #15

## Что CI-пайплайн с гейтами для монорепо: `.gitea/workflows/ci.yml` + доки `docs/ci/`. ``` lint ─┬─ unit ───────┐ │ ├─ build ── image-scan ── push (staging-<sha>) └─ security ───┘ ``` | Job | Гейт | |---|---| | `lint` | ruff check + ruff format + mypy strict | | `unit` | pytest, **coverage < 70 % → fail** | | `security` | bandit -lll (**HIGH → fail**) + pip-audit | | `build` | `docker build -f deploy/Dockerfile` → `192.168.1.111:3000/embeddevio/awg-dash:staging-<sha8>` | | `image-scan` | trivy **HIGH/CRITICAL → fail** (образ aquasec/trivy через docker-сокет, БД-кэш) | | `push` | `docker login` + push тега `staging-<sha>` (только push-события) | `build`/`image-scan`/`push` активируются автоматически, когда в репозитории есть `deploy/Dockerfile` (сейчас он есть только в #18 / PR #49 — поэтому на этой ветке они скипаются). ## Проверено на живом runner'е (repo-scoped `awg-dash-147-repo`, 192.168.1.147) **Run #39 (эта ветка, от `main`)** — http://192.168.1.111:3000/embeddevio/awg-dash/actions/runs/39 `lint ✅` · `unit ✅` (198 passed, **coverage 96.80 %**) · `security ✅` (bandit 0 HIGH, pip-audit чисто) · `build/image-scan/push ⏭` (нет Dockerfile) **Run #49 (`feat/17-verify` = эта ветка + `deploy/*` из #18)** — http://192.168.1.111:3000/embeddevio/awg-dash/actions/runs/49 `lint ✅` · `unit ✅` · `security ✅` · **`build ✅`** (образ собран) · `image-scan ❌` — trivy: `Total: 22 (HIGH: 21, CRITICAL: 1)` → `push ⏭` (fail-closed: уязвимый образ не публикуется) **Гейты проверены негативными прогонами** (ветка-пробник, удалена): - покрытие: run #51 — `FAIL Required test coverage of 99% not reached. Total coverage: 96.80%` → `unit` **failure** - HIGH в коде: run #55 — `B602 Severity: High` → `security` **failure**, pipeline красный - HIGH/CRITICAL в образе: run #49 — 22 находки → `image-scan` **failure** ## Что починино в инфраструктуре runner'а (192.168.1.147) 1. Runner был зарегистрирован instance-токеном → задачи забирались, но результаты и логи не фиксировались (`runner_id: 0`, вечный `queued`). Зарегистрирован **repo-scoped** runner `awg-dash-147-repo` (id 2, online). 2. `Duplicate mount point: /var/run/docker.sock` — убран лишний `container.options`. 3. `all predefined address pools have been fully subnetted` — вычищены 23 висячие сети `GITEA-ACTIONS-*`, job'ы переведены на `container.network: host`. 4. В `/etc/docker/daemon.json` на .147 добавлен `insecure-registries: ["192.168.1.111:3000"]` (применено `systemctl reload docker`, контейнеры не перезапускались). ## Известные ограничения (раскрыты в issue) - **Gitea git-http** отдаёт пустой pack → `actions/checkout` падает; в `ci.yml` fallback на `archive/<sha>.tar.gz` (issue #59, нужен доступ к хосту Gitea). - **Артефакты**: `upload-artifact@v3` рапортует успех, но Gitea их не публикует; `@v4` зависает → сводки дублируются в лог job (coverage-таблица, bandit, trivy). - **Образ из #18 содержит 21 HIGH + 1 CRITICAL** (Go stdlib v1.25.14, `golang.org/x/crypto` v0.42.0) — гейт правильно блокирует публикацию; после бампа Go/crypto `image-scan` и `push` пойдут зелёными без правок CI. - **Registry push** требует секрет `REGISTRY_TOKEN` с `write:package` (сейчас fallback на `GITHUB_TOKEN`; PAT агента такого права не имеет — проверено вручную: 401). ## Порядок merge 1. #18 (PR #49) — даёт `deploy/Dockerfile`, после него `build` включается автоматически. 2. Этот PR. Refs #17, Refs #15
embeddevio added 6 commits 2026-10-28 23:12:30 +03:00
ci: пайплайн с гейтами (lint, unit+coverage>=70%, security, build, image-scan, push staging-<sha>)
contract-openapi / openapi-contract (push) Failing after 0s
contract-openapi / ts-client-is-current (push) Failing after 1s
ci / lint (push) Successful in 7m38s
ci / unit (push) Failing after 1m3s
ci / security (push) Successful in 2m19s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / push (push) Has been skipped
b13f5e8ac5
Refs #17, Refs #15

- lint: ruff check/format + mypy strict
- unit: pytest с --cov-fail-under=70, артефакты coverage.xml + htmlcov
- security: bandit -lll (HIGH) + pip-audit, артефакты bandit/pip-audit
- build: docker build deploy/Dockerfile -> staging-<sha> (активируется после merge #18)
- image-scan: trivy HIGH/CRITICAL --exit-code 1
- push: docker login + push в registry 192.168.1.111:3000

Обход дефекта Gitea git-http (upload-pack отдаёт пустой pack): fallback
на archive/<sha>.tar.gz, actions/checkout остаётся основным путём.
ci: тесты требуют requirements-contract.txt; явный guard на отсутствие deploy/Dockerfile
ci / lint (push) Successful in 42s
contract-openapi / openapi-contract (push) Failing after 41s
contract-openapi / ts-client-is-current (push) Failing after 31s
ci / unit (push) Successful in 41s
ci / security (push) Successful in 1m19s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / push (push) Has been skipped
a941525f2e
Refs #17
ci: trivy ставим из релизного tarball (install.sh + v0.57.1 → 404), версия 0.76.1
ci / lint (push) Successful in 46s
contract-openapi / openapi-contract (push) Failing after 35s
contract-openapi / ts-client-is-current (push) Failing after 32s
ci / unit (push) Successful in 56s
ci / security (push) Successful in 1m13s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / push (push) Has been skipped
88bdaf7d3a
Refs #17
ci: trivy через образ aquasec/trivy (сокет) + кэш БД на хосте; бинарь через github releases качается слишком медленно
ci / lint (push) Successful in 53s
contract-openapi / openapi-contract (push) Failing after 35s
contract-openapi / ts-client-is-current (push) Failing after 36s
ci / unit (push) Successful in 47s
ci / security (push) Successful in 1m23s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / push (push) Has been skipped
336df50ca0
Refs #17
ci: токен для registry — secret REGISTRY_TOKEN с fallback на GITHUB_TOKEN
ci / lint (push) Successful in 48s
contract-openapi / openapi-contract (push) Failing after 38s
contract-openapi / ts-client-is-current (push) Failing after 33s
ci / unit (push) Successful in 56s
ci / security (push) Successful in 1m8s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / push (push) Has been skipped
aac82e6d23
Refs #17
docs(ci): runbook пайплайна и отчёт проверки runner'а (#17)
ci / lint (push) Successful in 42s
contract-openapi / openapi-contract (push) Failing after 48s
contract-openapi / ts-client-is-current (push) Failing after 50s
ci / lint (pull_request) Successful in 42s
contract-openapi / openapi-contract (pull_request) Failing after 40s
contract-openapi / ts-client-is-current (pull_request) Failing after 28s
ci / unit (push) Successful in 49s
ci / security (push) Successful in 3m10s
ci / unit (pull_request) Successful in 48s
ci / security (pull_request) Successful in 2m22s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / build (pull_request) Has been skipped
ci / push (push) Has been skipped
ci / image-scan (pull_request) Has been skipped
ci / push (pull_request) Has been skipped
bbe0886342
Refs #17, Refs #15
embeddevio added 1 commit 2026-10-28 23:40:44 +03:00
docs(ci): дефекты 6.4 (артефакты, #62) и 6.5 (contract-openapi checkout, #59)
ci / lint (push) Successful in 47s
ci / lint (pull_request) Successful in 1m29s
contract-openapi / openapi-contract (push) Failing after 35s
contract-openapi / ts-client-is-current (push) Failing after 35s
contract-openapi / openapi-contract (pull_request) Failing after 33s
contract-openapi / ts-client-is-current (pull_request) Failing after 36s
ci / unit (push) Successful in 57s
ci / security (push) Successful in 7m12s
ci / unit (pull_request) Successful in 46s
ci / security (pull_request) Successful in 4m25s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / build (pull_request) Has been skipped
ci / push (push) Has been skipped
ci / image-scan (pull_request) Has been skipped
ci / push (pull_request) Has been skipped
80b33d5132
Refs #17, Refs #59, Refs #62
embeddevio reviewed 2026-10-29 00:03:57 +03:00
embeddevio left a comment
Author
Owner

TechLead — ревью round 1 (лента «artifact»), вердикт: принято как реализация #17. APPROVED-ревью технически невозможно: PR и токен агента принадлежат одному аккаунту (approve your own pull is not allowed) — поэтому фиксирую вердикт комментарием.

Проверял своими прогонами/логами, не по отчёту:

  • ci.yml прочитан целиком (325 строк): push: [feat/**, fix/**, chore/**, ci/**, main], pull_request: [main], workflow_dispatch; lint → {unit, security} → build → image-scan → push; --cov-fail-under=70 и trivy --severity HIGH,CRITICAL --exit-code 1 на месте.
  • run 66 (push, 80b33d5), run 67 (PR sync): jobs 194–196 / 200–202 success; в логе Required test coverage of 70% reached. Total coverage: 96.80%, 198 passed.
  • негативы воспроизводятся: run 51 job 145 (FAIL Required test coverage of 99% not reached. Total coverage: 96.80%), run 55 job 162 (B602 Severity: High → шаг bandit ❌ Failure), run 49 job 140 (trivy Total: 22 (HIGH: 21, CRITICAL: 1) → image-scan ❌, push ⏭ fail-closed).
  • archive-fallback по #59 работает: bad pack header (exit 128) → archive/<sha>.tar.gz → тесты по архиву.
  • list_run_artifacts(66) = total_count: 0 — артефакты платформа не публикует (#62); митигация сводками в логе действует.

Merge-порядок (обязателен): (1) PR #63 → (2) rerun/перетолкнуть feat/17-ci до зелёного combined status → (3) этот PR → (4) PR #49 (#18) — после него build/image-scan/push включаются сами.

Сейчас merge не разрешаю: combined status = failure из-за contract-openapi / * (run 68/69, дефект #59); фикс — PR #63.

Замечания, не блокирующие merge: bandit -lll фильтрует confidence, а не severity (гейт строже заявленного «HIGH only»); trivy --ignore-unfixed — осознанное сужение; REGISTRY_TOKEN не задан → возможен 401 на push.

Полная AC-матрица — в issue #17, комментарий TechLead 786.

**TechLead — ревью round 1 (лента «artifact»), вердикт: принято как реализация #17.** APPROVED-ревью технически невозможно: PR и токен агента принадлежат одному аккаунту (`approve your own pull is not allowed`) — поэтому фиксирую вердикт комментарием. Проверял своими прогонами/логами, не по отчёту: - `ci.yml` прочитан целиком (325 строк): `push: [feat/**, fix/**, chore/**, ci/**, main]`, `pull_request: [main]`, `workflow_dispatch`; `lint → {unit, security} → build → image-scan → push`; `--cov-fail-under=70` и `trivy --severity HIGH,CRITICAL --exit-code 1` на месте. - run 66 (push, `80b33d5`), run 67 (PR sync): jobs 194–196 / 200–202 `success`; в логе `Required test coverage of 70% reached. Total coverage: 96.80%`, `198 passed`. - негативы воспроизводятся: run 51 job 145 (`FAIL Required test coverage of 99% not reached. Total coverage: 96.80%`), run 55 job 162 (`B602 Severity: High` → шаг bandit `❌ Failure`), run 49 job 140 (trivy `Total: 22 (HIGH: 21, CRITICAL: 1)` → `image-scan ❌`, `push ⏭` fail-closed). - archive-fallback по #59 работает: `bad pack header` (exit 128) → `archive/<sha>.tar.gz` → тесты по архиву. - `list_run_artifacts(66)` = `total_count: 0` — артефакты платформа не публикует (#62); митигация сводками в логе действует. **Merge-порядок (обязателен):** (1) PR #63 → (2) rerun/перетолкнуть `feat/17-ci` до зелёного combined status → (3) этот PR → (4) PR #49 (#18) — после него `build`/`image-scan`/`push` включаются сами. **Сейчас merge не разрешаю:** combined status = `failure` из-за `contract-openapi / *` (run 68/69, дефект #59); фикс — PR #63. **Замечания, не блокирующие merge:** `bandit -lll` фильтрует confidence, а не severity (гейт строже заявленного «HIGH only»); `trivy --ignore-unfixed` — осознанное сужение; `REGISTRY_TOKEN` не задан → возможен 401 на push. Полная AC-матрица — в issue #17, комментарий TechLead 786.
embeddevio added 1 commit 2026-10-29 20:58:47 +03:00
Merge branch 'main' into feat/17-ci
ci / lint (push) Successful in 41s
ci / lint (pull_request) Successful in 43s
contract-openapi / openapi-contract (push) Successful in 55s
contract-openapi / ts-client-is-current (push) Successful in 46s
contract-openapi / openapi-contract (pull_request) Successful in 53s
contract-openapi / ts-client-is-current (pull_request) Successful in 40s
ci / unit (push) Successful in 48s
ci / security (push) Successful in 1m16s
ci / unit (pull_request) Successful in 46s
ci / security (pull_request) Successful in 1m20s
ci / build (push) Has been skipped
ci / image-scan (push) Has been skipped
ci / build (pull_request) Has been skipped
ci / push (push) Has been skipped
ci / image-scan (pull_request) Has been skipped
ci / push (pull_request) Has been skipped
0f2a646df2
embeddevio merged commit 19f0526b2e into main 2026-10-29 21:09:27 +03:00
Sign in to join this conversation.