Single-node transactions via pre-receive hook
In order to allow for strong consistency for Git reference updates, Gitaly nodes are expected to perform voting on the updates they intend to perform. While the server side for this exists already in form of the transaction manager and reference transaction service, the client-side is not yet wired up.
In this first iteration, we implement the client side by reaching out to the reference transaction service from the pre-receive hook. While this won't yet catch all reference updates but only those performed as the result of git-push(1), it serves as a first minimally viable demonstration that a two-phase commit via Git hooks works.
One interesting bit is that starting the transaction is not guarded by a feature flag on the hook side, but only by presence of environment variables that carry transaction information. As this environment variable is only set in case Praefect has registered a transaction, which in turn only happens if the "reference_transactions" feature flag is set, we are still guarded.
Further note the hook is only implemented in the Go hook service, which is in turn guarded by the "hooks_rpc" feature flag. As the work is currently of experimental nature, it's deemed as a nice proof of concept for the Go hooks RPC.
Note that this MR builds on !2137 (merged) for the logging part, so it shouldn't get merged before !2137 (merged) is. I tried to come up with a test to exercise this, but unfortunately I failed with this quest. Turns out it's quite hard to write a test exercising Git, Praefect and Gitaly with hooks working correctly. Anyway, I'm posting this MR for some feedback already, as I don't expect the implementation will change for now.
Edit: !2137 (merged) is merged now, so this MR is unblocked. I've also implemented a test case for this, but due to transactions not yet being observable, the test is currently rather limited in scope. This restriction is going to be lifted with the introduction of metrics, though.
References #2635 (closed)