Керування залежностями

Як сайт встановлює, перевіряє та оновлює свої npm-залежності

npm-залежності закріплені зафіксованим package-lock.json, а встановлення виконують лише перевірені скрипти життєвого циклу. Щодо моделі загроз та обґрунтування цих заходів див. Безпека ланцюга постачання.

Контракти встановлення

CI, devcontainer та Netlify встановлюють із точним блокуванням версій та без скриптів, а потім явно повторно вмикають єдиний перевірений хук: повторну збірку hugo-extended, яка завантажує зафіксований бінарний файл Hugo. За середовищами:

  • CI: npm run ci:min; завдання, які збирають сайт, після цього виконують npm run ci:prepare.
  • Devcontainer: npm run install:safe — той самий контракт зі збереженням опціональних залежностей.
  • Netlify: npm run install:safe, який виконує команда збірки після inert auto-install, між перевірками чистоти робочого дерева:
    • Відхилення блокування або будь-які інші зміни, видимі в Git, призводять до збою збірки.
    • Для збоїв на шляхах, яких встановлення ніколи не торкалося, див. Застарілий кеш збірки Netlify нижче.
  • Локально: npm run install:safe або стандартне npm install, яке слідує за блокуванням, поки воно узгоджується з package.json, і обмежує скрипти життєвого циклу дозволеним списком, а не вимикає їх; див. локальне налаштування.

Вкладене налаштування теми Docsy дотримується того самого контракту: крок prepare викликає власне точне, без скриптів, встановлення залежностей теми.

Застарілий кеш збірки Netlify

Netlify зберігає кеш збірки для кожного контексту розгортання:

  • Один для робочої версії
  • Один для кожного вже зібраного PR, створений на основі кешу робочої версії під час першої збірки PR.

Кожен кеш містить клон репозиторію, а перехід на коміт, який прибирає git-субмодуль, залишає робоче дерево субмодуля на місці, тож видалений субмодуль може через кеш повернутися у наступні збірки як невідстежуваний залишок і призвести до збою перевірок чистоти робочого дерева: журнал розгортання показує шлях у статусному рядку з префіксом ??.

Очистіть відповідний кеш збірки, а не додавайте шлях до .gitignore:

  • Робоча версія:
    • Очистіть кеш і розгорніть сайт: Deploys > Trigger deploy.
  • Deploy Previews: кожен вже зібраний PR має власну копію кешу, на яку пізніше очищення кешу робочої версії не впливає.
    • Очистіть його зі сторінки останнього розгортання PR: Retry > Clear cache and retry with latest branch commit. Масового очищення по всіх PR немає.

Оновлення залежностей

Планові оновлення

npm run update:packages оновлює лише package.json. До запропонованих версій застосовується період охолодження. Потім перегенеруйте блокування та зафіксуйте обидва файли разом:

npm install --package-lock-only --ignore-scripts

Пакунки зі скриптами

Коли додаєте або оновлюєте пакунок, який має чи потребує запис allowScripts, учасник, що вносить зміну:

  1. Переглядає скрипти життєвого циклу нової версії.
  2. Записує результат, зафіксований разом зі зміною залежності та перевірений під час рецензування PR: потрібний скрипт — як схвалення з точною версією, непотрібний — як заборона на рівні назви (false, яка не потребує оновлення при наступних підвищеннях версій).
  3. Для нового схвалення також додає пакунок до винятку автоматичного злиття Renovate у .github/renovate.json5: кожне підвищення схваленого пакунка потребує наведених вище кроків, тож його PR з оновленням мають чекати на учасника.

Обслуговування файлу блокування

  • Ви змінили залежності: перегенеруйте блокування, як у планових оновленнях, і зафіксуйте його разом із package.json.
  • Конфлікт злиття у файлі блокування: візьміть версію з main і повторно виконайте команду регенерації.
  • Файл блокування змінився, але ви не змінювали залежності (перевірка postinstall попереджає, коли встановлення робить це): це ознака відхилення; відновіть блокування та дослідіть причину, а не фіксуйте перезапис.

Заходи безпеки ланцюга постачання

Період охолодження випусків

Визначення версій ігнорує випуски, молодші за налаштований мінімальний вік.

  • Вимога: min-release-age у .npmrc.
  • Сфера дії:
    • Зачіпаються лише операції визначення версій; точні встановлення з блокуванням (npm ci) не визначають версії.
    • npm надає перевагу конфігурації проєкту над конфігурацією користувача, тож суворіший період охолодження у вашому власному .npmrc тут послаблюється до значення проєкту; щоб зберегти своє для одного виклику, встановіть змінну середовища npm_config_min_release_age, яка має вищий пріоритет за обидва.
  • Renovate: застосовує власний період охолодження до PR з оновленнями, які він відкриває, заданий minimumReleaseAge у .github/renovate.json5; довший для оновлень, які зливаються без рецензування людиною.

Дозволений список скриптів життєвого циклу

Встановлення виконує скрипти життєвого циклу пакунка лише тоді, коли його точна назва та версія внесені до списку дозволів allowScripts:

  • Вимога: мапа allowScripts у package.json, яка стає стандартно закритою через strict-allow-scripts у .npmrc.
  • Заборони:
    • Запис зі значенням false фіксує переглянуту заборону: пакунок встановлюється, його скрипт пропускається.
    • Заборони нічого не надають, тож вони покривають пакунок за назвою, на всіх версіях.
  • Взаємодія з --ignore-scripts:
    • Дозволений список лише фільтрує: він ніколи не вмикає повторно скрипти, які вимикає ignore-scripts, тож встановлення без скриптів не виконують жодних, дозволених чи ні.
    • Переглянутий виняток вимагає явного --ignore-scripts=false у місці виклику.

Мінімальна версія npm

Встановлення завершується збоєм, коли активний npm старший за мінімальну версію engines: найстарішу версію, яка підтримує наведені вище заходи.

  • Забезпечення:
    • engines у package.json задає мінімальну версію.
    • engine-strict у .npmrc робить це закритим.
  • Політика мінімальної версії:
    • Мінімальна версія зростає, коли npm виправляє прогалини у забезпеченні цих заходів.
    • Вона слідує за версіями npm, вбудованими у Node LTS, тож стандартний інструментарій проходить перевірку.
  • Netlify:
    • Стандартний npm, вбудований у Node від Netlify, може бути старшим за мінімальну версію; NPM_VERSION у netlify.toml закріплює версію, яка її задовольняє.
    • Оновлюйте закріплення щонайменше тоді, коли зростає мінімальна версія.

Автоматичне встановлення Inert Netlify

Автоматичне встановлення Netlify на початку збірки нейтралізується NPM_FLAGS у netlify.toml:

  • --dry-run: npm вирішує та логує, що змінило б встановлення, але нічого не записує.
  • --ignore-scripts: скрипти життєвого циклу залишаються вимкненими за явною вказівкою, а не як побічний ефект сухого запуску.

Сфера дії: NPM_FLAGS — це налаштування збірки Netlify, а не конфігурація npm; він застосовується лише до автоматичного встановлення, ніколи до запусків npm у команді збірки.

Захист у глибину: справжнє встановлення — це npm ci, яке замінює node_modules повністю, тож залишки автоматичного встановлення чи кешу збірки там не переживають збірку, навіть якщо node_modules невидиме для перевірок чистоти робочого дерева (вони бачать лише зміни, видимі в Git).

Жодного голого npx

Обвʼязка репозиторію (скрипти пакунка, CI, допоміжні скрипти, документація для учасників) ніколи не викликає бінарний файл як npx BIN: на застарілому чи відсутньому node_modules npx звертається до публічного реєстру та виконує будь-який пакунок, якому належить ця назва. Його запит на встановлення не є захистом: він пропускається в неінтерактивних контекстах і провокує бездумне «так» в інших. Локалізовані копії документації для учасників наздоганяють це правило через відстеження відхилень.

  • Натомість:
    • Скрипти пакунка викликають бінарні файли, надані залежностями, безпосередньо; npm додає node_modules/.bin до їхнього PATH, а відсутній бінарний файл завершується гучним збоєм без жодного звернення до реєстру.
    • Контексти без запису в PATH (документація, окремі скрипти) використовують npm exec --no -- BIN, який ніколи нічого не встановлює.
  • Забезпечення: дисципліна рецензування; автоматичної перевірки немає.
Востаннє змінено July 12, 2026: [uk] Ukrainian documentation for OpenTelemetry (4cc17d8b)