From e664ba613bf0b9f7cb292f82a5b79a1f4c463420 Mon Sep 17 00:00:00 2001 From: Todor Kolev Date: Wed, 2 Sep 2026 12:45:04 +0000 Subject: [PATCH] =?UTF-8?q?build:=20=D0=B5=D0=B4=D0=BD=D0=B0=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20=D0=BD=D0=B0=20Node=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B2=D1=81=D1=8F=D0=BA=D1=8A=D0=B4=D0=B5=20(24)=20?= =?UTF-8?q?=D0=B8=20Dependabot=20=D0=B7=D0=B0=20npm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Node беше три различни неща наведнъж: engines казваше >=22, workflow-ите ползваха 22 (ci, deploy, scripts-test) и 24 (related-persons-data и вторият job на scripts-test), devcontainer-ът беше 22, а нямаше нито .node-version, нито .nvmrc. Резултатът е, че локално и в CI кодът върви върху различни runtime-и - точно така локалният пайплайн се разминава със сървърния, без някой да е избирал това. Изборът е 24, защото related-persons-data вече го изисква (node:sqlite DatabaseSync и native TS type-stripping без експериментален флаг) и това е единственият workflow, който наистина зависи от версията. Останалите просто не бяха обновени. - .node-version и .nvmrc = 24; engines.node >=24 - всички workflow-и на 24 (ci, deploy, двата job-а на scripts-test) - devcontainer образът на typescript-node:24-bookworm, пиннат по digest както досега (digest-ът е от манифест-индекса на MCR) - коментарът в scripts-test, който обосноваваше 24 "спрямо 22 по-горе", вече казва истината: разликата между двата job-а е node_modules, не runtime-ът Dependabot: досегашният файл покриваше само GitHub Actions и твърдеше, че npm "се обработва отделно" - не се обработваше от нищо, затова за уязвимости научавахме чак когато Dependency audit стане червен на main (browserslist, 2026-09-02). Блокът за actions е запазен дословно; добавен е npm: седмично, minor+patch в един групиран PR, мажорите по един PR за видимост, а шест от тях (react-router 8, TypeScript 7, @ai-sdk 4, ai 7, workers-types 5) изрично отложени за след релийза - миграции със собствен риск. Подовете в overrides остават единственият източник на security пинове; Dependabot мести lockfile-а, те са границата. Проверено локално с Node v24.20.0: lint, typecheck, целият turbo пакет, node --test scripts/*.test.mjs и cacbg/tr пакетът. По ревюто: мажорите остават НЕгрупирани. Отворен minor/patch PR маркира членовете си за "обработени" преди Dependabot да погледне негрупираните обновления (dependabot-core#14202), тъй че мажор за същия пакет се появява едва след като седмичният PR се мърджне или затвори; втора група не поправя това - тя само събира мажорите и добавя обратното потискане. Коментарите вече казват точно това, както и че override в pnpm-workspace.yaml е замяна, не под, а игнорираните мажори са потиснати, не "видими". jsdom 30 влиза в отложените: иска undici ^8.9, а override-ът в pnpm-workspace.yaml е замяна, не под, и би дал неподдържан граф. Коментарът и командата за преразрешаване в Dockerfile, както и CONTRIBUTING, вече не сочат Node 22. --- .devcontainer/Dockerfile | 6 +-- .github/dependabot.yml | 60 +++++++++++++++++++++++++++--- .github/workflows/ci.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/scripts-test.yml | 8 ++-- .node-version | 1 + .nvmrc | 1 + CONTRIBUTING.md | 2 +- package.json | 2 +- 9 files changed, 69 insertions(+), 15 deletions(-) create mode 100644 .node-version create mode 100644 .nvmrc diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 84eee8a9e..3c8640da8 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,10 +1,10 @@ -# Digest-pinned to the 22-bookworm multi-arch index resolved on 2026-06-16. +# Digest-pinned to the 24-bookworm multi-arch index resolved on 2026-09-02. # The tag is kept for readability; the @sha256 is what actually pins the image. # Re-resolve with: curl -fsSL -D - -o /dev/null \ # -H 'Accept: application/vnd.oci.image.index.v1+json' \ -# https://mcr.microsoft.com/v2/devcontainers/typescript-node/manifests/22-bookworm \ +# https://mcr.microsoft.com/v2/devcontainers/typescript-node/manifests/24-bookworm \ # | grep -i docker-content-digest -FROM mcr.microsoft.com/devcontainers/typescript-node:22-bookworm@sha256:59e8c044af4ed4795967188c3d0b9bc677f42d42b0ff41f98c8be5333defeb64 +FROM mcr.microsoft.com/devcontainers/typescript-node:24-bookworm@sha256:3c84ba4842b181e699f9494842dbf737a3c96cc3a6028dd83f9a9d9b6f059d1a ARG WRANGLER_VERSION=4 # uv installer is fetched from a version-pinned path (astral.sh/uv//install.sh), diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bf1ea944b..17ac1bccd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,8 +1,22 @@ -# Keeps the SHA-pinned GitHub Actions in .github/workflows/ fresh. Dependabot rewrites the pinned -# commit SHA and updates the trailing `# vX.Y.Z` comment, so we keep the supply-chain safety of -# pinning without the pins silently going stale. Scoped to github-actions only — the npm/pnpm -# dependency surface is handled separately (and the security-sensitive @babel/core pin is a manual -# override in pnpm-workspace.yaml). +# Two surfaces, one file. +# +# GitHub Actions: keeps the SHA-pinned actions in .github/workflows/ fresh. Dependabot rewrites the +# pinned commit SHA and updates the trailing `# vX.Y.Z` comment, so we keep the supply-chain safety of +# pinning without the pins silently going stale. +# +# npm/pnpm: until 2026-09-02 this surface had NO automation, and advisories reached us only when the +# Dependency audit step turned main red (browserslist, that day). Weekly minor+patch bumps arrive as +# ONE grouped PR. Majors are NOT grouped: each comes as its own PR — but only while no grouped +# minor/patch PR is open for that dependency, because Dependabot marks a grouped PR's members as +# handled before it looks at ungrouped updates (dependabot/dependabot-core#14202). Merging (or +# closing) the weekly PR promptly is what keeps majors flowing; a second group would not fix this, +# it would just batch the majors and add the reverse suppression. The majors listed under `ignore` +# are deferred past the release (each is a migration with its own risk) and are SUPPRESSED, not +# surfaced — delete an entry to see it again. Security updates are not configured here: GitHub raises +# them on its own once enabled for the repo, and the Dependency audit step (osv-scanner) fails CI on a +# real advisory regardless of Dependabot. The security-sensitive pins (browserslist, undici, …) are +# overrides in pnpm-workspace.yaml, maintained by hand: a pnpm override is a REPLACEMENT of every +# resolution, not a floor, so a Dependabot PR that needs a newer one must lift the override with it. version: 2 updates: - package-ecosystem: github-actions @@ -17,3 +31,39 @@ updates: commit-message: prefix: ci include: scope + + - package-ecosystem: npm + directory: '/' + schedule: + interval: weekly + day: monday + time: '06:00' + timezone: Europe/Sofia + open-pull-requests-limit: 5 + groups: + # minor + patch in one weekly PR — one CI run, one review, instead of ten small ones. Majors stay + # ungrouped on purpose (see the header for the #14202 caveat). + minor-and-patch: + update-types: [minor, patch] + # majors deferred past the release (see the header) — suppressed until an entry is removed + ignore: + - dependency-name: react-router + update-types: [version-update:semver-major] + - dependency-name: '@react-router/*' + update-types: [version-update:semver-major] + - dependency-name: typescript + update-types: [version-update:semver-major] + - dependency-name: '@ai-sdk/*' + update-types: [version-update:semver-major] + - dependency-name: ai + update-types: [version-update:semver-major] + - dependency-name: '@cloudflare/workers-types' + update-types: [version-update:semver-major] + # jsdom 30 needs undici ^8.9, while pnpm-workspace.yaml overrides undici to ^7.29 — and a pnpm + # override is a REPLACEMENT, not a floor, so that PR would install an unsupported graph. Lift both + # together, not one at a time. + - dependency-name: jsdom + update-types: [version-update:semver-major] + commit-message: + prefix: build + include: scope diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8958cd339..6d05a4443 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,7 +58,7 @@ jobs: - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: 24 cache: pnpm - run: pnpm install --frozen-lockfile - name: Dependency audit diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2ed7a02ac..dc850a2e4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -86,7 +86,7 @@ jobs: - uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: 24 cache: pnpm - run: pnpm install --frozen-lockfile diff --git a/.github/workflows/scripts-test.yml b/.github/workflows/scripts-test.yml index 61deb9f7a..2d738a66e 100644 --- a/.github/workflows/scripts-test.yml +++ b/.github/workflows/scripts-test.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: 24 # node:test only — the scripts under test import nothing outside node built-ins and each other, # so no `pnpm install` is required. The one external dependency is the `sqlite3` binary, which # ship-e2e.test.mjs drives as the real target its fake wrangler writes into; it ships with the @@ -33,8 +33,10 @@ jobs: # свързани-лица pipeline tests — the CACBG leg (parse/classify/load/audit/extract) and the # Търговски регистър leg (scripts/tr: ЕИК checksum, HTTP client, deed cache). These use node:sqlite # (DatabaseSync) and import the shared companyNameKey .ts via the register-ts resolve hook, so they - # need Node 24 (node:sqlite + native TS type-stripping, no experimental flag) rather than the Node 22 - # above. The libel-critical resolution logic gates merges here. + # need Node 24 (node:sqlite + native TS type-stripping, no experimental flag) — which is now the one + # Node version everywhere (.node-version, engines, every workflow, the devcontainer), so the split + # between the two jobs is about node_modules, not the runtime. The libel-critical resolution logic + # gates merges here. cacbg: runs-on: ubuntu-latest timeout-minutes: 10 diff --git a/.node-version b/.node-version new file mode 100644 index 000000000..a45fd52cc --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24 diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..a45fd52cc --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c837c3a89..9f8a05981 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ ## Среда за разработка Хранилището е пригодено за **Devcontainer** (нужни са Docker или съвместим и редактор с -поддръжка на devcontainer). Изисквания извън контейнера: Node `>=22` и `pnpm` (виж +поддръжка на devcontainer). Изисквания извън контейнера: Node `>=24` и `pnpm` (виж `packageManager` в `package.json`). ```bash diff --git a/package.json b/package.json index 26ab02ffa..423d149e1 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "packageManager": "pnpm@10.33.0", "engines": { - "node": ">=22" + "node": ">=24" }, "scripts": { "dev": "turbo run dev",