Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix exclusions in build.watch getting applied to all components #2554

Merged
merged 1 commit into from
Jun 13, 2024

Conversation

itowlson
Copy link
Contributor

This tidies some issues arising from the revelation that spin watch understands ! syntax for exclusions after all. Thank you @me-diru for finding these little nasties!

The first issue is that an exclusion in one component affects all other components. This happens because we combine all component globs into one list so that we can run one instance of watchexec, so any exclusions that get chucked into that list and apply list-wide.

The second issue is that adding an exclusion for spin.toml means that components no longer rebuild on manifest changes (e.g. to be build.command). Well, okay, you did ask for the bad thing. Because of the first issue this affects all components which is a bad thing you didn't ask for.

The fix in this PR is, instead of combining the globs, to create a composite filterer which treats a change as triggering if any component expresses an interest in it. A component can still use bang syntax to exclude a file, but if other components are interested in that same file then changes to that file will still cause a rebuild. There is still only one instance of watchexec, but the filterer for the buildifier is now built out of per-component filterers, plus a separate filterer for the manifest (so that it doesn't need to be spliced into individual components, and therefore can't be banged away).

The composite filterer is used only for the build patterns, because assets are derived from the actual file mounts, and therefore don't have the same problem of user-provided pattern syntax.

Copy link
Collaborator

@calebschoepp calebschoepp left a comment

Choose a reason for hiding this comment

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

Couple nits but otherwise LGTM. Thanks for hunting this down Ivan.

Comment on lines 186 to 204
struct CompositeFilterer {
filterers: Vec<Box<dyn watchexec::filter::Filterer>>,
}

impl watchexec::filter::Filterer for CompositeFilterer {
fn check_event(
&self,
event: &watchexec::event::Event,
priority: watchexec::event::Priority,
) -> Result<bool, watchexec::error::RuntimeError> {
for f in &self.filterers {
if f.check_event(event, priority)? {
return Ok(true);
}
}
Ok(false)
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: A comment explaining that any(event) triggers this filter rather than all(event) might be nice.


#[derive(Debug)]
struct CompositeFilterer {
filterers: Vec<Box<dyn watchexec::filter::Filterer>>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: Perhaps put a Vec<Box<dyn watchexec::filter::Filterer>> behind a type alias? Not sure if that is cleaner so I'll leave that up to you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, to my mind it doesn't occur enough, or have a distinct semantic concept other than "vector of filterers", to merit the indirection. I agree Rust's insistence on box-dyn ceremony makes it harder to read than it needs to be though. If we want to do this I think I'd alias the box-dyn and make this Vec<AnyFilterer>...

Signed-off-by: itowlson <ivan.towlson@fermyon.com>
Copy link
Contributor

@me-diru me-diru left a comment

Choose a reason for hiding this comment

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

Thanks a lot, @itowlson, for the quick rescue against the negation madness! :D

I tested the fix with multiple components and tried to exclude files included under one component in another and it still worked.

Can we assume this PR adds the feature requested in #1692 as well? It seems to exclude files under the same component with a ! operator

@itowlson
Copy link
Contributor Author

@me-diru Once this merges we can flag it on #1692 for folks to test. The reason I am not saying "yes" is that the watchexec exclusion syntax feels a bit like we lucked into whatever watchexec does rather than designing it to meet our needs, so I would rather have the folks who want the feature to confirm that it really does work the way they want it!

@itowlson itowlson merged commit 98aa3e4 into fermyon:main Jun 13, 2024
17 checks passed
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.

3 participants