[CL-CI-OOM] CI(api): чиним JS heap OOM в Typecheck — NODE_OPTIONS через env-блок #861

Merged
andrei merged 2 commits from feature/claude-ci-api-oom-fix into master 2026-06-25 10:28:30 +00:00
Owner

Что сделано

В job API (.forgejo/workflows/ci.yml) шаг Typecheck переведён с inline-формы
NODE_OPTIONS=--max-old-space-size=4096 npx tsc --noEmit на step-level env:-блок:
run: npx tsc --noEmit + env: { NODE_OPTIONS: --max-old-space-size=4096 }.

Зачем

Шаг Typecheck падал с FATAL ERROR: Ineffective mark-compacts near heap limit — JavaScript heap out of memory (v8 heap ~1550MB). Runner (/opt/forgejo-runner/config.yml)
капает каждый job-контейнер на --memory=3g, и node:22 авто-выбирает дефолтный
v8 old-space ~1550MB. Inline-форма NODE_OPTIONS=... npx tsc не доходит до процесса
tsc в act/forgejo-runner
— v8 остаётся на дефолте (в OOM-логе виден лимит 1550, не 4096).
env-блок инжектится как docker run -e и применяется надёжно (тот же приём, что
рабочий Build-шаг ниже). api tsc крупнее app, поэтому именно он перерос дефолт
(app/contracts с тем же inline проходят — их tsc меньше 1550MB).

Память раннера НЕ трогаю намеренно: хост 30GB, свободно ~14GB (остальное — прод
adami-api/forgejo/postgres), поднятие --memory при capacity:4 переподписало бы RAM.

План тестирования

  • Локально на master прогнаны все шаги job API: tsc --noEmit (0 errors),
    eslint src --max-warnings 0, OpenAPI drift (clean), guards, pnpm install --frozen-lockfile,
    lockfile-integrity, vitest run --coverage (10356/10356 passed, coverage выше порогов).
  • 4096 — лимит, не резерв; фактическое потребление tsc < 3g cap → kernel-OOM исключён.
  • Проверка: CI job API на этом PR должен пройти Typecheck без heap OOM.

Где могу ошибаться

  • Если app/contracts tsc в будущем тоже перерастут 1550MB — у них остаётся та же
    сломанная inline-форма (здесь не трогал, YAGNI; чинить тем же приёмом при появлении OOM).
  • Если api tsc вырастет > 3g — упрётся уже в cgroup-лимит контейнера, понадобится
    отдельное решение по памяти раннера.
## Что сделано В job `API` (`.forgejo/workflows/ci.yml`) шаг **Typecheck** переведён с inline-формы `NODE_OPTIONS=--max-old-space-size=4096 npx tsc --noEmit` на step-level `env:`-блок: `run: npx tsc --noEmit` + `env: { NODE_OPTIONS: --max-old-space-size=4096 }`. ## Зачем Шаг Typecheck падал с `FATAL ERROR: Ineffective mark-compacts near heap limit — JavaScript heap out of memory` (v8 heap ~1550MB). Runner (`/opt/forgejo-runner/config.yml`) капает каждый job-контейнер на `--memory=3g`, и `node:22` авто-выбирает дефолтный v8 old-space ~1550MB. **Inline-форма `NODE_OPTIONS=... npx tsc` не доходит до процесса tsc в act/forgejo-runner** — v8 остаётся на дефолте (в OOM-логе виден лимит 1550, не 4096). `env`-блок инжектится как `docker run -e` и применяется надёжно (тот же приём, что рабочий Build-шаг ниже). `api` tsc крупнее `app`, поэтому именно он перерос дефолт (app/contracts с тем же inline проходят — их tsc меньше 1550MB). Память раннера НЕ трогаю намеренно: хост 30GB, свободно ~14GB (остальное — прод adami-api/forgejo/postgres), поднятие `--memory` при `capacity:4` переподписало бы RAM. ## План тестирования - Локально на master прогнаны все шаги job API: `tsc --noEmit` (0 errors), `eslint src --max-warnings 0`, OpenAPI drift (clean), guards, `pnpm install --frozen-lockfile`, lockfile-integrity, `vitest run --coverage` (10356/10356 passed, coverage выше порогов). - 4096 — лимит, не резерв; фактическое потребление tsc < 3g cap → kernel-OOM исключён. - Проверка: CI job API на этом PR должен пройти Typecheck без heap OOM. ## Где могу ошибаться - Если `app`/`contracts` tsc в будущем тоже перерастут 1550MB — у них остаётся та же сломанная inline-форма (здесь не трогал, YAGNI; чинить тем же приёмом при появлении OOM). - Если api tsc вырастет > 3g — упрётся уже в cgroup-лимит контейнера, понадобится отдельное решение по памяти раннера.
[CL-CI-OOM] CI(api): чиним JS heap OOM в Typecheck — NODE_OPTIONS через env-блок
Some checks failed
CI / API (pull_request) Failing after 4m15s
CI / App (pull_request) Has been cancelled
PR Janitor / janitor (pull_request) Failing after 27h4m22s
CI / Prisma Migrate Gate (pull_request) Failing after 27h4m28s
CI / Python SDK (pull_request) Failing after 27h5m17s
CI / Telegram Mini App (pull_request) Failing after 27h6m43s
CI / Contracts (pull_request) Failing after 27h8m40s
CI / Secrets Scan (pull_request) Failing after 27h9m34s
e596c2ec1d
Шаг Typecheck в job API падал с FATAL JavaScript heap out of memory
(heap ~1550MB при container --memory=3g). Inline-форма
`NODE_OPTIONS=... npx tsc` не доходит до процесса tsc в act/forgejo-runner —
v8 остаётся на дефолтном лимите. api tsc крупнее app, поэтому упирается
в дефолт и падает (app с тем же inline проходит, т.к. меньше).

Перенёс NODE_OPTIONS в env-блок шага (инжектится как docker -e, применяется
надёжно — тот же приём, что рабочий Build-шаг). 4096 — лимит, не резерв,
фактическое потребление tsc < 3g cap.
[CL-CI-OOM] CI(api): tsc heap через прямой node CLI-арг (env NODE_OPTIONS игнорится в act)
Some checks failed
CI / API (pull_request) Failing after 4m35s
PR Janitor / janitor (pull_request) Failing after 26h44m51s
CI / Prisma Migrate Gate (pull_request) Failing after 26h45m2s
CI / Python SDK (pull_request) Failing after 26h45m33s
CI / Telegram Mini App (pull_request) Failing after 26h46m37s
CI / Contracts (pull_request) Failing after 26h48m31s
CI / App (pull_request) Failing after 26h49m32s
CI / Secrets Scan (pull_request) Failing after 26h49m49s
61ea8d85fb
Предыдущий env-блок не помог: act/forgejo-runner НЕ пробрасывает step-env
NODE_OPTIONS в процесс tsc — он остаётся на дефолтном heap ~1550MB
(container_mem/2 при --memory=3g) и падает в JS heap OOM.

Проверено decisive-тестом: raw docker run --memory=3g node:22 с
NODE_OPTIONS=4096 даёт heap_limit 4144MB (флаг работает в чистом контейнере),
значит дело именно в проброске env раннером, не в самом node.

Рабочая форма в этом раннере — флаг прямым CLI-аргом node (репо уже так
запускает prerender в app/deploy и проходит):
  node --max-old-space-size=4096 node_modules/typescript/bin/tsc --noEmit
andrei left a comment
No description provided.
Code review approved. NODE_OPTIONS=4096MB фиксит OOM в CI. Безопасно, документировано.
andrei merged commit 4d1ce6c0a6 into master 2026-06-25 10:28:30 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
europa-tech-srl/europatech!861
No description provided.