Conversation
afbc8fb to
4b86fd6
Compare
4457fa3 to
a533711
Compare
f40e237 to
088e5b3
Compare
|
I may add some individual comments but this is my overall stance after viewing this:
|
The goal isn't to remove complexity or avoid the YAML. If a tool does its job its OK to look ugly (like nix). But I think there are a few benefits to using a special purpose task runner which can be weighed against the cost of the introduced indirection.
Just is a nice interface, but doesn't have to be the task runner. I was also looking into cargo aliases which are cool cause no new dependency. But they are also defined in a file under a hidden directory and don't offer great cross platform support if you try to run more than a single cargo command. Looks like they defer to shell calls or recommend writing little rust programs which is interesting, but feels a little much for now.
Not sure I agree on keeping comments to a minimum, although they can be a sign things are getting too complicated? Guess I am just not offended by over documentation. It does require upkeep, but doesn't usually actively hurt and can always be easily deleted. Stuff doesn't build on top of documentation like it does with code. And for build stuff in particular, lots of times even small declarative changes have a bunch of subtle effects which are helpful to document. For the clippy comments, I usually like to document why I am turning off something. Kinda justifying the short cut. It might help in the future if the filter-control feature is refactored to remind us to remove the short cuts instead of just unintentionally living on leaving an opening for leaks.
I don't think I have made the lockfile stuff clear, so dropping some high level thoughts. The lockfile for a library doesn't matter to the consumers since they will generate their own dependency set. But they do care about the dependency constraints of a library since they will have to deal with them to generate that lockfile. So the goal of a library is to gain confidence that its dependency constraints are as flexible as possible (easy for consumers) while capturing the requirements of the code. The worst case scenario is the constraints are too strict and actually impossible to satisfy. An example would be a low MSRV paired with high versions for some dependencies. Its impossible to satisfy a 1.63.0 MSRV and a recent version tokio. The v2 resolver doesn't detect this, but the v3 resolver fails, so at least lets the maintainers know. Generating a lockfile is proof for the maintainers that the constraints work. Maintainers could generate lockfiles for every possible combination of dependency versions for the highest level of confidence the constraints are good, but that might actually take forever. I think the best middle ground is generating an MSRV compliant version set as a bare minimum, and then some sort of minimum set and max set to make sure the extremes work. There is still potential for some version set in the middle to cause issues, but feels like a lower chance without that high of a cost. I think generating an MSRV lockfile is very useful check to just ensure dependency constraints are possible. But maybe just that generation should be added to the CI pipe and less care given to whatever lockfile happens to be checked in? The
Prefixing is just a form of namespacing, but I don't have a strong opinion between them and instead taking an argument. Conditionals in just are a little weird, but maybe there is a smoother pattern to dispatch an arg to a certain command. |
a3dd967 to
eec6517
Compare
Cargo.toml
Outdated
| path = "example/managed.rs" | ||
| required-features = ["filter-control"] | ||
|
|
||
| [lints.rust] |
There was a problem hiding this comment.
There are some cases where intermediate commits might have lints, but with the intention of them being removed in a later commit. For instance making a new struct and unit testing it will result in lints because it isn't used yet, but I would consider that a good software practice
There was a problem hiding this comment.
Do you think this is just too strict a setting? I flipped it on because there was only like 2 warnings and easy to fix. I think its one of those things that would be easier to enforce now, cause I've accepted that anything not tested in CI slips through. But don't have a super strong take on this setting.
rust-bitcoin has a policy that every commit needs to pass CI. While strict, I appreciate the consistent bar for commits on master. Obviously depends on the merge strategy though since squash would make the effort worthless.
There was a problem hiding this comment.
For the purpose of this library I think it is pretty strict. By exporting a type as public, there is no lint incurred even if you don't "use" the method. For rust-bitcoin most type are public. In this crate, like with the BlockTree example, some abstractions can and should be completely internal. Getting lints on something that isn't used would lead us to try to build a type and integrate in one commit, which seems bad to me.
There was a problem hiding this comment.
I'll roll it back since I am not totally sold on it myself, could definitely cause pain. I think the ideal might be to enable it and then poke holes for certain rules that are the most annoying, but can think on that later.
FWIW I am not sure your use case is the most compelling though. I think it is another sign that there are some downsides to pub(crate) and it might be worth using the more traditional "private module with pub items" pattern in some scenarios.
There was a problem hiding this comment.
heh, I rolled back the lint-warn-to-error and associated fixes, only to have CI fail on them. Turns out, the fancy new rust action enables that flag by default: https://github.com/actions-rust-lang/setup-rust-toolchain?tab=readme-ov-file#rustflags
Can disable it on the action for now, but may take a quick look at more granular controls.
There was a problem hiding this comment.
OK, instead of reverting the default on all instances of the github action, took it as a sign to "roll forward" and keep the setting in the manifest, that way local and CI have the same settings.
There are only 2 errors I iron'd out for now, both due to code being available (or not) with the filter-control features. Feels like something to clean up later.
There was a problem hiding this comment.
AFICT the solution you described would still cause the lint. If it is public via pub to the module or pub(crate) to the entire crate I think the linter would still complain there is no user of the method. It feels like a massive pain in the ass to try to develop a new feature and still pass clippy. I don't necessarily understand the reasoning that local and CI has to be the same on this policy. To get into master, sure - deny lints, but intermediate commits in development?
There was a problem hiding this comment.
I had a bad assumption about the visibility modifiers and thought pub was always considered possibly external facing by the linter, so never dead. Turns out it's smarter than that though, just ran this test.
pub mod exposed {
mod hidden {
pub fn public_in_private() {} // Will be flagged as dead
}
pub mod visible {
pub fn truly_public() {} // Won't be flagged as dead
}
}
As far as local and CI, tbh I've always worked under the assumption that life is easier when those match. Didn't consider it a feature to have flexible settings between them. My local workflow isn't harmed by the setting so figured take the bonus and match CI, but i'll drop it since it hurts.
|
Small conflict in |
e07d745 to
2e82030
Compare
|
Dang, there is a cool new feature for giving structure to lint disable reasons, but it isn't available for our msrv. Will keep it in mind though for the future. Looks like it was stabilized in rust |
rust-toolchain.toml
Outdated
There was a problem hiding this comment.
Back to this one. If there is the change proposed in .cargo/config.toml and resolver=3 is removed, do we really care what toolchain people develop on?
There was a problem hiding this comment.
It might be helpful to avoid certain "broken on my machines" issues, but also could cause confusion that this is a requirement. I'll drop it.
Keep build and test logic as agnostic as possible to whatever CI task runner is used (today that is Github Actions). Let the CI job focus on performance, like caching artifacts and keep the build and test logic in the forefront easy for developers to use. With that goal in mind, the CI job has been refactored to a handful of jobs which each call a `just` recipe. Consistent caching has been added to each job which shows a nice improvement in speed for the workflow, running in less than a minute. The justfile has been refactored with the logic that previously lived in the CI yaml. This makes it easier to maintain as well as run locally when developing. A few un-used recipes have been cleaned up. Lockfile complexity has been relegated to the _test-msrv recipe. This recipe checks that there is at least one set of dependencies which satisfy the msrv requirements. The check no longer depends on the checked in lockfile which doesn't matter much since consumers create their own. A rust-toolchain.toml file was added as a gently nudge for contributers to stay on a recent version of "stable", that way we can use some of the newer features like the v3 resolver and see less of "works on my machine". CI will most likely not use the file however, since it usually needs to test more complex things like MSRV.
|
ACK 3e5feb7 |
Some more deets in the commit message, but quick hits.
testrecipe is exposed with an arg to run a specific suite._test-msrvrecipe. The check no longer depends on a checked in lockfile which technically doesn't matter much since consumers create their own.Nice clean interface for contributors: