Commit Graph
11 Commits
Author SHA1 Message Date
Simone a7a22a29be feat(cache): restore and publish the cargo dependency cache around Linux builds
Restore runs after the source is in place and before the build; publish runs
only after a successful build and only on a miss, so the steady state uploads
nothing and a failed build can never become an entry. The whole path is
best-effort: a cache problem degrades to a cold build with a message rather
than turning a good build red.

Gated on Cargo.lock being present, so non-Rust jobs are untouched with no flag
to set. The Windows branch is not touched at all.

The prune script is read through importlib.resources rather than a path
relative to the repo root: the production venv is installed non-editable, so a
parents[] walk lands in site-packages where scripts/ does not exist.

The fake transport gained substring-matched canned results; indexing by call
position broke as soon as the cache added calls mid-flow.

Mutation-tested rather than assumed. Three guards were each disabled in turn --
the publish call, the prune-refusal check, the packing-failure check -- and a
test went red for each. The prune-refusal test initially survived its mutant:
it passed because the fake's fetch left no file behind, so publishing failed
for an unrelated reason. Fixed by making fetch write a real file, so the only
thing preventing publication is the guard under test.
2026-07-22 20:59:23 +02:00
Simone a211833316 feat(build): optional xvfb-run for Linux GUI builds
Add an --xvfb switch to 'build run' and 'job' that wraps the Linux build
command in 'xvfb-run -a sh -c ...', giving GUI toolkits (GTK4/PyGObject)
a headless $DISPLAY. Exported env vars precede xvfb-run so they
propagate into the virtual-display session. No-op (with a notice) for
Windows guests.

The local-ci-build composite action exposes it as the 'xvfb' input
(default false), forwarded as INPUT_XVFB -> --xvfb, mirroring the
use-shared-cache/skip-artifact wiring.

Docs: WORKFLOW-AUTHORING.md parameter table + Linux example note;
LINUX-TEMPLATE-SETUP.md Step 4a (the template ships python3-gi
gir1.2-gtk-4.0 xvfb). Adds build-run unit tests (wrap, plain, Windows
no-op).
2026-06-06 13:38:34 +02:00
Simone 2b2d8d9968 fix: eliminate Linux build clock skew from RTC/NTP race
Linux clones could boot with the RTC interpreted as local time (guest
runs hours ahead of UTC). NTP then steps the clock backward at runtime,
landing after source mtimes were stamped, so make reported "Clock skew
detected" and future-dated files.

- build run: enable NTP and block until NTPSynchronized before stamping
  the sources, so the backward correction happens pre-touch. Drop
  `hwclock -s`, which read the local-time RTC and pushed the clock further
  ahead.
- template prepare-linux: set-local-rtc 0 so clones interpret the RTC as
  UTC and boot at the correct time; NTP then only nudges, never steps 2h.

Linux/SSH path only; WinRM branch untouched.
2026-05-31 17:45:32 +02:00
Simone 83a0e46e6b feat(build): live-stream Linux build output; ns7zip via in-guest clone
- SshTransport.run_streaming: incremental channel recv, forwards
  stdout/stderr live (no more one-block-at-end). _linux_build uses it
  with PYTHONUNBUFFERED so the guest python flushes promptly.
- _tail_lines split out for failure messages (no double print).
- Windows live streaming deferred (TODO 8.2) — pypsrp execute_ps
  returns only at completion.
- build-ns7zip.yml: use-git-clone:'true' (in-guest), repo-url ->
  https://gitea.emulab.it/... (guest-reachable; host SSH alias was
  host-only). Requires GiteaPAT in the LocalSystem keyring or a public
  nsis-plugin-ns7zip.
