Commit Graph
30 Commits
Author SHA1 Message Date
vhaudiquet 961f6bc234 deb: wipe the staged tree when overlay staging falls back to a copy
On a resumed session whose overlay mount fails (no overlayfs, mount
error, non-overlay driver), the fallback used to copy the host tree
into the staged tree of the previous attempt: a merge that keeps the
old build stamps and resurrects files deleted on the host — a
silently half-stale build, exactly what resume must never produce.
The driver now reports the failure instead of copying, and the
caller wipes the staged build root and re-stages a fresh copy
(environment resumable, build artifacts discarded).
2026-09-27 23:32:16 +02:00
vhaudiquet 0f1446ad4d context: stage trees over a caller-supplied overlay upperdir
Resumable build sessions need to re-mount the staged tree over the
same overlay upperdir on every attempt: the build artifacts written
inside the chroot (object files) live there, while the host tree
stays visible as the live lowerdir. Add an optional
ensure_available_with_overlay staging path (OverlayStaging reports
whether the persistent upperdir was actually mounted or a fresh copy
was staged instead) with a default implementation rejecting the
request, so drivers without overlay support degrade cleanly.

The overlay mount itself is factored out of try_overlay_mount into
mount_overlay, taking optional pinned upper/work directories; a
failed mount only cleans up the directories it created, never the
caller-pinned ones.
2026-09-26 11:50:39 +02:00
vhaudiquet 681fa3d687 context: add ContextDriver::is_dir
list_files returns context-relative paths (rooted inside the chroot
for an unshare context, on the remote for ssh): whether an entry is
a directory can only be decided through the context, never with a
host-side stat. Give every driver a proper is_dir rather than
approximating it with exists, so callers can keep directories and
files apart — the deb package-directory search lists directories
only.
2026-09-22 14:29:12 +02:00
vhaudiquet ae5b0042e4 context: name temp dirs atomically, not probe-then-create
CI / build (push) Successful in 2m58s
CI / test (push) Skipped
CI / snap (push) Successful in 4m39s
create_temp_dir probed for a free pkh-<seconds> name and then created
the directory, so two contexts arriving together could both observe a
free name and unpack into the same directory — observed as two e2e
tests started within the same second failing on 'File exists when
hard linking' during the chroot tarball unpack.

Name with sub-second precision and create atomically: a losing race
gets AlreadyExists and falls through to the next attempt, which
removes the probe window instead of narrowing it. The schroot and
ssh drivers already use mktemp -d and need no change.
2026-09-20 19:47:24 +02:00
vhaudiquet 31fe6dc524 context: run commands in the C locale by default
Subprocesses inherit the session environment, so a translated host
locale leaked into builds: perl-based packaging tools
(dpkg-architecture, dpkg-parsechangelog, quilt, ...) warned about
missing locale settings, change their output with the environment,
and dpkg-buildpackage treats some of that output as data.

Default every command to LANG=C and LC_ALL=C; a caller can still
override explicitly through envs().
2026-09-20 19:06:04 +02:00
vhaudiquet c2dae4f3f9 lift main.rs business logic into the library
The chlog target-series resolution becomes changelog::series_candidates
(UNRELEASED pinning, development-series default and fallbacks modeled
by SeriesCandidates), PPA references get package_info::split_ppa
(shared by pull and deb, now also rejecting empty parts), and SSH
endpoints get context::ContextConfig::from_endpoint — so a library
consumer can resolve series, validate PPAs and build context
configurations without reimplementing the CLI's rules. All three carry
unit tests; main.rs keeps only parsing of flags and error handling.
2026-09-18 20:51:36 +02:00
vhaudiquet 8ad50aaf83 put: check the SFTP close status after uploads
ssh2::File's Drop discards the close-handshake error ('too late to
recover'), so a quota or server-side abort surfacing in the final ACKs
was recorded as a successful upload of a truncated file. Close upload
handles explicitly and propagate the error; also applies to the ssh
context driver's write_file and upload_recursive, which had the same
silent-drop issue.
2026-09-17 16:36:36 +02:00
vhaudiquet 4c26122357 test: keep cargo test output quiet with per-test logs and a failure matrix
cargo test used to be unreadable: subprocesses inherited the terminal, so
dpkg-buildpackage, apt and configure output interleaved with the harness
summary, and env_logger lines from parallel tests crossed each other.

