-
Notifications
You must be signed in to change notification settings - Fork 37.7k
ci: run in worktrees #31787
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
ci: run in worktrees #31787
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31787. ReviewsSee the guideline for information on the review process. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
--mount "${CI_DEPENDS_SOURCES_MOUNT}" | ||
--mount "${CI_PREVIOUS_RELEASES_MOUNT}" | ||
) | ||
# Add worktree root mount, if needed |
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.
Why is any .git
data needed to be copied, when an init .git
is sufficient?
It would be easier to just call git init
?
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.
Hmmm, this was actually my first approach in the lint script, as it was simpler. Once I got this working in the Ci script, I backported a "matching" version to the linter script.
Looking at:
bitcoin/ci/test/01_base_install.sh
Lines 11 to 16 in 1172bc4
CFG_DONE="ci.base-install-done" # Use a global git setting to remember whether this script ran to avoid running it twice | |
if [ "$(git config --global ${CFG_DONE})" == "true" ]; then | |
echo "Skip base install" | |
exit 0 | |
fi |
...I mistakenly thought that .git
was actually needed, but i) it's mounted RO, and ii) it's only used as above here as far as I can see in the whole CI.
Can we just touch a (any) file to persist the flag then, and drop all .git
requirement?
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 mistakenly thought that
.git
was actually needed, but i) it's mounted RO, and ii) it's only used as above here as far as I can see in the whole CI.
It is also used in tidy via git --no-pager diff
.
Can we just touch a (any) file to persist the flag then, and drop all
.git
requirement?
Yes, but I don't know how to do that in a one-liner cross-platform (linux+mac), taking into account the different root trees and permissions. So just using git seems simplest?
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.
Is the (possible) running of 01_base_install.sh more than once deliberate? If so, then I'm curious why we ever do that? Is it just for the DANGER_RUN_CI_ON_HOST
path or is there another use?
If not then it seems like we could just mark install as done when building the image, something like this...
It is also used in tidy via git --no-pager diff.
Does this not mean that it requires the actual .git directory to be mounted for the refs, meaning git init
wouldn't work in that case?
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.
Is the (possible) running of 01_base_install.sh more than once deliberate? If so, then I'm curious why we ever do that? Is it just for the
DANGER_RUN_CI_ON_HOST
path or is there another use?
It should only install once (otherwise there will be issues). Yes, it is for DANGER_RUN_CI_ON_HOST
.
If not then it seems like we could just mark install as done when building the image, something like this...
lgtm. Could rename the file to /ci_base_install_done
to include the ci prefix?
Does this not mean that it requires the actual .git directory to be mounted for the refs, meaning
git init
wouldn't work in that case?
Just for printing the diff, as long as the repo commits to the same tree (or even the staging index is the same), it should work. I see why you opted for copying .git
, as it is a bit more future-proof and less confusing, given that the commit id also ends up in the binary or may otherwise be printed in the ci script? No strong opinion on how to fix it, though.
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 don't think the file touch method will work for the same reasons we discussed above (needing the actual .git dir with all its objects and refs for tidy), so have not opted to go for that currently.
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.
On a second though, I guess if someone wanted to run the CI on an extracted tarball of the repo (git-archive), it would be better to also support that. Not sure if it is as trivial as git init && git add ./
, so no strong opinion.
test/lint/run_lint.sh
Outdated
|
||
if [[ -n "$WORKTREE_ROOT" ]]; then | ||
# If in a worktree, mount both the current directory and the git root | ||
DOCKER_ARGS+=(--mount "type=bind,src=$WORKTREE_ROOT,dst=$WORKTREE_ROOT,readonly") |
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.
Would be good to explain why this is needed (with an example error log) and why this is the correct fix. My preference would be to fix it in the lint test_runner itself, so that everyone benefits from the fix, not just people running this ci bash script in a workdir.
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 far as I can tell, running bash -c '( cd ./test/lint/test_runner/ && cargo fmt && cargo clippy && RUST_BACKTRACE=1 cargo run )'
in a worktree already works fine for me, because the .git directory (referenced by the .git
file that a worktree creates) is available to me, unlike in the containerised scenario where this path must be explicitly mounted into the container at runtime, which is what the helper script does.
I added some more comments to describe why the mount is needed in the script itself.
Apologies if I've misunderstood what you mean here.
187ee84
to
95207aa
Compare
Run CI in worktrees by mounting the .git root target into the container.
95207aa
to
1a67538
Compare
test/lint/run_lint.sh
Outdated
DOCKER_ARGS+=(--mount "type=bind,src=$WORKTREE_ROOT,dst=$WORKTREE_ROOT") | ||
fi | ||
|
||
RUST_BACKTRACE=full docker run "${DOCKER_ARGS[@]}" bitcoin-linter |
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.
RUST_BACKTRACE=full docker run "${DOCKER_ARGS[@]}" bitcoin-linter | |
docker run "${DOCKER_ARGS[@]}" bitcoin-linter |
I don't think this env var will affect anything?
Also, style-wise I wonder if the contents of this file should be put into ci/lint_run_all.sh
, so that there is only one bash script, instead of multiple.
Ideally there would only be one script, used by ci and locally, but that can be a follow-up. For now, just a single large if in ci/lint_run_all.sh
should be fine to switch between the cirrus_ci code paths ( current content of ci/lint_run_all.sh
) and a local run (current content of this file).
Run linter in worktrees by mounting the .git root target into the container. Rename `get_git_root` to `get_git_toplevel` to avoid confusion around what this variable represents when modifying the code in the future.
1a67538
to
cc67e45
Compare
Is this still meant to be a draft? |
For reference, I can't review this, because I don't know if all the bash refactors/behavior changes here are correct and best practise, or if they could fail (and when) on error or on ancient versions of bash used in macOS. |
🐙 This pull request conflicts with the target branch and needs rebase. |
@maflcko thinking more on this after the merge of #31948 my opinion is that we should close this PR, the associated issue (#30028), and, if any action should be take it would be to document that linting in a worktree is possible by running the linter outside of a container? e.g.: # install required python dependencies
bash -c '( cd ./test/lint/test_runner/ && cargo fmt && cargo clippy && RUST_BACKTRACE=1 cargo run )' This change feels like it adds a lot of complexity, for little benefit (and I can't think of a simpler way to achieve the functionality desired). What do you think? |
For the lint task, the docker wrapper is nice, because it takes care of installing all the exact versions: Lines 49 to 65 in e568c1d
However, given the limited feedback, I wonder if anyone cares about running the linters in a worktree. For the "real" CI tasks, at least on person complained on IRC IIRC, so at least there seems to be some demand. |
⌛ There hasn't been much activity lately and the patch still needs rebase. What is the status here?
|
Closing due to lack of interest. |
Looks like this was closed, so I opened a trivial line-neutral +4-4 fix in #32767 (Missing lint and tidy support, but this can be done in a follow-up, if needed) |
Fixes: #30028
AFAIK mounting the git root should not present any additional security issues, as this would already be mounted (in RO mode) when not using a worktree.