Очередной забавный кейс с npm



Есть у нас приложение, которое поднимает стенды с приложеньками, «ферма» называется. Вот просто, качает нужную ветку из git, делает условно npm ci && npm run build && npm run start и поднимает инстанс, на который мы натравливаем E2E. Да-да, мы знаем про докер, но пока не успели.



И вот буквально позавчера ловим странный баг. В одной из веток не устанавливается несколько зависимостей. Просто нет их node_modules. Локально не повторяется. Захожу на ферму, дёргаю npm ci из консоли — всё ок. Зависимости не ставятся:



1) только когда npm ci вызывается из самой фермы через child_process.exec,

2) только на конкретной ветке.



Ооок. Я магию не люблю, потому сажусь разбираться. Посмотрим что там в env. Ого, а там npm_config_legacy_peer_deps: 'true' . П-нятненько почему зависимости не ставятся, они же peerDeps.



Две загадки:



1) Откуда legacy-peer-deps залетает в env,

2) Почему он влияет не всегда.



Что ж, ответ на первую. В папке самой фермы в .npmrc лежит legacy-peer-deps=true. Когда мы её запускаем через npm run start npm читает .npmrc и прокидывает в env всю свою лабуду в npm_config_*. А child_process.exec запускает дочерние процессы с process.env родителя.



Ответ на вторую загадку. npm ci --legacy-peer-deps не разрушал приложение, потому что ставил все зависимости как и было написано в package-lock.json. Но в конкретной ветке случилась коллизия, зависимость поставили и в devDependencies и в просто dependencies. Вот после этого npm ci перестал доверять package-lock.json и пересчитал всё дерево, уже тихо применяя к нему правило --legacy-peer-deps.



Люблю я эту работу.