I reusable workflow Node non sono utilizzabili nei repo dove package.json non è in root #4

Closed
opened 2026-08-01 17:29:49 +00:00 by LucaZanni · 1 comment
Owner

Problema

I reusable workflow Node (quality-gates, dependency-check, dependency-outdated, npm-publish, auto-release) eseguono npm ci e gli altri comandi npm nella root del repository chiamante, senza possibilità di configurarla.

Nei repo dove il pacchetto Node non sta in root, ogni job muore subito:

npm error code EUSAGE
npm error The `npm ci` command can only install with an existing package-lock.json

Casi reali riscontrati oggi:

Repo Dove sta il pacchetto Node Perché
PZeta_Touch/pzeta-calendar typescript/ repo multi-linguaggio (go/, java/, php/, python/, typescript/)
PZeta_Touch/pzeta-king server/ root = docs/ + submodule front/ + server/

Perché non era aggirabile dal chiamante

I reusable workflow non ereditano defaults.run.working-directory dal workflow chiamante, e questi template non espongono un input equivalente: gli unici disponibili sono node-version e, per quality-gates, npm-version.

L'unica via era rinunciare ai template e reinlineare i job nel repo chiamante. È esattamente ciò che è stato fatto in entrambi i repo — ma in pzeta-calendar la regressione si era già ripresentata tre volte, perché a ogni riallineamento ai template condivisi la working-directory andava persa di nuovo.

Soluzione

Aggiunto l'input opzionale working-directory (default .) ai 5 workflow Node e alle rispettive varianti -github, applicato via defaults.run.working-directory a livello di job — quindi copre tutti gli step run senza toccare gli step uses (checkout, setup-node, cache), che devono continuare a operare sulla root.

Il default . rende la modifica retrocompatibile: nessun repo che usa già i template cambia comportamento.

Uso lato chiamante:

jobs:
  quality-gates:
    uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates.yml@v1
    with:
      working-directory: typescript

Criteri di accettazione

  • I 5 workflow Node accettano working-directory e le varianti -github sono allineate
  • Con l'input omesso il comportamento resta identico a oggi (verifica su un repo con package.json in root)
  • Con working-directory valorizzato, npm ci gira nella sottocartella (verifica su pzeta-calendar o pzeta-king)
  • Il tag mobile v1 viene spostato solo dopo entrambe le verifiche
## Problema I reusable workflow Node (`quality-gates`, `dependency-check`, `dependency-outdated`, `npm-publish`, `auto-release`) eseguono `npm ci` e gli altri comandi npm nella **root del repository chiamante**, senza possibilità di configurarla. Nei repo dove il pacchetto Node non sta in root, ogni job muore subito: ``` npm error code EUSAGE npm error The `npm ci` command can only install with an existing package-lock.json ``` Casi reali riscontrati oggi: | Repo | Dove sta il pacchetto Node | Perché | |---|---|---| | `PZeta_Touch/pzeta-calendar` | `typescript/` | repo multi-linguaggio (`go/`, `java/`, `php/`, `python/`, `typescript/`) | | `PZeta_Touch/pzeta-king` | `server/` | root = `docs/` + submodule `front/` + `server/` | ## Perché non era aggirabile dal chiamante I reusable workflow **non ereditano `defaults.run.working-directory`** dal workflow chiamante, e questi template non espongono un input equivalente: gli unici disponibili sono `node-version` e, per `quality-gates`, `npm-version`. L'unica via era rinunciare ai template e reinlineare i job nel repo chiamante. È esattamente ciò che è stato fatto in entrambi i repo — ma in `pzeta-calendar` la regressione si era già ripresentata **tre volte**, perché a ogni riallineamento ai template condivisi la `working-directory` andava persa di nuovo. ## Soluzione Aggiunto l'input opzionale `working-directory` (default `.`) ai 5 workflow Node e alle rispettive varianti `-github`, applicato via `defaults.run.working-directory` a livello di job — quindi copre tutti gli step `run` senza toccare gli step `uses` (checkout, setup-node, cache), che devono continuare a operare sulla root. Il default `.` rende la modifica **retrocompatibile**: nessun repo che usa già i template cambia comportamento. Uso lato chiamante: ```yaml jobs: quality-gates: uses: https://gitea.pzetatouch.it/devops/shared-actions/.gitea/workflows/quality-gates.yml@v1 with: working-directory: typescript ``` ## Criteri di accettazione - [ ] I 5 workflow Node accettano `working-directory` e le varianti `-github` sono allineate - [ ] Con l'input omesso il comportamento resta identico a oggi (verifica su un repo con package.json in root) - [ ] Con `working-directory` valorizzato, `npm ci` gira nella sottocartella (verifica su `pzeta-calendar` o `pzeta-king`) - [ ] Il tag mobile `v1` viene spostato solo dopo entrambe le verifiche
Author
Owner

