Skip to content

runtime build and config: one project root for src_dir projects (ENG-2758, ENG-2759) - #303

Open
nicksinas wants to merge 4 commits into
mainfrom
nsinas/src-dir-one-root
Open

nicksinas wants to merge 4 commits into
mainfrom
nsinas/src-dir-one-root

Conversation

@nicksinas

Copy link
Copy Markdown
Contributor

Summary

ENG-2758 and ENG-2759. Both hit a project whose avocado.yaml sits in a subdirectory with src_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 build writes the signed TUF staging files to .tuf-staging-tmp under the config file's directory, but the copy script reads them from /opt/src, which is the mounted src_dir. The copy fails, both staging functions drop the bool from run_container_command, and the build prints Generated deployment delegation staging and exits 0 with no tuf-staging/targets.json in the runtime. The only trace is a cp: cannot stat line in the log.

ENG-2759. cd project/avocado && avocado install fails with Extension '<ext>' declares source: { type: package } but its configuration has not been merged. The container layer writes .avocado-state in the working directory. merge_installed_remote_extensions read it from src_dir, found nothing, and could not read the fetched extension configs. ext fetch did not help. get_extensions_dir had the same mismatch.

Changes

  • runtime build: the staging root is config.project_root, the same directory the container mounts at /opt/src. A failed copy returns an error, which the caller already reports as Skipping TUF delegation staging: .... The temp dir is removed on both paths.
  • config: both readers load the volume state through the new VolumeState::load_from_current_dir, the key get_or_create_volume writes and StampSearchRoot::for_container already reads. src_dir stays the base for path: sources.

Not changed: the lock file is still keyed on src_dir and the volume pointer on the working directory. Keying the volume on src_dir instead would orphan every existing volume for a src_dir project. 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_dir
  • load_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 on main at b796364 on macOS (BSD sed -i, no sha256sum), none in the touched files. fmt and clippy clean on the touched files.

End to end, on macOS with the avocado-vm, a qemu-quickstart copy at project/avocado/avocado.yaml with src_dir: .., run from project/avocado, 2024/edge, qemux86-64. Same script and fixture against main and this branch.

Step main this branch
avocado install from the config directory exit 1, has not been merged (ENG-2759) exit 0
avocado build not reached exit 0, no cannot stat, no staging skip
tuf-staging/targets.json in the runtime volume not reached present

Regression: smoke (install, build, install again on the reference layout with no src_dir) passes 3 of 3 on this branch. Fixture and script: wip/cli-rc6-fixtures/src-dir/ and local-scripts/cli-rc6-validate.sh in the workspace, not in this repo.

Follow-up (not in this PR)

  • The staging copy error is reported as a skip and the build still exits 0, as every staging error does today.
  • ENG-2648: the 23 empty-root path sites.

…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.
Copilot AI balanced review requested due to automatic review settings October 16, 2026 22:18

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants