feat: add pnpm-install as a shared composite action
Lifts ptpa_pl's local .gitea/actions/pnpm-install into this repo, parametrised enough for repositories we have not met yet: working-directory, install args, pnpm version and an opt-in store cache. Cache is off by default. ADR-0014 pins actions/cache to major 3 and no workflow on this instance has exercised the cache server yet - a shared action that a dozen jobs hang off is the wrong place to premiere that dependency. Two traps found while testing against ptpa_pl's lockfile in node:24-bookworm-slim, both avoided by pinning the store instead of reading `pnpm store path`: that command defaults to <workspace>/.pnpm-store, inside the working tree where a committing job could sweep it up, and it exits 0 while printing its error to stdout, which would have fed actions/cache a garbage path silently. The version input also carries COREPACK_ENABLE_PROJECT_SPEC=0, without which a packageManager field outranks `corepack prepare --activate` and the input would do nothing at all - no effect, no error.
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# 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 **`<workspace>/.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ę.
|
||||
Reference in New Issue
Block a user