Currently, if a pull request has more than one commit, previous commits may fail to compile, or may fail the tests. This is problematic, because it breaks git-bisect, or worse.
Fix this by adding a CI task for this.
Currently, if a pull request has more than one commit, previous commits may fail to compile, or may fail the tests. This is problematic, because it breaks git-bisect, or worse.
Fix this by adding a CI task for this.
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--021abf342d371248e50ceaed478a90ca-->
See the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.
Will squash if there is conceptual agreement (Not sure when this concept last came up, but I think @dergoegge and @achow101 mentioned it?). Review question: Looks like the worst-case runtime is 1 hour per commit, so with GHA at most 6 commits could be tested before a timeout. Maybe a self-hosted worker with a longer timeout would be better?
Concept ACK
Maybe a self-hosted worker with a longer timeout would be better?
Probably but I am wondering a bit if these task could end up clogging our self-hosted worker queue and hinder other jobs from running in their regular time?
Probably but I am wondering a bit if these task could end up clogging our self-hosted worker queue and hinder other jobs from running in their regular time?
Right, that is another reason for self-hosted runners, because it is possible to assign a label to them, so that they are task-specific, and not interfere with other tasks. On GHA "free" runners will stop being spun up after n total parallel running tasks.
This would be a cirrus self-hosted worker though, right?
Concept ACK if our CI infra can handle it. I build and run the unit tests on each commit for more critical pulls, or pulls with commits that aren't clearly separate or that look interactive, or those with many commits, but often without also running the functional tests that take longer to run. Having the CI verify this would alert PR authors more quickly and save developer time for everyone.
often without also running the functional tests that take longer to run
That said, what my build+test checks most often find is a failing build before running any tests. So if infra resources are limited, just build (or build + units) might still catch most of the issues.
I think it is fine to use GHA for now, with a limit of 6 commits. This should cover 99% of all pull requests. If there is a need for a self-hosted runner, it can trivially be added later.
Concept ACK.
Currently, if a pull request has more than one commit, previous commits may fail to compile, or may fail the tests. This is problematic, because it breaks git-bisect, or worse.
I've encountered such cases during my reviews.
On GHA "free" runners will stop being spun up after n total parallel running tasks.
Sure, but as I said, we can use self-hosted runners if and when there is a need. This check will take a few seconds on pulls with one commit (I can reduce this, if needed), which should be the most common type of pull request. Also, there is a limit of 6 hours, so this should be fine as well, unless many pull requests with many commits are pushed to at the same time, in which case there likely is a backlog either way.
35 | + with: 36 | + ref: ${{ github.event.pull_request.head.sha }} 37 | + fetch-depth: '8' # Two more than $MAX_COUNT 38 | + - run: git checkout HEAD~ # Skip the top commit, because it is already checked by the other tasks. 39 | + - run: sudo apt install ccache build-essential libtool autotools-dev automake pkg-config bsdmainutils python3-zmq libevent-dev libboost-dev libsqlite3-dev libdb++-dev systemtap-sdt-dev libminiupnpc-dev libnatpmp-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools qtwayland5 libqrencode-dev -y 40 | + - run: EDITOR=true git rebase --interactive --exec "./autogen.sh && CC=clang CXX=clang++ ./configure && make clean && make -j $(nproc) check && ./test/functional/test_runner.py -j $(( $(nproc) * 2 ))" "$( git log '^'$( git log --merges -1 --format='%H' ) HEAD --format='%H' ${MAX_COUNT} | tail -1 )~1"
Out of curiosity, why clang? To catch -Wthread-safety?
It is jammy clang.
It doesn't catch compile warnings, I think. Only compile errors.
Right, it is configured without --enable-werror.
Why did you choose clang over gcc then?
Why did you chose clang over gcc then?
Clang is generally faster and uses less memory
Approach ACK fac02205ff59467dd061429e469d4fd07fcc5ed5.
What is the way to figure out which commit failed?
What is the way to figure out which commit failed?
Compile each commit locally, I guess? See the existing docs on how to do that.
What is the way to figure out which commit failed?
Compile each commit locally, I guess? See the existing docs on how to do that.
Yes, it is what is expected from a developer in first place before they push their branch.
But if we add a CI task that tests every commit, it is reasonable, at least for me, to expect it prints a commit hash being tested somewhere.
ACK faed0f4ed43e9416eb0620db1943c9ae083a5b50
utACK faed0f4ed43e9416eb0620db1943c9ae083a5b50
Small fixup to remove the unused/disabled --interactive flag. Should be trivial to re-ACK.
utACK fa5356cd49facf195447f0f5921dce1fa53cb25d
29 | + if: github.event_name == 'pull_request' 30 | + timeout-minutes: 360 # Use maximum time, see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes. Assuming a worst case time of 1 hour per commit, this leads to a --max-count=6 below. 31 | + env: 32 | + MAX_COUNT: '--max-count=6' 33 | + steps: 34 | + - uses: actions/checkout@v3
Yes, can be done on the next force push or in the other pull.
Ah sorry, I forgot it was already merged.
I don't think v3 or v4 are any different, so I'll follow-up with this style nit later.
40 | - run: git checkout HEAD~ # Skip the top commit, because it is already checked by the other tasks. 41 | - - run: sudo apt install ccache build-essential libtool autotools-dev automake pkg-config bsdmainutils python3-zmq libevent-dev libboost-dev libsqlite3-dev libdb++-dev systemtap-sdt-dev libminiupnpc-dev libnatpmp-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools qtwayland5 libqrencode-dev -y 42 | - - run: EDITOR=true git rebase --interactive --exec "./autogen.sh && CC=clang CXX=clang++ ./configure && make clean && make -j $(nproc) check && ./test/functional/test_runner.py -j $(( $(nproc) * 2 ))" $( git log --merges -1 --format='%H' ) 43 | + - run: sudo apt install clang ccache build-essential libtool autotools-dev automake pkg-config bsdmainutils python3-zmq libevent-dev libboost-dev libsqlite3-dev libdb++-dev systemtap-sdt-dev libminiupnpc-dev libnatpmp-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools qtwayland5 libqrencode-dev -y 44 | + # Use clang++, because it is a bit faster and uses less memory than g++ 45 | + - run: git rebase --exec "echo Running test-one-commit on \$( git log -1 ) && ./autogen.sh && CC=clang CXX=clang++ ./configure && make clean && make -j $(nproc) check && ./test/functional/test_runner.py -j $(( $(nproc) * 2 ))" "$( git log '^'$( git log --merges -1 --format='%H' ) HEAD --format='%H' ${MAX_COUNT} | tail -1 )~1"
fa5356cd49facf195447f0f5921dce1fa53cb25d
Why don't combine unrelated to MAX_COUNT changes into the previous commit?
For review, it may be better to just look at the overall changes. There are two commits, so that the CI can be observed working.
ACK fa5356cd49facf195447f0f5921dce1fa53cb25d
rfm or is there anything left to be done here?
Per https://github.com/bitcoin/bitcoin/actions/runs/6075652138/job/16482267917?pr=28279
Running test-one-commit on commit fafcd2e9ef1209d614de5763a2733098537919dd Author: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Wed Aug 16 16:40:42 2023 +0200 ci: Add test-each-commit task
ACK fa5356cd49facf195447f0f5921dce1fa53cb25d
Modulo one question in #28279 (review).
Looks like this is currently failing for new PRs: https://github.com/bitcoin/bitcoin/actions/runs/6184007676/job/16786866270?pr=28476
Run git rebase --exec "echo Running test-one-commit on \$( git log -1 ) && ./autogen.sh && CC=clang CXX=clang++ ./configure && make clean && make -j $(nproc) check && ./test/functional/test_runner.py -j $(( $(nproc) * 2 ))" "$( git log '^'$( git log --merges -1 --format='%H' ) HEAD --format='%H' ${MAX_COUNT} | tail -1 )~1"
fatal: invalid upstream '~1'
Error: Process completed with exit code 128.
I guess the issue is that ( git log '^'$( git log --merges -1 --format='%H' ) HEAD --format='%H' ${MAX_COUNT} | tail -1 ) prints nothing for some reason when there is only one commit in the pull request?
Not sure why, because locally it works:
$ git --version
git version 2.41.0
$ git log -1 --format='%H'
3c99f66f8a10aa4dfc1e85c3a240cc144442eac7
$ ( git log '^'$( git log --merges -1 --format='%H' ) HEAD --format='%H' ${MAX_COUNT} | tail -1 )
3c99f66f8a10aa4dfc1e85c3a240cc144442eac7