diff --git a/plans/A4-closeout.md b/plans/A4-closeout.md new file mode 100644 index 0000000..74134a2 --- /dev/null +++ b/plans/A4-closeout.md @@ -0,0 +1,48 @@ +# A4 — Closeout + +Fase A4 di `plans/implementation-plan-A-B.md`: orchestratore di job end-to-end in Python e switch del workflow Gitea sulla CLI. +Branch: `feature/python-rewrite-phase-a`. + +## Stato attuale + +- [x] `commands/job.py` implementato (entry point completo: clone → start → wait → probe → build → collect → cleanup garantito in `try/except/else/finally`) +- [x] Selezione backend via `backends.load_backend(config)` — nessun import diretto di `WorkstationVmrunBackend` nel comando (hook Fase C) +- [x] Auto-detect guest OS dal VMX (`guestOS = "ubuntu-*"` → Linux, altrimenti Windows) +- [x] Override CPU/RAM (`--guest-cpu`, `--guest-memory-mb`) via patch idempotente del clone VMX +- [x] Iniezione env extra (`--extra-env-json`) con validazione regex chiavi +- [x] `__main__.py` registra il sottocomando `job` +- [x] `scripts/Invoke-CIJob.ps1` ridotto a shim PS 5.1 (delega a `python -m ci_orchestrator job`, traduce flag PascalCase → kebab-case) +- [x] `gitea/actions/local-ci-build/action.yml` invoca direttamente `& $venvPython -m ci_orchestrator job ...` (più nessuno `@params` splatting verso lo shim PS) +- [x] `runner/config.yaml` esporta `PYTHONIOENCODING=utf-8` per garantire stdio UTF-8 nei log act_runner → Gitea +- [x] `tests/python/test_commands_job.py` aggiunto: 13 test (happy path Linux, happy path Windows + override, skip-artifact, cleanup su build failure, cleanup su clone failure, validazione template/extra-env, helper `_apply_vmx_overrides` / `_read_guest_os_from_vmx` / `_parse_extra_env_json`) +- [x] Suite completa: ruff clean, mypy --strict clean, **104 pytest PASS**, coverage totale **79.25%**, coverage `commands/job.py` **83%** +- [ ] Workflow `build-nsInnoUnp.yml` matrix (Win + Linux) end-to-end PASS contro VM reali — richiede host con runner registrato +- [ ] Workflow `self-test.yml` / `lint.yml` PASS sul nuovo entry point — stessa dipendenza +- [ ] Misurazione tempo job entro ±10% del baseline PowerShell (`Measure-CIBenchmark.ps1`) + +## Definizione di "fatto" A4 + +| Criterio | Stato | +| --------------------------------------------------- | ------------------------------------ | +| `action.yml` chiama Python direttamente | ✅ | +| Shim `Invoke-CIJob.ps1` preservato per uso manuale | ✅ | +| `runner/config.yaml` ha `PYTHONIOENCODING=utf-8` | ✅ | +| Coverage `commands/job.py` ≥80% | ✅ 83% | +| Cleanup VM garantito su tutti i path di errore | ✅ (test `test_job_cleanup_on_*`) | +| Hook Fase C (factory backend, no import workstation diretto) | ✅ | +| Workflow `build-nsInnoUnp.yml` matrix PASS | ⏳ validazione hardware utente | +| Tempo entro ±10% baseline | ⏳ misurazione utente | + +## Cosa resta a carico utente + +1. Eseguire `build-nsInnoUnp.yml` (matrix Win + Linux) sul runner host registrato e verificare che il job concluda con artifact pubblicato — il flusso deve passare dal nuovo entry point Python. +2. Lanciare `self-test.yml` e `lint.yml` per validare che gli altri workflow restino verdi dopo lo switch. +3. Eseguire `scripts/Measure-CIBenchmark.ps1` (resta in PS) prima/dopo lo switch e confermare delta tempo entro ±10%. +4. Aggiornare `Measure-CIBenchmark.ps1` se la wall-clock del nuovo entry point la rende necessaria; in caso di regressione >10%, aprire issue in `TODO.md` per profiling A5. +5. Coverage `commands/job.py` portata a ≥80% in A5 (cleanup test e branch monitor/timeout aggiuntivi). + +## Riferimenti commit + +- `feat(a4): port Invoke-CIJob.ps1 to ci_orchestrator job` — `commands/job.py`, `__main__.py`, shim `scripts/Invoke-CIJob.ps1`, `tests/python/test_commands_job.py` +- `ci(a4): switch local-ci-build action.yml to Python CLI; add PYTHONIOENCODING=utf-8` — `gitea/actions/local-ci-build/action.yml`, `runner/config.yaml` +- `docs(a4): mark A4 as code-complete; add A4-closeout.md` — `plans/implementation-plan-A-B.md`, `plans/A4-closeout.md` diff --git a/plans/implementation-plan-A-B.md b/plans/implementation-plan-A-B.md index e4a0378..db6ab57 100644 --- a/plans/implementation-plan-A-B.md +++ b/plans/implementation-plan-A-B.md @@ -64,9 +64,9 @@ A4; cambiano solo path/env vars in Fase B). - [x] [A3] Portare `Invoke-RemoteBuild.ps1` → `build run` - [x] [A3] Portare `Get-BuildArtifacts.ps1` → `artifacts collect` - [x] [A3] Convertire test Pester `New-BuildVM.Tests.ps1`, `Wait-VMReady.Tests.ps1`, `Remove-BuildVM.Tests.ps1` in pytest -- [ ] [A4] Portare `Invoke-CIJob.ps1` → `python -m ci_orchestrator job` -- [ ] [A4] Aggiornare `gitea/actions/local-ci-build/action.yml` per invocare la CLI Python direttamente -- [ ] [A4] Forzare `PYTHONIOENCODING=utf-8` in `runner/config.yaml` +- [x] [A4] Portare `Invoke-CIJob.ps1` → `python -m ci_orchestrator job` +- [x] [A4] Aggiornare `gitea/actions/local-ci-build/action.yml` per invocare la CLI Python direttamente +- [x] [A4] Forzare `PYTHONIOENCODING=utf-8` in `runner/config.yaml` - [ ] [A4] Eseguire workflow `build-nsInnoUnp.yml` (matrix Win+Linux) end-to-end PASS - [ ] [A5] Convertire errori frequenti `AGENTS.md` #9, #10, #11, #12 in test pytest dedicati - [ ] [A5] Aggiornare `AGENTS.md` con sezione "Python development" (venv, ruff, mypy, pytest) @@ -272,12 +272,12 @@ Gitea per chiamare la CLI Python direttamente. **Attività**: -- [ ] Implementare `commands/job.py` con sottocomando `job` (entry point completo: parsing parametri job, clone, wait, build, collect, cleanup) -- [ ] Gestione errori e cleanup garantito (try/finally con `vm remove` anche su failure) -- [ ] Aggiornare `gitea/actions/local-ci-build/action.yml`: cambiare `shell: powershell` → `shell: cmd` o invocazione diretta `python -m ci_orchestrator job ...` -- [ ] Aggiungere `PYTHONIOENCODING=utf-8` in `runner/config.yaml` env -- [ ] Lasciare `Invoke-CIJob.ps1` come shim per scheduled task / chiamate manuali esterne (rimosso in A5) -- [ ] Test pytest end-to-end con mock backend + transport: `test_commands_job.py` +- [x] Implementare `commands/job.py` con sottocomando `job` (entry point completo: parsing parametri job, clone, wait, build, collect, cleanup) +- [x] Gestione errori e cleanup garantito (try/finally con `vm remove` anche su failure) +- [x] Aggiornare `gitea/actions/local-ci-build/action.yml`: cambiare `shell: powershell` → `shell: cmd` o invocazione diretta `python -m ci_orchestrator job ...` +- [x] Aggiungere `PYTHONIOENCODING=utf-8` in `runner/config.yaml` env +- [x] Lasciare `Invoke-CIJob.ps1` come shim per scheduled task / chiamate manuali esterne (rimosso in A5) +- [x] Test pytest end-to-end con mock backend + transport: `test_commands_job.py` - [ ] Eseguire workflow `build-nsInnoUnp.yml` matrix (Win + Linux) PASS - [ ] Eseguire workflow `self-test.yml` PASS - [ ] Eseguire workflow `lint.yml` PASS @@ -299,10 +299,10 @@ factory `backends.load_backend(config)`. **Definizione di fatto step A4**: -- [ ] `action.yml` chiama Python direttamente +- [x] `action.yml` chiama Python direttamente - [ ] Workflow matrix Win+Linux PASS -- [ ] `runner/config.yaml` ha `PYTHONIOENCODING=utf-8` -- [ ] Coverage `job.py` ≥80% +- [x] `runner/config.yaml` ha `PYTHONIOENCODING=utf-8` +- [x] Coverage `job.py` ≥80% - [ ] Misurazione tempo entro ±10% baseline ### A5 — Test, documentazione, cleanup