-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Merge commits break LLVM CI download #101907
Comments
Can you say more about their usefulness? What are you merging in? We can maybe support merging non-bors commits, though it brings some complexity (e.g., which parent do we follow for the "nearest" bors commit, and what does nearest mean at that point), so in general I would be inclined to say this isn't supported and you should build locally. |
I don't think it's a must-have. I'm personally fine with building locally or rebasing. But this would allow longer-running branches to use the CI artifacts without rewriting history due to rebasing. Also, the current behavior can be a little bit confusing if one is not aware of this issue. |
Yeah it is confusing. :D Could you explain what happens? |
From what I can tell, yes. The logic that determines that commit seems to not account for merge commits. But @jyn514, who helped me troublshoot this issue initially, might know the details. |
I now also ran into this because syncing Miri changes back into rustc creates merge commits. Not sure how to work around this problem; rebasing is not an option for these syncs and a local build takes forever... Cc @jyn514 |
Specifically that Miri history contains commits made by bors in Miri, which then fools the detection logic to think that was a rustc bors commit. |
Currently, bootstrap uses the following command to determine the commit to fetch LLVM for
I can see two ways of making things work even for the Miri sync situation:
|
I think the second option would be a solid solution, and it also works for the usecase I had in mind. (Side note: Though I'm sure why this uses |
On master there are tons of merge commits -- the ones created by bors. In fact the commit we are looking for is always a merge commit, so maybe we should add |
Ah yes, right, of course. The "no merge-commit policy" is only for PRs... Nevermind. |
Fetching introduces a network call on each x.py invocation, I think, since we need to know if something has changed. I guess we could try to cache based on the head sha, but I'm not generally a fan of that. I think the right answer is probably to change bors to include a repository in the commits it generates more explicitly - perhaps the email could be bors+rust@rust-lang.org, for example. Would need some care to update all of our automation, but seems achievable. |
Yeah I agree having to invoke the network is not great. In principle we could search the user's remotes for one that points to our github repo and use Having different bors email addresses for different repos would help for the Miri case, yeah. And I guess for @jachris we could replace the @Mark-Simulacrum I take it you are also not a fan of trying multiple commit candidates? I guess that would require caching negative lookups so it's also not great. A temporary hack that would be helpful is some way to overwrite the |
Updating the lockfile should be cargo metadata >/dev/null or something like that, no need for x.py. Yeah, multiple candidates I think has similar problems in terms of network hits (or negative cache of some kind). --merges seems fine to me, but I'm not sure we can do away with --first-parent - for example, in the case of rollups, we need to be sure we're looking at the first parent commit to traverse the commit graph. I guess with -n1 that might not matter but it feels iffy to me. Can you point me at the SHA/branch for the miri merges that are causing trouble? I wonder if the merge commits might be distinguishable by (for example) not having a tree associated with them that contains src/stage0.json or something like that. |
Yeah you can just check out the branch for #103392 to see the problem.
No that wouldn't help... this is Miri history reconstructed into the rust repo, it also has all of the rest of the rust repo around.
Ah, I never even tried doing anything outside of x.py in the rustc repo, it seemed hopeless. But anyway sometimes I might also have to actually build that branch. |
Yeah, I see. OK, I think the best option then is going to be the adjustment to bors to highlight which repository the merge commit is from. We'll want to check against triagebot, crater, rustc-perf, cargo-bisect-rustc, and the promote-release infrastructure which I think are the infrastructure places that have some amount of processing of rustc commit history. |
We don't need to fetch to support remotes named something other than rust/src/tools/build_helper/src/git.rs Lines 22 to 30 in 3e565f1
👍 this seems like a good solution |
This problem still regularly hits me when I synchronize Miri changes. An LLVM_FETCH_COMMIT env var hack would help a lot to bridge the gap until a proper solution emerges. EDIT: For the record, here's a hacky patch that helps: diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 3e82a381a1b..7600365d29b 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -568,6 +568,7 @@ pub(crate) fn maybe_download_ci_llvm(&self) {
let llvm_root = self.ci_llvm_root();
let llvm_stamp = llvm_root.join(".llvm-stamp");
let llvm_sha = detect_llvm_sha(&self, self.rust_info.is_managed_git_subrepository());
+ let llvm_sha = "PUT_SHA_HERE"; // output of `git merge-base HEAD origin/master` goes here
let key = format!("{}{}", llvm_sha, self.llvm_assertions);
if program_out_of_date(&llvm_stamp, &key) && !self.dry_run() {
self.download_ci_llvm(&llvm_sha); |
Reopened by #114345. I hope the perf team can help figure out what is going on; just calling |
Uh, why should I call it "upstream"? The standard name is "origin" isn't it?
|
Anyway I think the main question is whether the |
I would definitely expect it to be load bearing if there's merge commits between HEAD and the closest bors commit. (If there's not then there's no parents to choose between). I think that situation is relatively rare, but would e.g. come up with subtree syncs. You shouldn't need a particular name for the remote though, iirc we lookup a remote that has the right target (rust-lang/rust). Maybe we don't do that in all cases though... |
A Miri subtree sync is exactly where |
@RalfJung Can you say more about how you ended up with f461981 as HEAD? By the first parent history that traces to a bors commit on Tue Oct 22 08:21:37 2024 (quite old...), which makes sense in terms of why that broke things. For bors merges, we take care that the first parent of the merge commit is the previous bors merge. This property is also kept for rollup merges (e.g., 0a33d7c has a first parent of 3536503 which ends up chaining recursively to c49fc91 and finally a9e7b30 for that rollup's bors merge parent). It seems like miri is not respecting that property, sometimes the "rustc side" of the merge is most recent through the 2nd parent commit -- which is why The reason for first-parent (or something like it -- doesn't have to be first necessarily) is that the alternative (most recent commit ("reverse chronological order" by docs in rev-list) with bors@rust-lang.org as the email) could have found a clippy, miri, etc. bors merge commit as being more recent in the past, even in rust-lang/rust history, if you were syncing in merge commits from those repos (first-parent avoided that there because it refused to traverse the "sideways" history). But now that we no longer use bors anywhere except rustc, it seems plausible that just dropping It seems like you came to that conclusion earlier (#101907 (comment)) but we didn't actually follow up and improve the finding logic given that realization :) |
It was created by The reasons the merge commit looks like that is that it got created in Miri (by a GH merge), where as usual the first commit is "the previous HEAD of this repo" and the 2nd commit is "the changes of this PR". The rustc history is "changes made in the PR" when that PR is a rustc-pull (i.e. syncing rustc changes into Miri). |
Somehow the removal of Not being able to test Miri syncs locally is quite annoying so it'd be really good to finally resolve this issue. |
Yeah, it shouldn't. I am planning to have a look at that (both on git and LLVM download logics) in a couple of days. |
Note that CI does run on a merge commit (f43d771 in the case of the failed CI run). However both parents of the merge commit are recent (a46c755, the first parent, looks right to me), it is also the indirect parent of the 2nd parent (e045a02 -> a46c755). An empty rev-list result so far for me is from this12:
It's possible my local env is messed up, but if I set it up correctly, all the "known" commits are:
(because we have a shallow fetch: That said, it's not very clear to me how first-parent managed to find a commit when regular traversal doesn't. I wouldn't expect that to increase what results are available to git. Maybe the diff attributed to a commit changes depending on how that commit is reached, given the shallow history? Footnotes
|
Uh, removing --first-parent finds fewer things? Yeah that makes no sense to me.
Can we just treat "empty result" as "do not download LLVM"?
|
This would silently hide actual bugs in the commit finding logic. I just made #137994 which adds a fallback logic to |
Where does that commit come from? It says @nikic created it, but it doesn't show up in the PR itself...? Is this the commit created by github as part of CI? I didn't realize that would be attributed to the PR author, interesting.
How do you reproduce this? Did you do a shallow clone and then get that result? Locally when I run that comment on my regular clone, I get
This is the same result I also get with The main thing I am wondering about how: given that we have a shallow clone in CI, it makes no sense at all to try and determine anything about the git history. What even is our plan here, what is the intended behavior? Also, what is the intended behavior if LLVM has changed since the most recent merge commit that updates LLVM? It seems the current logic would just blatantly ignore that and use the downloaded LLVM anyway, or is there a check somewhere that I missed? |
Okay yeah I can reproduce this as well, using
The answer you get with The docs for
And indeed, using
And it seems like that option will also work for Miri sync commits:
However, I am still not convinced it makes sense to run
We are already silently hiding bugs in that logic, it seems. |
FWIW the points about shallow clones could also explain this:
with such a shallow view of what the history is, there's no way git can reliably compute the merge base. On nightly CI, So we have to either make a full clone, or stop doing any kind of git history queries in CI. (But also, on beta/stable CI, I don't think the merge base with master should even be relevant.) |
Would a partial (blobless) clone instead of a shallow clone work maybe?
|
I don't think that would help since we are filtering based on the diff of the commits, and determining the diff needs the blobs. |
Right, I was for some reason thinking that filtering was based on commit message content. |
Rollup merge of rust-lang#137593 - RalfJung:subtree-sync-download-llvm, r=Mark-Simulacrum fix download-llvm logic for subtree sync branches Fixes rust-lang#101907 Cc `@onur-ozkan` r? `@Mark-Simulacrum`
Reopening because I'm posting a revert for #137593 to fix perf. |
Revert "fix download-llvm logic for subtree sync branches rust-lang#137593" Looks like unfortunately the `--diff-merges` flag is a `git show`-only command, not `git rev-list`. See https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---first-parent which has `--first-parent`, versus https://git-scm.com/docs/git-show#Documentation/git-show.txt---diff-mergesltformatgt which has `--diff-merges=first-parent`. This reverts commit 95994f9, reversing changes made to 7290b04. This will unfortunately re-open rust-lang#101907 but that isn't fixed anyway since the git invocation is broken. r? `@onur-ozkan` (or bootstrap or infra or anyone really)
Where can I see the failing CI log that is fixed by the revert? |
Revert "fix download-llvm logic for subtree sync branches rust-lang#137593" Reverts rust-lang#137593. Looks like unfortunately the `--diff-merges=first-parent` flag is a `git show`-only flag, not `git rev-list` which only accepts `--first-parent`. See https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---first-parent which has `--first-parent`, versus https://git-scm.com/docs/git-show#Documentation/git-show.txt---diff-mergesltformatgt which has `--diff-merges=first-parent`. This reverts commit 95994f9, reversing changes made to 7290b04. This will unfortunately re-open rust-lang#101907 but that isn't fixed anyway since the git invocation is broken. cc `@RalfJung` `@Mark-Simulacrum` for FYI (but I would've written the same incorrect flag 💀) r? `@onur-ozkan` (or bootstrap or infra or anyone really)
(Asking in #t-infra > benchmarks failed?) |
While PRs are not allowed to have merge commits, they can still be useful locally (or for not rewriting history for longer-running branches).
However, they break the commit detection logic for downloading CI artifacts.
Steps to Reproduce
git checkout <old-commit>
git merge --no-ff master
./x.py build library/std
Expected Result
Builds fine.
Actual Result
The text was updated successfully, but these errors were encountered: