Morgan Smith <[email protected]> writes:

>> In theory, such tests could be done on CI. But adding this kind of
>> feature to CI tests will require work that may or may not be justified.
>>
>>> If I remember correctly though he wasn't able to make it work for
>>> rebasing which is how I made these patches :/.
>>
>> What exactly was the problem?
>
> https://newartisans.com/2009/02/building-a-better-pre-commit-hook-for-git/
>
> https://newartisans.com/2009/02/the-saga-of-rebase-versus-merge/
>
>
> I haven't actually tried implementing any of this and the blog posts
> date back to 2009 so there might be easy fixes for these issues
> available now.
>
> In the first link John Wiegley describes the issue with creating the
> pre-commit hook in the first place (wanting to test only the commit made
> while having a dirty worktree).
>
> In the second link he discovers his solution is inadequate for his
> workflow as the hooks aren't run on rebase.

I toyed with this problem a little with LLM, and got the following
script

#!/usr/bin/env bash
# .git/hooks/pre-push

# -------------------------------------------------
# Abort push if any commit that will be added to the
# remote fails `make test`.
# -------------------------------------------------

# Read each line from stdin (skip the first line which
# contains remote name and URL).
while read -r local_ref local_sha remote_ref remote_sha; do
    # Skip deletions (remote_sha = 0) and tags that are not
    # being updated (no new commits to test).
    [ "$local_sha" = "0" ] && continue

    # Determine the base commit that already exists on the remote.
    # If the remote does not have the ref yet, remote_sha will be
    # 0000000…; in that case we rebase onto the empty tree (i.e.
    # treat the whole history as “new”).
    base=${remote_sha:-$(git hash-object -t tree /dev/null)}

    # Rebase our new commits onto that base, running `make test`
    # after each one.  The `-x` option runs the command after every
    # replayed commit.
    if ! git rebase -x "make test" "$base" "$local_sha"; then
        echo "❌  Tests failed on $local_ref – push aborted."
        exit 1
    fi
done

# All tests passed → allow the push.
exit 0

-- 
Ihor Radchenko // yantar92,
Org mode maintainer,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

Reply via email to