Skip to content

Commit dc2f783

Browse files
committed
Explain how GitGitGadget's backend is set up
1 parent f213e5d commit dc2f783

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# How does GitGitGadget process user comments on PRs?
2+
3+
GitGitGadget is implemented as a GitHub App (with the very imaginative name ["GitGitGadget"](https://github.com/apps/gitgitgadget)), which means that a webhook is called on certain events, such as new PR comments on PRs (e.g. `issue_comment`).
4+
5+
In GitGitGadget's case, this webhook is implemented as an Azure Function: https://github.com/gitgitgadget/gitgitgadget/tree/master/azure-function
6+
7+
Apart from validating that the payload really originated from GitHub, the Azure Function performs a rudimentary check whether the comment (if it was triggered by a comment) contains a command that GitGitGadget should act on, and depending on that check triggers the Azure Pipeline [GitGitGadget PR Handler](https://dev.azure.com/gitgitgadget/git/_build?definitionId=3).
8+
9+
The `push` event (and also the `pull_request` event) is not actually handled by the Azure Function. It is handled via the Azure Pipeline being configured as "Pull request validation". That also allows it to be shown in the Checks tab of the PR.
10+
11+
You can see the difference on https://dev.azure.com/gitgitgadget/git/_build?definitionId=3: the `push`-triggered builds are labeled as "Pull request build", and the `issue_comment` ones as "Manual build" (because they are triggered using a Personal Access Token, also known as "PAT").
12+
13+
Depending how the Azure Pipeline was triggered, it calls [`misc-helper.ts`](https://github.com/gitgitgadget/gitgitgadget/blob/master/script/misc-helper.ts) with the `handle-pr-comment` or with the `handle-pr-push` parameter, respectively.
14+
15+
# Keeping https://github.com/gitgitgadget/git up to date
16+
17+
The repository gitgitgadget/git is kept up to date by two Azure Pipelines: [Synchronize gitster.git to GitGitGadget](https://dev.azure.com/gitgitgadget/git/_build?definitionId=8) and [Synchronize git.git to GitGitGadget](https://dev.azure.com/gitgitgadget/git/_build?definitionId=7).
18+
19+
## Why synchronize both git/git _and_ gitster/git?
20+
21+
### Background
22+
23+
The existence of the `git/git` -> `gitgitgadget/git` pipeline is probably obvious.
24+
25+
The `gitster/git` repository contains the individual branches for code contributions, and the first reason why the corresponding pipeline was added is that `pu` had test failures all the time without any actionable information: it has been always unclear _which_ of those patch series that made it into `pu` was responsible for the test failures. Now with the individual branches being mirrored into `gitgitgadget/git`, and obviously triggering [CI builds](https://dev.azure.com/gitgitgadget/git/_build?definitionId=4), it is a lot easier to find the culprits.
26+
27+
Of course, from time to time the `pu` failures are caused by unfortunate interactions of separate patch series' changes, in which case the CI builds of the individual branches may very well succeed but `pu` still causes failures, which is a very useful piece of information in and of itself.
28+
29+
A secondary benefit of mirroring the `gitster/git` branches is that PRs at `gitgitgadget/git` can target more fine-grained base commits. I use this a lot, e.g. in my six "built-in add -i/-p" patch series which build on top of each other.
30+
31+
While the pipeline that synchronizes with `gitster/git` is triggered by all updates to `refs/heads/*`, for technical reasons polling every 180 seconds, i.e. every three minutes, the pipeline that synchronizes with `git/git` is triggered immediately.
32+
33+
### What do the pipelines do, exactly?
34+
35+
The pipeline that mirrors gitster/git into gitgitgadget/git (the pipeline names cannot contain slashes, that's why the `/` was replaced by a `.`) has two tasks:
36+
37+
1. Synchronize branch:
38+
```bash
39+
case "$(Build.SourceBranch)" in
40+
refs/heads/*)
41+
refspec="+HEAD:$(Build.SourceBranch)"
42+
;;
43+
refs/tags/*)
44+
refspec="$(Build.SourceBranch)"
45+
;;
46+
*)
47+
echo "Cannot handle '$(Build.SourceBranch)'" >&2
48+
exit 1
49+
;;
50+
esac
51+
52+
git -c http."https://github.com/gitgitgadget/git".extraheader="Authorization: Basic $(gitgitgadget.push.token.base64)" \
53+
push https://github.com/gitgitgadget/git "$refspec"
54+
```
55+
2. Synchronize tags (if necessary):
56+
```bash
57+
die () {
58+
echo "$*" >&2
59+
exit 1
60+
}
61+
62+
for d in git gitgitgadget
63+
do
64+
git ls-remote --tags https://github.com/$d/git | grep -v '\^{}$' | sort >tags.$d ||
65+
die "Could not enumerate tags in $d"
66+
done
67+
68+
refspec="$(comm -23 tags.git tags.gitgitgadget | tr '\t' :)" ||
69+
die "Could figure out missing tags"
70+
71+
if test -z "$refspec"
72+
then
73+
echo "##vso[task.complete result=Skipped]No tags to synchronize!"
74+
else
75+
git -c http."https://github.com/gitgitgadget/git".extraheader="Authorization: Basic $(gitgitgadget.push.token.base64)" \
76+
push https://github.com/gitgitgadget/git $refspec
77+
fi
78+
```
79+
80+
That second task is necessary because there is currently no way to trigger non-YAML Azure Pipelines from tag updates. Of course this means that new tags are only synchronized together with branch updates, but in practice that's okay because the Git maintainer always pushes out the tags with corresponding branches.
81+
82+
This task mirrors tags from the git/git repository, even if the pipeline purports to mirror `gitster/git` to `gitgitgadget/git`; This is a deliberate decision, to make sure that we only mirror the "official tags" from the authoritative repository.
83+
84+
The two pipelines are identical except for these aspects:
85+
- The `gitster/git` repository contains substantially more branches. The only `git/git` branch that is missing from `gitster/git` is `todo`, which [we might parse at some stage to provided concise excerpts from the "What's cooking" mails](https://github.com/gitgitgadget/gitgitgadget/issues/152).
86+
- For technical reasons, the `git/git` pipeline does not need to poll.
87+
88+
### Git GUI's branches
89+
90+
As GitGitGadget can also be used to contribute Git GUI patches and patch series, there is also the [Synchronize git-gui.git (branches only) to GitGitGadget](https://dev.azure.com/gitgitgadget/git/_build?definitionId=10) pipeline. It mirrors the branches of Pratyush Yadav's repository (i.e. the current Git GUI maintainer's authoritative repository) into the `git-gui/*` namespace on `gitgitgadget/git`.

0 commit comments

Comments
 (0)