Verificato in CI reale, tag v1 spostato

Implementato in dae2a74. Il tag mobile v1 è stato spostato solo dopo entrambe le prove, per non propagare un'eventuale rottura a tutti i repo che lo referenziano.

Il dubbio da sciogliere era se Gitea Actions (runner act, non GitHub) valuti l'espressione ${{ inputs.working-directory }} dentro defaults.run — la sintassi è corretta su GitHub, ma non è una garanzia qui.

Prova 1 — input omesso, retrocompatibilità

PZeta_Touch/pzeta-validation (package.json in root), run #44success.

Dal log, tutti gli step run:

docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/N] user= workdir=.

Il campo workdir vale . dove nei run precedenti era vuoto: prova che defaults.run.working-directory viene applicato e che l'espressione con fallback || '.' è stata valutata. Un semplice "il job passa" non sarebbe bastato — con valore . un defaults ignorato darebbe lo stesso esito.

Prova 2 — input valorizzato

Stesso repo, pacchetto fittizio in testpkg/ con script che stampano process.cwd(), chiamato con working-directory: testpkg. Run #45success:

workdir=testpkg
npm ci  →  up to date, audited 1 package
lint:check   eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg
typecheck    eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg
format:check eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg
build        eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg
test         eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg

npm ci ha risolto il lockfile della sottocartella, e gli step uses (checkout, setup-node, cache) hanno continuato a operare sulla root, come previsto.

Il branch temporaneo di test e il pacchetto fittizio sono stati rimossi; pzeta-validation è pulito su main.

Stato

v1dae2a74. Nessuna azione richiesta ai repo esistenti: con l'input omesso il comportamento è identico a prima.

pzeta-calendar e pzeta-king restano per ora con i job Node inlineati — funzionanti e verdi. Possono tornare ai template condivisi passando working-directory: typescript e working-directory: server, quando si preferisce; a quel punto va rimosso il commento di avviso in testa ai loro workflow, che documentava proprio l'assenza di questo input.

## Verificato in CI reale, tag `v1` spostato Implementato in `dae2a74`. Il tag mobile `v1` è stato spostato **solo dopo** entrambe le prove, per non propagare un'eventuale rottura a tutti i repo che lo referenziano. Il dubbio da sciogliere era se Gitea Actions (runner `act`, non GitHub) valuti l'espressione `${{ inputs.working-directory }}` dentro `defaults.run` — la sintassi è corretta su GitHub, ma non è una garanzia qui. ### Prova 1 — input omesso, retrocompatibilità `PZeta_Touch/pzeta-validation` (package.json in root), run #44 → **success**. Dal log, tutti gli step `run`: ``` docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/N] user= workdir=. ``` Il campo `workdir` vale `.` dove nei run precedenti era **vuoto**: prova che `defaults.run.working-directory` viene applicato e che l'espressione con fallback `|| '.'` è stata valutata. Un semplice "il job passa" non sarebbe bastato — con valore `.` un `defaults` ignorato darebbe lo stesso esito. ### Prova 2 — input valorizzato Stesso repo, pacchetto fittizio in `testpkg/` con script che stampano `process.cwd()`, chiamato con `working-directory: testpkg`. Run #45 → **success**: ``` workdir=testpkg npm ci → up to date, audited 1 package lint:check eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg typecheck eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg format:check eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg build eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg test eseguito in /workspace/PZeta_Touch/pzeta-validation/testpkg ``` `npm ci` ha risolto il lockfile della sottocartella, e gli step `uses` (checkout, setup-node, cache) hanno continuato a operare sulla root, come previsto. Il branch temporaneo di test e il pacchetto fittizio sono stati rimossi; `pzeta-validation` è pulito su `main`. ### Stato `v1` → `dae2a74`. Nessuna azione richiesta ai repo esistenti: con l'input omesso il comportamento è identico a prima. `pzeta-calendar` e `pzeta-king` restano per ora con i job Node inlineati — funzionanti e verdi. Possono tornare ai template condivisi passando `working-directory: typescript` e `working-directory: server`, quando si preferisce; a quel punto va rimosso il commento di avviso in testa ai loro workflow, che documentava proprio l'assenza di questo input.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: devops/shared-actions#4