2026-05-17 20:51:48 +02:00
Simone 90ecce7dc0 fix(build): flush guest build output + put tail in failure message
On a non-zero build the guest stdout/stderr was written unflushed
then a ClickException raised, so the cause was lost (only
"build command failed (exit 1)" surfaced). _report_build_output now
emits the output with markers, flushes both streams, and returns the
last lines which are appended to the failure message — diagnosable
even if act_runner buffering drops the body. Applied to Linux + Windows.
2026-05-17 17:47:17 +02:00
Simone 6c9822b929 refactor(artifacts): harmonize Windows to Linux raw-file collection
Windows produced an intermediate C:\CI\output\artifacts.zip that
upload-artifact then re-zipped (zip-in-zip), while Linux deposited raw
files. Make both paths consistent: the build stages raw outputs into a
collect dir; collect zips it only as a transport archive, fetches, and
extracts into the host artifact dir; actions/upload-artifact produces
the single final archive.

- _windows_build: param artifact_zip -> output_dir; stage raw files
  (in-place when source IS the collect dir, else wipe+copy), no
  Compress-Archive; absolute artifact-source resolved.
- _windows_collect: zip guest dir as transport, fetch, extract (mirror
  _linux_collect); guest_path is now the collect directory.
- job.py / build_run CLI: pass output_dir; rename --guest-artifact-zip
  -> --guest-output-dir.
- Tests updated for the raw-file contract.
2026-05-17 16:30:34 +02:00
Simone 54a7fd4171 fix(build): fetch pinned commit (shallow clone lacks it)
git clone --depth 1 --branch X only fetches the branch tip. When the
branch advances between workflow trigger and runner pickup, checking
out the pinned commit failed with "reference is not a tree: <sha>".
Fetch that exact commit (git fetch --depth 1 origin <sha>) before
checkout, on both Linux (SSH) and Windows (WinRM) paths.
2026-05-17 16:17:55 +02:00
Simone 0c68013e87 fix(build): Linux artifact staging — absolute source + don't wipe output
Two bugs made the Linux smoke "succeed" with an empty artifact:
- artifact_source was always joined as workdir + '/' + src, so an
  absolute source (/opt/ci/output) became /opt/ci/build//opt/ci/output
  and was never found — only a non-fatal WARNING was logged.
- `rm -rf output_dir` ran unconditionally; when the build writes
  directly into the collect dir (the smoke case: output == source),
  it deleted the build output before collection.

Resolve absolute vs workdir-relative; when the source is the output
dir, collect in place without wiping; a missing/empty source is now a
hard failure instead of a silent empty artifact.
2026-05-17 16:12:50 +02:00
Simone 1b2b6acb45 fix(build): run Windows build cmd as PowerShell; resolve absolute artifact-source
Two Windows-guest build bugs:
- The build command was wrapped in `cmd /c`, so PowerShell-authored
  commands failed ("'New-Item' is not recognized"). Run it as PS
  (seed LASTEXITCODE=0 so PS-only commands exit cleanly).
- artifact_source was always Join-Path'd with the workdir; an absolute
  source (C:\CI\output) became C:\CI\build\C:\CI\output. Use the path
  as-is when rooted, else Join-Path the workdir.
2026-05-17 15:50:17 +02:00
Simone 57bfc41a5a docs,config: aggiorna AGENTS.md, config.example, HOST-SETUP.md, checklist faseA e fix vari orchestrator (workstation, build, job, wait, winrm, test) 2026-05-17 00:14:04 +02:00
Simone 1b80a99b47 feat(a3): port build pipeline (vm new, build run, artifacts collect)
Implements Phase A3 of plans/implementation-plan-A-B.md:

- commands/vm.py: vm new (replaces New-BuildVM.ps1)

- commands/build.py: build run (replaces Invoke-RemoteBuild.ps1) with WinRM/SSH dispatch and stdout streaming for act_runner

- commands/artifacts.py: artifacts collect (replaces Get-BuildArtifacts.ps1) using transport.fetch()

- 3 PS scripts reduced to shims preserving \0

- Pester tests/{New-BuildVM,Wait-VMReady,Remove-BuildVM}.Tests.ps1 removed; equivalent cases covered in pytest

- Phase C hook: build/artifacts accept opaque VmHandle/vmx; no Windows path assumptions

Tests: 91 pytest, ruff clean, mypy --strict clean, coverage 78.27% (>=70 gate).

Master checklist + step A3 attivita + 'definizione di fatto' updated; A3-closeout.md added.
2026-05-14 18:34:03 +02:00