# pnpm-install Aktywuje pnpm przez corepack i instaluje zależności z lockfile'a. ```yaml - uses: actions/checkout@v7 - uses: https://git.cierzniak.it/gitea-runner/actions/pnpm-install@v1 - run: pnpm run lint:js ``` Podprojekt w monorepo, z cache'em store'a: ```yaml - uses: https://git.cierzniak.it/gitea-runner/actions/pnpm-install@v1 with: working-directory: ./wizard cache: 'true' ``` `args` zastępuje **całą** listę flag, więc `--frozen-lockfile` trzeba powtórzyć: ```yaml - uses: https://git.cierzniak.it/gitea-runner/actions/pnpm-install@v1 with: args: --frozen-lockfile --ignore-scripts ``` ## Wejście | Input | Wymagany | Domyślnie | Co to | | --- | --- | --- | --- | | `working-directory` | nie | `.` | Katalog z `package.json` i `pnpm-lock.yaml` | | `version` | nie | — | Wersja pnpm. Pusta bierze ją z pola `packageManager`; podana **nadpisuje to pole** | | `args` | nie | `--frozen-lockfile` | Pełna lista argumentów `pnpm install` | | `cache` | nie | `false` | `'true'` cache'uje store pnpm między jobami | Outputów nie ma. Node i corepack pochodzą z obrazu joba — akcja nie stawia żadnego z nich. Sprawdzone na `git.cierzniak.it/gitea-runner/node:24` (Node 24.18.1, corepack 0.35.0). ## Dlaczego tak **`args` to jeden input, nie `frozen-lockfile` plus `extra-args`.** Kto go podaje, przejmuje całą listę flag. Dwa inputy wymagałyby reguły, co się dzieje przy `frozen-lockfile: true` i `args: --no-frozen-lockfile` — tu takiego stanu nie ma. **Wersja pnpm domyślnie z `packageManager`.** To pole jest już źródłem prawdy dla corepacka lokalnie, a wpisanie jej drugi raz do workflow tworzy dwa źródła, które rozjeżdżają się po pierwszym bumpie. Input `version` jest przede wszystkim dla repozytoriów bez tego pola — bez niego samo `corepack enable` nie ma czego aktywować. **`version` dokłada `COREPACK_ENABLE_PROJECT_SPEC=0`, bo inaczej nic by nie robił.** Samo `corepack prepare pnpm@X --activate` ustawia tylko wersję *domyślną*, do której corepack sięga przy braku `packageManager`; obecne pole ją przebija. Sprawdzone: w projekcie z `packageManager: pnpm@9.15.9` po `prepare pnpm@10.20.0 --activate` dalej odpowiada `9.15.9` (`COREPACK_ENABLE_STRICT=0` też nie pomaga — dopiero `COREPACK_ENABLE_PROJECT_SPEC=0` daje `10.20.0`). Bez tego input byłby cichym no-opem: ustawiasz, nic się nie zmienia, zero błędu. Cena jest taka, że przy podanym `version` pole `packageManager` przestaje obowiązywać — dlatego zostawiaj go pustym wszędzie, gdzie to pole istnieje. **Cache jest opt-in i domyślnie wyłączony.** [ADR-0014](https://git.cierzniak.it/gitea-runner/images/src/branch/main/docs/adr/0014-akcje-cache-i-artefaktow-na-v3.md) trzyma `actions/cache` na majorze 3, bo od v4.2 akcja mówi protokołem cache service v2, którego Gitea nie implementuje ([go-gitea#33393](https://github.com/go-gitea/gitea/issues/33393)). Akcja wymaga też skonfigurowanego serwera cache'a — kontener joba i kontener runnera siedzą w różnych przestrzeniach sieciowych, więc bez tego zwraca `ETIMEDOUT`. Runnery tej instancji mają `cache.enabled: true` i `external_server`, ale **żaden workflow jeszcze z tego nie korzystał**. Domyślnie wyłączony cache pozwala to sprawdzić na jednym repo, zamiast robić premierę na wszystkich naraz. **Klucz cache'a liczy `sha256sum`, nie `hashFiles()`.** `hashFiles` to funkcja natywna GitHuba i jej zachowanie w `act_runner` byłoby kolejną niewiadomą dokładaną do i tak niesprawdzonego tutaj `actions/cache`. Do tego sklejanie ścieżki z `working-directory` daje wzorce w rodzaju `.//pnpm-lock.yaml`. `sha256sum` jest w każdym obrazie z `gitea-runner/images` i widać w logu, co policzył. `runner.os` w kluczu idzie za wzorcem oficjalnej `pnpm/action-setup`. **Store jest przypięty do `~/.pnpm-store`, zamiast odczytany z `pnpm store path`.** Dwa powody, oba sprawdzone w obrazie `node:24-bookworm-slim`: 1. Domyślnie store ląduje w **`/.pnpm-store/v3`**, czyli w drzewie roboczym — pnpm celowo szuka miejsca na tym samym systemie plików co projekt, a `/workspace` jest bind-mountem. Job, który commituje (jak `check-pchia` w `ptpa_pl`), ma tam minę. 2. `pnpm store path` przy błędzie **kończy się kodem 0 i wypisuje błąd na stdout** (`EROFS: read-only file system…`). `path=` w `GITHUB_OUTPUT` dostałoby wtedy śmieci, a `actions/cache` cache'owałby nieistniejącą ścieżkę — po cichu, bez czerwonego joba. Przestawia go wyłącznie `npm_config_store_dir`; **`PNPM_STORE_DIR` nie jest ustawieniem pnpm** i nie działa. Zmienna leci przez `$GITHUB_ENV`, żeby dosięgła też kroku instalacji, i tylko przy włączonym cache — przy `cache: false` rozmieszczenie store'a zostaje takie, jakie pnpm wybiera dziś, więc obecni konsumenci nic nie odczuwają. Cache obejmuje `~/.pnpm-store`, a nie podkatalog z wersją, bo ten zależy od majora pnpm — sprawdzone: `v3` przy pnpm 9, `v10` przy pnpm 10. **Akcja obsługuje wyłącznie pnpm.** Wariant wykrywający lockfile i wołający npm albo yarn rozmyłby kontrakt na trzy ścieżki o różnych flagach, różnym modelu cache'a i różnych trybach błędu — z czego dwie nikt by nie testował. Gdy npm będzie potrzebny, dostanie osobną akcję.