-
Notifications
You must be signed in to change notification settings - Fork 41
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
ping/rust: Refactor into multiple binaries #72
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the direction this is taking. Thanks @thomaseizinger!
I will take a more in-depth look.
Mentioning it here to not forget, this pull request also needs to update the root README.md
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good to me. Before we merge, @thomaseizinger can you confirm that this fixes libp2p/rust-libp2p#2972?
I'll have to check that locally! |
I had to make several changes to make all the usecases work but I've verified it locally now and it all works. I made some more changes to the Dockerfile that should hopefully make it more maintainable. Pretty much all the configuration is in When we release a new version, we only need to append an entry to |
We should also get much better build-performance out of the new Dockerfile, assuming testground has enough space to cache our docker layers (spoiler: they are massive, ~ 20GB). All released versions should always be pre-build and not require and changes. |
I don't understand why the build is failing: https://github.com/libp2p/test-plans/actions/runs/3468917140/jobs/5795285685#step:6:326 For some reason, testground is building an old Dockerfile. |
ping/rust/Dockerfile
Outdated
|
||
RUN mv /tmp/Cargo.toml /tmp/Cargo.lock ./plan | ||
ARG GIT_TARGET="" | ||
RUN if [ ! -z "${GIT_TARGET}" ]; then export ESCAPED_GIT_TARGET="$(printf '%s' "${GIT_TARGET}" | sed -e 's/[\/]/\\&/g')"; sed -i "s/^git.*/git = \"https:\/\/${ESCAPED_GIT_TARGET}\"/" ./plan/Cargo.toml; fi # URLs contain forward slashes that need to be escaped for `sed` to work correctly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an aside, you can use a different delimiter than /
with sed
, e.g. #
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My god, knowing this would have saved me quite some time 😂
I'll try to simplify that then.
Just a thought: Is the environment variable properly expanded, or accidentally used in plaintext?
|
It was when I tested it locally! |
Oh my god it is finally working! 🎉 |
It seems that the initial docker layers are not cached between CI runs: https://github.com/libp2p/test-plans/actions/runs/3484164725/jobs/5828413991#step:6:46 I think that was the case before as well though, so this doesn't make things worse I think. |
@@ -4,43 +4,23 @@ WORKDIR /usr/src/testplan | |||
RUN apt-get update && apt-get install -y cmake protobuf-compiler |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@laurentsenta tagging you here for visibility, given that you have worked on the caching optimizations below.
With this pull request cargo build
is the same across rust-libp2p versions (apart from master
and a specific git commit hash), i.e. it builds all rust-libp2p versions and can thus be reused when testing different rust-libp2p versions. This results in the below simplifications.
Let us know in case you have any objections.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mxinden thanks for the heads up; no objection on my side, but a question and a comment:
(q) it seems like we "just" moved the version indirection from feature flags to one layer up, but no big change in the Cargo.toml
:
So we replace cargo build --features="${VERSION_ID}"
with cargo build --bin=${VERSION_ID}
That might be something that comes up again, how is this improving how we track dependencies in the Cargo.lock
?
(c) We're dropping dependency caching, i.e. "do not download and rebuild all my dependencies when I change one line in my main.rs".
I added this to make the experience of iterating on the test code more bearable. We might want to add back that feature eventually (through dummy mains, cargo-chef
, or something else).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mxinden thanks for the heads up; no objection on my side, but a question and a comment:
(q) it seems like we "just" moved the version indirection from feature flags to one layer up, but no big change in the
Cargo.toml
:So we replace
cargo build --features="${VERSION_ID}"
withcargo build --bin=${VERSION_ID}
That might be something that comes up again, how is this improving how we track dependencies in the
Cargo.lock
?
I think in practice, it doesn't make much a difference whether we use features or not. What is important is splitting the binaries per version to allow fine granular control over the code per version. As long as we track this out of tree of rust-libp2p, I think this will be necessary.
With split binaries, it doesn't make much sense to have optional features any more because they don't conflict anyway.
(c) We're dropping dependency caching, i.e. "do not download and rebuild all my dependencies when I change one line in my main.rs".
I added this to make the experience of iterating on the test code more bearable. We might want to add back that feature eventually (through dummy mains,
cargo-chef
, or something else).
Yeah I've been there. I am okay with it being added back. I stripped it to simplify things as much as possible during debugging.
If somehow possible, I'd like to avoid containers for local iteration. Can testground run local binaries too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it; thanks for the clarification,
If somehow possible, I'd like to avoid containers for local iteration. Can testground run local binaries too?
Yes, it doesn't do network isolation and simulation, so you might not be able to use this as the main workflow to develop & fix tests.
What is important is splitting the binaries per version to allow fine granular control over the code per version.
One last comment on this, if that's the point of this PR, is it possible we're trading "simple" for "easy" and we'll pay in the long term?
We're replacing "I have one main, with many shims for backward compatibility" with "I have many mains re-implementing a shared API".
The go version has been around for longer, so we have more examples of this:
- One shared main
- Shim some parts of the library (build flags in the header are ~= rust feature flags)
Note how surgical we can be when we support new versions, upgrading from v0.20 to v0.21 is "just" adding a flag because there was no API-breaking change.
With the new approach, it seems like we have 7 main files, ~600 lines, and only ~40 lines that are different, LOC is not a perfect metric, but it seems to indicate we're trading O(log(versions)) code complexity for O(versions).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last comment on this, if that's the point of this PR, is it possible we're trading "simple" for "easy" and we'll pay in the long term?
I see your point. Though unfortunately I don't see how we can support future breaking changes in rust-libp2p with the current "simple" approach. In other words, I don't see an alternative to the "easy" approach going forward.
All that said, I think it is relatively easy to iterate on this part of the code base. In case we come up with a better design, let's refactor ping/rust
.
(c) We're dropping dependency caching, i.e. "do not download and rebuild all my dependencies when I change one line in my main.rs".
I added this to make the experience of iterating on the test code more bearable. We might want to add back that feature eventually (through dummy mains,cargo-chef
, or something else).Yeah I've been there. I am okay with it being added back. I stripped it to simplify things as much as possible during debugging.
@thomaseizinger would you mind adding it back in? I suggest not blocking this pull request, but instead do so in a follow-up pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the new approach, it seems like we have 7 main files, ~600 lines, and only ~40 lines that are different, LOC is not a perfect metric, but it seems to indicate we're trading O(log(versions)) code complexity for O(versions).
What I'd like to mention here is that from my PoV, all old versions shouldn't really need maintaining so it is code that just sits there but doesn't have to be touched.
I know it looks scary but honestly, the only problem I can see is breaking changes in the Rust client of testground. Nothing else should warrant touching those old test binaries and even that we could work around by depending on the library multiple times, same as we do for libp2p itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I've been there. I am okay with it being added back. I stripped it to simplify things as much as possible during debugging.
@thomaseizinger would you mind adding it back in? I suggest not blocking this pull request, but instead do so in a follow-up pull request.
I'll have a look. Right now, I am just happy to be unblocked on my PR :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM Thomas 💪
|
||
[[groups]] | ||
Id = "v0.47.0" | ||
CargoFeatures = 'libp2pv0470' | ||
BinaryName = 'testplan_0470' | ||
|
||
[[groups]] | ||
Id = "v0.46.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should here also be the 46.1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, this is take verbatim from current master.
|
||
[[groups]] | ||
Id = "v0.45.1" | ||
CargoFeatures = 'libp2pv0450' | ||
BinaryName = 'testplan_0450' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BinaryName = 'testplan_0450' | |
BinaryName = 'testplan_0451' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you send a follow-up if you care much? :)
I'd prefer to merge this asap to unblock libp2p/rust-libp2p#2972.
development_transport(local_key).await?, | ||
ping::Behaviour::new( | ||
#[allow(deprecated)] | ||
// TODO: Fixing this deprecation requires https://github.com/libp2p/rust-libp2p/pull/3055. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we are not using the derive
macro here, do we need #[allow(deprecated)]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is still a deprecated function!
If I am not missing anything, we seem to have consensus that this is a step forward. Thanks for the work here @thomaseizinger. Thanks for the input @laurentsenta and @jxs. Follow-ups to this pull request:
|
Any sed experts here? Something doesn't seem to quite work: https://github.com/libp2p/rust-libp2p/actions/runs/3499746591/jobs/5861640925 |
By having one Rust binary per version, we can vary the actual binary from version to version and f.e. fix deprecated API calls. It does introduce a bit of duplication between the different versions but I'd rather have that then not being able to adapt the tests to new APIs.
Instead of activating a feature per libp2p version, we add them all as dependencies. This ensures all transitive dependencies are properly tracked in
Cargo.lock
. Additionally, this gives us a single place we are can activate all the feature.For
master
and pull-request builds, we replace the git target or rev with the one coming from the CI build. Once we trigger a build,cargo
will update and resolve the necessary dependencies before that, thus fixing problems such as libp2p/rust-libp2p#2972.Fixes #71.