Fossil Forum

Commit hooks in Fossil
Login

Commit hooks in Fossil

Commit hooks in Fossil

(1) By Dan Shearer (danshearer) on 2022-04-11 10:51:06 [link] [source]

This post is what I have learned so far about client side of Fossil automation, which is easy and reliable. There are other kinds of automation suitable for more complicated continuous integration pipelines. Client-side pre-commit hooks in Fossil are about putting the developer in control, and getting set up in minutes. First I had to disentangle what is meant by 'hook' in Fossil, and figure out that a pre-commit hook is by default running on the client machine.

As so often in Fossil, the easy path for a pre-commit hook is also the friendly team path. If the project team can agree on a script to be run before each commit, then that script can be added to the central repo and each developer can type one line to enable it on their local Fossil repo. There are many other possibilities.

Example of how fossil hook works

cd /tmp
fossil new hooktest.fossil
mkdir hooktest
cd hooktest
fossil open ../hooktest.fossil
fossil hook list                                            # should be empty
fossil hook add --command ./test.sh --type before-commit    # test.sh can be any executable and need not exist yet
fossil hook list                                            # should show the hook we just added
                                                            # --command could be "/bin/true" or "C:\HOOK.BAT"
echo "#!/bin/sh" > test.sh ; echo "echo In Hook" > test.sh
chmod +x test.sh
cp /etc/hostname .
fossil add hostname
fossil commit                                               # should see the message "In Hook" appear

What is missing?

  • the help and documentation for fossil hook needs improvement, and this post is a step towards that.
  • this is not enforced in any way.
  • I think hooks need to be removed in reverse order with fossil hook delete, although I need to test some more
  • A clear acknowledgement that Fossil does not provide the full enormity of workflows supported by the big forges such as GitHub and GitLab, some of which are very powerful. Then again, you need to work quite hard to introduce into Fossil security problems from third-party toolchains such as GitHub and GitLab did in April 2021.

What are the alternatives?

  • fossil hook is nothing to do with Fossil TH1 hooks which are a work in progress that I have not yet made to function for me.
  • the other type of simple fossil hook is post-receive, and that is executed on the server side. For some operations that will be too late, so if you want a server-side pre-commit hook then you need TH1.
  • Another kind of trigger for post-commit operations is to run a script on receipt of a commit notification email.

I'm sure the good people here will point out the things I have overlooked.

(2) By Stephan Beal (stephan) on 2022-04-11 13:57:47 in reply to 1 [source]

the other type of simple fossil hook is post-receive, and that is executed on the server side. For some operations that will be too late...

FWIW... i suspect that a common misunderstanding here is that fossil can install server-side hooks to reject checkins which don't match project requirements. That is not the case for the very simple reason that if a server rejects your artifacts, you're left in a state where you can no longer push to that server without shunning the offending artifacts from your repo first (shunning being something that we (especially me) generally actively discourage). When a checkin is performed, your copy of the repo (which is entirely under your control) gets the checkin. You might be on a plane over the Atlanta, without internet access, hacking away with the intent to push those changes 17 hours later from Malta. If the server rejects them at that point, you're left holding a messy can of worms in the form of a repo you can no longer sync (pull, yes, but not push).

Because of such eventualities, fossil cannot feasibly outright reject what's already been checked in somewhere.

(4) By John Rouillard (rouilj) on 2022-04-13 15:18:47 in reply to 2 [link] [source]

That is not the case for the very simple reason that if a server rejects your artifacts, you're left in a state where you can no longer push to that server without shunning the offending artifacts from your repo first (shunning being something that we (especially me) generally actively discourage).

Well we already have a case where changes to a local repo won't sync: private branches. Would it be possible to mark artifacts as private, rather than shunning them?

Also is there a post-receive hook? https://fossil-scm.org/home/doc/trunk/www/hooks.md only show after-receive and that hook can't prevent artifact commits. It can only send email notifications, trigger builds etc.

Also, assume revision 1df456 fails the validation in the (mythical) post-receive hook (let's say due to a format style failure). Would revision 1df456 + 1 that fixes the issue be able to be received? I am not sure if this needs a change to the sync protocol (or maybe could be implemented in the mythical post-receive hook). IIUC the artifacts are sent unordered and there is no way for a post-receive hook to react to and process only the set of artifacts associated with a single commit.

Say I am pushing revisions (simple number to make it easier):

20 and 50

that has artifacts 21, 23, 22 and 55, 52, 53, and 51 in their respective manifests.

When should post-receive run? after-receive runs on a list of artifacts that could include multiple commits and may not even have all of the artifacts that make up a commit (manifest) artifact if the xfer was incomplete and not completed in 60 seconds (see hooks.md).

For a rejectable hook to be useful I think:

  1. the unit of evaluation would need to be a complete commit manifest and all referenced artifacts.
  2. needs to be called for each complete commit manifest and its artifacts. after-receive
  3. has to be called outside of back-office in the same transaction as the xfer.
  4. needs to be able to determine that a failed commit has a successor commit (which I think is info in the manifest) or was amended. Then have some mechanism to analyze the successor commit skipping/allowing the bad commit.

    Alternatively, the client marks the bad commit as "private" and cherry picks the private commit to a new commit that is properly formatted and only the good commit is pushed.

Another possible way to handle this is to permit transfer of bundles that undergo bundle-receive (rather than post-receive) and if they pass the script they are automatically applied as commits. I am not sure that applying the bundle for commit 50 would result in manifest 50 and artifacts 51, 52, 53, 55 being applied just as though it has been pushed from the original repo.

(5) By Stephan Beal (stephan) on 2022-04-13 16:48:27 in reply to 4 [link] [source]

Well we already have a case where changes to a local repo won't sync: private branches. Would it be possible to mark artifacts as private, rather than shunning them?

Once an artifact has gone public (via the rejected-by-hooks checkin, in this case), it can no longer be made private. Why that is so i can't say with certainty, i just recall that it's one of the internal conditions for private checkins.

As to your other questions i can't say with any certainty or authority - the hooks features are a part of fossil i've never explored.

Another possible way to handle this is to permit transfer of bundles that undergo bundle-receive (rather than post-receive) and if they pass the script they are automatically applied as commits.

FWIW, that sounds feasible to me. It would open up the potential for a race condition which could leading to unintentional forks, but those are easy to resolve in fossil.

(3) By sean (jungleboogie) on 2022-04-11 17:38:54 in reply to 1 [link] [source]

A clear acknowledgement that Fossil does not provide the full enormity of workflows supported by the big forges such as GitHub and GitLab, some of which are very powerful.

Why does this need to be acknowledged?

I first learned about workflows from Simon Willson a year or two ago. I posted about it on this forum, and basically came to the conclusion that things could be done similar to workflows via cronjobs and shell scripts.

I more or less have been doing this since ~2020, before I know about the workflow thing, without the integration of Fossil hooks.