New test_support module, compiled into test binaries only (inert stubs
otherwise) and initialized before main via .init_array:

- all log output goes to target/pkh-test-logs/<test>.log, one file per
  test thread, so concurrent tests never interleave
- context-launched commands are captured line by line into the same file
  (driver-level wrapper); test-code spawns use run_logged()
- a panic hook records failures and an atexit callback prints a matrix
  (test name, panic location, message, log path) after the libtest
  summary; tests panicking on purpose can opt out with a guard

Also fixes two test bugs found on the way:

- diff_checkbuilddeps_matrix compared dpkg-checkbuilddeps diagnostics
  against English messages without pinning the locale
- run_source_build in differential tests now captures output like the
  live-UI path does
2026-09-17 15:18:23 +02:00
vhaudiquet 6a5c5a7106 context: fix deadlock and panics when resolving parented contexts
set_current held the config RwLock for writing across make_context,
which for a context with a parent re-entered the same lock through
Context::new's global-manager lookup, deadlocking 'pkh context use'.
Context building is now lock-free by construction: make_context
resolves parent chains against a snapshot map (also rejecting parent
cycles), and neither set_current nor remove_context holds a guard
while building a Context.

A corrupt contexts.json no longer aborts every command at manager
init: load falls back to the default local-only config, backs the
corrupt file up to contexts.json.bak so a later save cannot silently
destroy it, and a dangling current/parent context falls back to local
with an error log instead of panicking.
2026-09-16 02:27:11 +02:00
vhaudiquet 592e98c1e9 deb: pass the build context explicitly instead of swapping the global
build_binary_package installed its ephemeral chroot context into the
process-global manager and read it back with context::current(),
ignoring its ctx parameter: two concurrent builds would re-point each
other's global and each drop would clean up whichever chroot was
current at the time. The guard now keeps the Arc of the context it
created (parented directly on the base context, not on a config-name
lookup), exposes it via context(), and Drop cleans up exactly that
context and restores the exact handle that was current at creation,
so overlapping builds no longer cross-destroy each other.
2026-09-16 02:05:40 +02:00
vhaudiquet f508f20846 context: quote program, args, cwd and env in ssh, schroot and unshare drivers
All three non-local drivers assembled remote/chroot command strings by
raw concatenation: ssh pushed args verbatim (TODO: escape), schroot
interpolated env values raw so DEB_BUILD_OPTIONS='parallel=4 nocheck'
made sh treat 'nocheck' as the command, and unshare wrapped args in
unescaped double quotes letting quotes break out and $/backticks
expand. Add a shared POSIX shell_quote helper and use it for every
component interpolated into a shell string, including ssh copy_path
(which used Rust's {:?}, not shell quoting) and schroot write_file
(which also switches echo -ne to printf %s so backslash sequences in
content are no longer interpreted).
2026-09-16 00:36:02 +02:00
vhaudiquet 86612efb00 deb: strip VCS metadata from prepared build trees
CI / build (push) Successful in 2m53s
CI / test (push) Skipped
CI / snap (push) Failing after 23s
Copying a git checkout verbatim into /tmp/pkh-build-*/ ships '.git',
flipping autotools' building-from-VCS detection (GNU hello's
BUILD_FROM_GIT): the shipped man page gets cleaned and regenerated
via help2man, which is correctly not in Build-Depends. Skip VCS
dirs (.git/.hg/.svn/.bzr/CVS) in local/unshare/ssh copies, and
prune them after an unshare overlayfs mount.
2026-08-24 17:33:44 +02:00
vhaudiquet c9b48d4573 build: live view for source builds, pin LC_ALL for the pipeline
Route 'pkh build' through the DebUi capture machinery 'pkh deb'
already uses instead of letting dpkg-source inherit the terminal:

- pin LANG=C and LC_ALL=C so dpkg-source emits deterministic English
  diagnostics regardless of the session locale;
- new DpkgSourceClassifier rewrites info:/warning:/error: lines into
  colored pane entries, telling benign tar warnings from failures;
- DebUi generalizes for reuse (arbitrary phase labels, build-specific
  log naming); run_source_build() drives phases and pipes subprocess
  output through the sink when a UI is present;
- glyph-free house-style summaries: 'Built in Ns:' plus artifact
  paths relative to cwd; failures print captured errors + log path;
