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

Add git pre-push hook #728

Merged
merged 17 commits into from
Feb 14, 2024
Merged

Add git pre-push hook #728

merged 17 commits into from
Feb 14, 2024

Conversation

tommy-gilligan
Copy link
Contributor

There are definitely different approaches that can be taken to sharing git hooks (some projects install git hooks automatically). Here I've gone with something simple: just have a directory githooks that the developer/user is expected to point their git at by manually changing core.hooksPath.

Documenting installation is necessary but I've not yet done it. Didn't want to go too far down the path I've chosen before getting feedback.

I also haven't yet done anything much to deal with stdout/stderr noise.

@joshlf
Copy link
Member

joshlf commented Dec 22, 2023

Hey @tommy-gilligan, thanks for this! Just wanted to let you know that, between other work and time off for the holidays, we likely won't get a chance to review this for at least a few weeks, but we haven't forgotten about it. We'll follow up once everyone's back at work and we've cleared out our backlog.

@tommy-gilligan
Copy link
Contributor Author

Thank you for updating me on this. You didn't have to do that and it is very kind of you!
Look forward to hearing more here in the new year. In the meantime, I hope you have a wonderful break!

@joshlf
Copy link
Member

joshlf commented Feb 11, 2024

Okay, had a chance to look at this. Unfortunately you'll need to rebase changes that have happened in the interim. This looks great, though! My one concern would be how long it takes all of these scripts to execute locally; I assume it's not too much time, but it's also doing enough parsing and shell script work that it wouldn't surprise me if it was at least a noticeable increase. git push is a very frequent part of our workflow, so I'd be worried about even small slowdowns. If you could time the execution of the git hook and let me know what you get, that'd be great. If you could time each individual step so we know what's taking more time, that'd be even better.

Thanks again for doing this! In the long run, I think this will save us a lot of needless headache with extra CI round trips.

@tommy-gilligan
Copy link
Contributor Author

globstar

Apple switched to Zsh some years back and only an old version of Bash is kept for compatibility. This version of Bash does not support globstar. The scripts could be converted to Zsh but I think Bash is still mostly what is used on Linux out of the box, so I don't think that's a good idea.

This is why I've replaced globstar with find in ci/check_fmt.sh.

Timing

A temporary change to githooks/pre-push to get timing information

#!/usr/bin/env bash
set -veo pipefail
time ./ci/check_fmt.sh
time ./ci/check_job_dependencies.sh
time ./ci/check_msrv.sh
time ./ci/check_readme.sh
time ./ci/check_versions.sh

Having already made some changes to ci/check_fmt.sh and because it is the slowest part of githook/pre-push, I decided to improve it slightly.

Relying on find isn't so bad, I measured how long it takes to run and it is insignificant compared to rustfmt. Also, using find in this way maybe protects against eg. forgetting to add new directories to the script in the future (just build files in target are excluded).

Before check_fmt improvement

% time githooks/pre-push 
time ./ci/check_fmt.sh

real	0m0.532s
user	0m0.426s
sys	0m0.074s
time ./ci/check_job_dependencies.sh

real	0m0.032s
user	0m0.021s
sys	0m0.023s
time ./ci/check_msrv.sh
Same MSRV (1.56.0) found for zerocopy and zerocopy-derive.

real	0m0.099s
user	0m0.089s
sys	0m0.022s
time ./ci/check_readme.sh
     Ignored package `cargo-readme v3.2.0` is already installed, use --force to override

real	0m0.086s
user	0m0.054s
sys	0m0.022s
time ./ci/check_versions.sh
Same crate version (0.8.0-alpha.4) found for zerocopy and zerocopy-derive.
zerocopy depends upon same version of zerocopy-derive in-tree (=0.8.0-alpha.4).
In dev mode, zerocopy depends upon same version of zerocopy-derive in-tree (=0.8.0-alpha.4).
Same crate version (=0.8.0-alpha.4) found for optional and targeted zerocopy-derive dependency.

real	0m0.221s
user	0m0.223s
sys	0m0.049s
githooks/pre-push  0.81s user 0.19s system 96% cpu 1.042 total

After check_fmt improvement

% time githooks/pre-push 
time ./ci/check_fmt.sh

real	0m0.271s
user	0m0.194s
sys	0m0.065s
time ./ci/check_job_dependencies.sh

real	0m0.038s
user	0m0.021s
sys	0m0.025s
time ./ci/check_msrv.sh
Same MSRV (1.56.0) found for zerocopy and zerocopy-derive.

real	0m0.093s
user	0m0.091s
sys	0m0.021s
time ./ci/check_readme.sh
     Ignored package `cargo-readme v3.2.0` is already installed, use --force to override

real	0m0.091s
user	0m0.056s
sys	0m0.023s
time ./ci/check_versions.sh
Same crate version (0.8.0-alpha.4) found for zerocopy and zerocopy-derive.
zerocopy depends upon same version of zerocopy-derive in-tree (=0.8.0-alpha.4).
In dev mode, zerocopy depends upon same version of zerocopy-derive in-tree (=0.8.0-alpha.4).
Same crate version (=0.8.0-alpha.4) found for optional and targeted zerocopy-derive dependency.

real	0m0.229s
user	0m0.225s
sys	0m0.051s
githooks/pre-push  0.59s user 0.19s system 106% cpu 0.735 total

