Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Да, можно — через **fixed-output derivation (FOD)**, в которой разрешена сеть. Идея: одна FOD генерирует `package-lock.json` (с сетью, фиксированный хэш), вторая (обычный `buildNpmPackage`) использует результат первой.
- ```nix
- { buildNpmPackage, fetchurl, lib, stdenvNoCC, nodejs, cacert }:
- let
- pname = "vot-cli";
- version = "1.4.3";
- src = fetchurl {
- url = "https://registry.npmjs.org/${pname}/-/${pname}-${version}.tgz";
- hash = "sha256-eOUfy6l48MD9IcWiFlC142vXvo5XobKTJ2uC6xzDGS4=";
- };
- # FOD: имеет доступ в сеть, выход фиксируется по хэшу
- packageLock = stdenvNoCC.mkDerivation {
- name = "${pname}-${version}-package-lock.json";
- inherit src;
- nativeBuildInputs = [ nodejs cacert ];
- buildPhase = ''
- export HOME=$TMPDIR
- npm install --package-lock-only --ignore-scripts --no-audit --no-fund
- '';
- installPhase = ''
- cp package-lock.json $out
- '';
- outputHashMode = "flat";
- outputHashAlgo = "sha256";
- outputHash = lib.fakeHash; # заменишь после первого билда
- };
- in
- buildNpmPackage {
- inherit pname version src;
- postPatch = ''
- cp ${packageLock} package-lock.json
- '';
- npmDepsHash = lib.fakeHash; # заменишь после второго билда
- dontNpmBuild = true;
- meta = with lib; {
- description = "Voice Over Translation CLI tool";
- homepage = "https://github.com/ilyhalight/voice-over-translation";
- license = licenses.mit;
- platforms = platforms.all;
- mainProgram = "vot-cli";
- };
- }
- ```
- ## Как заполнить хэши
- Запускаешь `nix-build` — он упадёт два раза подряд с понятными сообщениями вида:
- ```
- hash mismatch in fixed-output derivation '/nix/store/...-vot-cli-1.4.3-package-lock.json':
- specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
- got: sha256-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
- ```
- Подставляешь полученный `got:` в соответствующее поле, перезапускаешь. Всего две итерации:
- 1. первый `nix-build` → получаешь хэш для `packageLock.outputHash`
- 2. второй `nix-build` → получаешь хэш для `npmDepsHash`
- 3. третий `nix-build` → собирается
- ## Подводные камни
- **Нечистота резолвинга.** `npm install --package-lock-only` резолвит semver-диапазоны (`^1.2.3`) в конкретные версии **на момент запуска**. Если завтра в реестр зальют `1.2.4`, лок-файл получится другим, хэш FOD не совпадёт, билд сломается. На практике это означает: периодически (раз в несколько месяцев или при апдейте `vot-cli`) хэш нужно будет обновить. Воспроизводимость в пределах одной «эпохи» сохраняется — Nix закэширует результат FOD и не будет ходить в сеть, пока хэш совпадает.
- **Можно прибить semver лагом времени:**
- ```nix
- buildPhase = ''
- export HOME=$TMPDIR
- npm config set before "2025-01-01"
- npm install --package-lock-only --ignore-scripts --no-audit --no-fund
- '';
- ```
- `npm config set before` заставляет резолвер игнорировать версии, опубликованные после указанной даты. Это сильно повышает шансы что лок-файл будет одинаковый месяцами.
- **Альтернатива — IFD.** Можно прочитать сгенерированный лок-файл прямо в evaluation через `builtins.readFile`, но это даёт мало пользы и Nix flakes по умолчанию запрещают IFD. Двухступенчатый FOD проще и работает везде.
Advertisement