- drop/capitalize pipeline chatter, add 'pkh build --verbose' to
  bypass the view like 'pkh deb --verbose'.
2026-08-24 11:58:19 +02:00
vhaudiquet e5adf600c3 deb: change ui/ux of pkh deb
CI / build (push) Successful in 2m54s
CI / test (push) Skipped
CI / snap (push) Failing after 12s
2026-08-22 22:26:20 +02:00
vhaudiquet 317dbcd062 deb: use overlayfs instead of copy
CI / build (push) Failing after 14m44s
CI / snap (push) Has been skipped
2026-08-12 15:44:13 +02:00
vhaudiquet a0d35bb18e pull,context: preserve file mtimes when copying sources
CI / build (push) Successful in 8m11s
CI / snap (push) Successful in 6m9s
std::fs::copy resets the destination mtime to "now", which breaks
timestamp-based build systems (autotools/gnulib). Packages like
'hello' from Debian sid ship pre-generated files alongside their
prerequisites; when the copy flattens all mtimes, make considers the
generated targets out-of-date and tries to regenerate them with tools
(e.g. gperf) that are not declared build-dependencies, failing the
build.

Restore the source modification and access times after every file copy
in pull::copy_dir_all, pull::fetch_archive_sources merge step, and
context::unshare copy_dir_recursive/ensure_available.
2026-07-24 14:14:18 +02:00
vhaudiquet 768e1c4f78 fmt
CI / build (push) Failing after 1m56s
CI / snap (push) Has been skipped
2026-07-22 14:36:28 +02:00
vhaudiquet c4b59a4376 context: copy symlinks as symlinks and improve error messages 2026-07-17 10:12:46 +02:00
vhaudiquet 7640952bdc unshare: mount proc differently depending on root privileges 2026-03-19 11:26:10 +01:00
vhaudiquet 8345f51d2f Multiple changes:
CI / build (push) Successful in 16m23s
CI / snap (push) Successful in 4m1s
- deb: can use ppa as dependency
- deb: cross and regular are using parallel nocheck builds
- deb: ephemeral will not pull keyring if no root powers
2026-02-06 12:04:25 +01:00
vhaudiquet dfd197415f unshare: fix device creation code 2026-01-26 10:26:16 +01:00
vhaudiquetandvhaudiquet b724d46f2c deb: fix concurrent testing (by making them serial)
CI / build (push) Successful in 8m34s
Co-authored-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
Co-committed-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
2026-01-11 00:32:03 +00:00
vhaudiquet 42e6165f78 context/unshare: mount proc after forking
CI / build (push) Failing after 6m46s
2026-01-09 23:36:27 +01:00
vhaudiquet a444a5d8d2 deb: fix bug in find_dsc_file
CI / build (push) Failing after 5m35s
2026-01-09 23:15:13 +01:00
vhaudiquet dd62baa455 context/unshare: mount proc and dev/pts 2026-01-09 23:08:59 +01:00
vhaudiquet b3365afe5b docs: added documentation, enforced documentation
CI / build (push) Successful in 7m21s
2026-01-01 18:37:40 +01:00
vhaudiquetandvhaudiquet 1538e9ee19 deb: cross-compilation, ephemeral contexts, local builds
CI / build (push) Successful in 7m18s
Multiple changes:
- New contexts (schroot, unshare)
- Cross-building quirks, with ephemeral contexts and repositories management
- Contexts with parents, global context manager, better lifetime handling
- Local building of binary packages
- Pull: pulling dsc files by default
- Many small bugfixes and changes

Co-authored-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
Co-committed-by: Valentin Haudiquet <valentin.haudiquet@canonical.com>
2025-12-25 17:10:44 +00:00
vhaudiquet 106c61a096 context: refactor context command running
CI / build (push) Successful in 1m55s
2025-12-17 10:05:47 +01:00
vhaudiquet b5ac76a293 deb: retrieve .deb artifacts
CI / build (push) Successful in 2m2s
sbuild options: unshare, build directory

context: retrieve files
2025-12-16 20:12:08 +01:00
vhaudiquet 1d65d1ce31 context: add context
CI / build (push) Successful in 1m50s
pkh context allows to manage contexts (local, ssh) and run contextualized commands (deb)

in other words, this allows building binary packages over ssh
2025-12-15 20:48:44 +01:00