Repository navigation
Conversation
…y (ENG-2758) The staging files were written under the config file's directory, but the copy script reads them from /opt/src, which is the resolved src_dir. With src_dir set the copy failed, and both staging functions dropped the bool from run_container_command, so the build printed the success line and shipped a runtime with no tuf-staging/targets.json. project_root is now the staging root, and a failed copy returns an error, which the caller already reports as "Skipping TUF delegation staging".
get_or_create_volume writes .avocado-state in the process working directory. merge_installed_remote_extensions and get_extensions_dir read it from src_dir, so a src_dir: .. project run from its config directory found no volume, could not read its fetched extension configs, and install failed with "has not been merged". The stamps code already keys on cwd. VolumeState::load_from_current_dir is the one reader for that key.
There was a problem hiding this comment.
🟡 Changes recommended
Concurrent board builds sharing a source root can overwrite or delete each other's TUF staging files.
1 open issue
What changed in this PR
Fixes runtime staging and extension lookup for projects whose configuration directory differs from src_dir.
Changes:
- Places TUF staging under the resolved project root and reports failed copies.
- Reads volume state from the working directory.
- Adds regression tests for project-root and volume-state resolution.
| File | Description |
|---|---|
| src/utils/volume.rs | Adds working-directory state loading and a regression test. |
| src/utils/config.rs | Updates state readers and tests src_dir root resolution. |
| src/commands/runtime/build.rs | Aligns staging paths and checks copy results. |
Review effort: Balanced
| // which is the resolved `src_dir`, so they have to be written under | ||
| // that root and not under the config file's directory. The two differ | ||
| // whenever `src_dir` is set. | ||
| let project_dir = config.project_root(&self.config_path); |
There was a problem hiding this comment.
Fixed in the latest push. Each staging call now gets its own tempfile directory under the project root (.tuf-staging-<random>/), the copy script reads that directory as /opt/src/<name>/, and the handle removes it on drop. Unit test tuf_staging_dir_is_unique_per_call_and_removed_on_drop. Re-ran the src_dir: .. fixture end to end: install and build exit 0, tuf-staging/targets.json present, no staging directory left behind. Within one avocado build the runtime builds already run one after another, so the overlap needs two separate builds sharing a src_dir; the fix covers that too.
Lockfile only. Clears the nine cargo audit findings that fail the Security Audit job on every PR: RUSTSEC-2026-0338 to 0342 (quinn-proto, fixed in 0.11.18) and RUSTSEC-2026-0346 to 0349 (rustls, fixed in 0.23.46). Both crates are transitive, pulled in through reqwest. (cherry picked from commit 0cd54a7)
Review follow-up on #303. Builds that share a src_dir shared one .tuf-staging-tmp; overlapping runs could overwrite or delete each other's files. Each call now gets its own tempfile directory under the project root, the copy script reads that directory, and the handle removes it on drop.

Summary
ENG-2758 and ENG-2759. Both hit a project whose
avocado.yamlsits in a subdirectory withsrc_dir: .., the "one config per board under a shared source tree" layout the 0.41.1 changelog says is supported. Two commits, one bug each.ENG-2758.
avocado buildwrites the signed TUF staging files to.tuf-staging-tmpunder the config file's directory, but the copy script reads them from/opt/src, which is the mountedsrc_dir. The copy fails, both staging functions drop the bool fromrun_container_command, and the build printsGenerated deployment delegation stagingand exits 0 with notuf-staging/targets.jsonin the runtime. The only trace is acp: cannot statline in the log.ENG-2759.
cd project/avocado && avocado installfails withExtension '<ext>' declares source: { type: package } but its configuration has not been merged. The container layer writes.avocado-statein the working directory.merge_installed_remote_extensionsread it fromsrc_dir, found nothing, and could not read the fetched extension configs.ext fetchdid not help.get_extensions_dirhad the same mismatch.Changes
runtime build: the staging root isconfig.project_root, the same directory the container mounts at/opt/src. A failed copy returns an error, which the caller already reports asSkipping TUF delegation staging: .... The temp dir is removed on both paths.config: both readers load the volume state through the newVolumeState::load_from_current_dir, the keyget_or_create_volumewrites andStampSearchRoot::for_containeralready reads.src_dirstays the base forpath:sources.Not changed: the lock file is still keyed on
src_dirand the volume pointer on the working directory. Keying the volume onsrc_dirinstead would orphan every existing volume for asrc_dirproject. ENG-2648 (empty config parent) lists 23 other path sites; neither of these is among them and none are touched.Testing
Unit tests, new:
project_root_follows_src_dir_above_the_config_dirload_from_current_dir_reads_the_working_directory_only(serial, changes cwd and restores it)cargo test --no-fail-fast: 1982 passed, 5 failed. The same 5 fail onmainatb796364on macOS (BSDsed -i, nosha256sum), none in the touched files. fmt and clippy clean on the touched files.End to end, on macOS with the avocado-vm, a
qemu-quickstartcopy atproject/avocado/avocado.yamlwithsrc_dir: .., run fromproject/avocado, 2024/edge, qemux86-64. Same script and fixture againstmainand this branch.mainavocado installfrom the config directoryhas not been merged(ENG-2759)avocado buildcannot stat, no staging skiptuf-staging/targets.jsonin the runtime volumeRegression:
smoke(install, build, install again on the reference layout with nosrc_dir) passes 3 of 3 on this branch. Fixture and script:wip/cli-rc6-fixtures/src-dir/andlocal-scripts/cli-rc6-validate.shin the workspace, not in this repo.Follow-up (not in this PR)