Remaining

  • The githook maybe adds a bit of noise to STDOUT/STDERR when running git from a terminal. Please let me know if anything should be done about this.
  • Document using the githook
  • I believe it shouldn't be too hard to improve running time further, I might like to take a stab at this before merging.

Copy link
Member

@joshlf joshlf left a comment

Choose a reason for hiding this comment

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

Amazing, thank you so much for your work on this!

The timings look totally acceptable to me - sub-one-second latency addition for git push shouldn't be a problem, especially given the benefit. You're more than welcome to work on optimizing, but maybe let's do that in a separate PR? That way we can isolate those changes in case it breaks anything.

The githook maybe adds a bit of noise to STDOUT/STDERR when running git from a terminal. Please let me know if anything should be done about this.

I'd recommend, in the pre-push script, just piping the stdout of each subcommand to /dev/null. We're good about printing errors to stderr, so this shouldn't swallow any.

CONTRIBUTING.md Outdated Show resolved Hide resolved
@tommy-gilligan
Copy link
Contributor Author

You're more than welcome to work on optimizing, but maybe let's do that in a separate PR?

Good idea!

I'd recommend, in the pre-push script, just piping the stdout of each subcommand to /dev/null. We're good about printing errors to stderr, so this shouldn't swallow any.

I've ended up with everything but the formatting script redirecting to /dev/null. rustfmt --check uses stdout for displaying a diff that highlights files that need to be formatted and this will be useful for the user to see.
Along the way I added -q to a cargo install, I think it makes sense to keep that.

Additionally, I found a small programming error in check_versions.sh. Because it was small, I went ahead and fixed it here.

Copy link
Member

@joshlf joshlf left a comment

Choose a reason for hiding this comment

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

I'd recommend, in the pre-push script, just piping the stdout of each subcommand to /dev/null. We're good about printing errors to stderr, so this shouldn't swallow any.

I've ended up with everything but the formatting script redirecting to /dev/null. rustfmt --check uses stdout for displaying a diff that highlights files that need to be formatted and this will be useful for the user to see. Along the way I added -q to a cargo install, I think it makes sense to keep that.

Sounds good!

Additionally, I found a small programming error in check_versions.sh. Because it was small, I went ahead and fixed it here.

Oh, what was the error?

githooks/pre-push Show resolved Hide resolved
@tommy-gilligan
Copy link
Contributor Author

Oh, what was the error?

Sorry I should have explained: $VER_A/$1 $VER_B/$2 were not being used in assert-match. There is similar code in a different file, it was probably just code not being updated after being copy/pasted. a8539dc I can revert this if it is too out of scope for this PR.

Copy link
Member

@joshlf joshlf left a comment

Choose a reason for hiding this comment

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

Oh gotcha, thanks for fixing that! Maybe we need tests for our tests...

Anyway, this looks great. Thanks for all your work on this!

@jswrenn jswrenn added this pull request to the merge queue Feb 14, 2024
Merged via the queue into google:main with commit bbc228a Feb 14, 2024
209 checks passed
dorryspears pushed a commit to dorryspears/zerocopy that referenced this pull request Feb 20, 2024
* [ci] Extract scripts in YAML to individual ci/*.sh

* [ci] Rename check_job_dependencies for consistency

* [ci] Run some checks on pre-push

* [ci] check for yq before trying to run it

* [ci] replace globstar for better compatibility

* [ci] streamline check_fmt for performance

* [ci] Use /usr/bin/env for improved compatibility

* [ci] check that there are files for formatting

* [ci] set check_all_toolchains_tested executable

* [ci] make githook quieter (errors still show)

* [ci] help user to know they are using pre-push hook

* [ci] add documentation for git hook config

* [ci] use function args instead of globals in check_versions.sh

* [ci] fix formatting in git hooks documentation

* [ci] direct all ci script stdout to null in git hook

* [ci] make sure rustfmt stdout gets printed

* [ci] explain why check_fmt.sh is not silenced
joshlf added a commit that referenced this pull request May 18, 2024
Previously, some scripts had output which would only be generated on
failure, but this output was passed to stdout, which `githooks/pre-push`
pipes to `/dev/null`. In this commit, any such output is unconditionally
redirected to `stderr` - if there's any output, we want to see it. This
previously resulted in very opaque errors during `git push`, which
should be addressed by this commit.

Also, in #728, we added `ci/check_all_toolchains_tested.sh`, but didn't
add it to `githooks/pre-push`. In this commit, we fix that, and also add
a test to `githooks/pre-push` to validate that all scripts in `ci/*` at
least show up in `githooks/pre-push` by name. This isn't a foolproof
check, but it should catch obvious errors.
github-merge-queue bot pushed a commit that referenced this pull request May 18, 2024
Previously, some scripts had output which would only be generated on
failure, but this output was passed to stdout, which `githooks/pre-push`
pipes to `/dev/null`. In this commit, any such output is unconditionally
redirected to `stderr` - if there's any output, we want to see it. This
previously resulted in very opaque errors during `git push`, which
should be addressed by this commit.

Also, in #728, we added `ci/check_all_toolchains_tested.sh`, but didn't
add it to `githooks/pre-push`. In this commit, we fix that, and also add
a test to `githooks/pre-push` to validate that all scripts in `ci/*` at
least show up in `githooks/pre-push` by name. This isn't a foolproof
check, but it should catch obvious errors.
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.

None yet

3 participants