Skip to content

Fix: include sub-app Towerfiles in packages#220

Merged
bradhe merged 2 commits intodevelopfrom
fix/towerfile-excluded-from-subapps
Mar 10, 2026
Merged

Fix: include sub-app Towerfiles in packages#220
bradhe merged 2 commits intodevelopfrom
fix/towerfile-excluded-from-subapps

Conversation

@bradhe
Copy link
Contributor

@bradhe bradhe commented Mar 10, 2026

Problem

Packages containing sub-apps with their own Towerfiles were broken: should_ignore_file matched any file named Towerfile and dropped it from the package, not just the root one used to drive the build.

Solution

Thread the specific Towerfile path through the packaging pipeline so only that exact file is excluded. Towerfiles in sub-directories are now treated as ordinary app content.

What changed:

  • should_ignore_file now accepts Option<&Path> (the exact file to exclude) instead of matching by name alone
  • resolve_path and resolve_glob_path accept and forward the same Option<&Path>
  • Package::build canonicalizes spec.towerfile_path and passes it through both the glob loop and the import-path loop

Tests:

  • New test it_includes_subapp_towerfiles_but_excludes_root_towerfile verifies that given a layout like:
    my-app/Towerfile        ← excluded (root, used for building)
    my-app/main.py          ← included
    my-app/subapp/Towerfile ← included (sub-app content)
    my-app/subapp/main.py   ← included
    
    the package contains main.py, subapp/Towerfile, and subapp/main.py, but not the root Towerfile under app/.
  • All existing tests continue to pass.

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4c3a4a2f-a785-49e7-88a6-f69463b2ee1e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/towerfile-excluded-from-subapps

Comment @coderabbitai help to get the list of available commands and usage tips.

}

async fn resolve_path(path: &PathBuf, base_dir: &Path, file_paths: &mut HashMap<PathBuf, PathBuf>) {
async fn resolve_path(path: &PathBuf, base_dir: &Path, file_paths: &mut HashMap<PathBuf, PathBuf>, exclude_path: Option<&Path>) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel it really doesn't make sense to pass in exclude_path and change all the call sites of this function just to exclude the root towerfile because

  1. Calling a function called should_ignore_file then literally passing in a path to ignore feels like a weird separation of concerns where you both want it to tell you whether you should ignore a file, but you also happen to know what one file you should ignore in advance is called
  2. There's only one exclude_path, which makes sense since there's only one path we care to remove atm (i.e. the base Towerfile) but the name suggests like it should be some kinda generic thing, so it's weird to be singular (or weird to be generic)
  3. We're already passing in base_dir here which is derived data from the path of the Towerfile, so we could do something like base_dir.join("Towerfile") instead

Also, not sure why it's Option<>, since presumably we'll always have a base Towerfile?

@bradhe bradhe force-pushed the fix/towerfile-excluded-from-subapps branch from 6acf00f to 13ab0c7 Compare March 10, 2026 11:17
@bradhe
Copy link
Contributor Author

bradhe commented Mar 10, 2026

Good call @socksy — threading Option<&Path> through every function was the wrong shape for this. Refactored in the latest commit: introduced a FileFilter struct that holds the canonicalized root Towerfile path and owns the ignore logic in a should_ignore method. resolve_glob_path and resolve_path now take a &FileFilter, and the old standalone should_ignore_file function is gone. All tests still pass.

@bradhe bradhe force-pushed the fix/towerfile-excluded-from-subapps branch 2 times, most recently from 6e2f77c to 5fe3d05 Compare March 10, 2026 12:31
Previously, should_ignore excluded every file named 'Towerfile' from
the package. This broke apps that contain sub-apps with their own
Towerfiles, since those files were silently dropped.

The fix introduces FileResolver, a struct that owns the base_dir and
the root Towerfile path, and uses it to make all resolution decisions.
Only the exact Towerfile used to build the package is excluded; any
Towerfile living in a sub-directory is included as normal app content.

Changes:
- FileResolver struct owns base_dir and root_towerfile
- Resolution logic lives on FileResolver as async methods (resolve_glob,
  resolve_path) rather than standalone free functions
- should_ignore compares by path identity, not by file name
- Package::build canonicalizes spec.towerfile_path and delegates to
  FileResolver for both the glob loop and the import-path loop
- New integration test it_includes_subapp_towerfiles_but_excludes_root_towerfile
  verifies the exact scenario described above
@bradhe bradhe force-pushed the fix/towerfile-excluded-from-subapps branch from 5fe3d05 to 9e49e97 Compare March 10, 2026 12:38
@bradhe bradhe merged commit 78d74d2 into develop Mar 10, 2026
29 checks passed
@bradhe bradhe deleted the fix/towerfile-excluded-from-subapps branch March 10, 2026 14:19
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