tvl-depot/third_party/gerrit-queue
sterni 0c178a0ef6 chore(3p/sources): Bump channels & overlays
Upstream nixpkgs removed a lot of aliases this time, so we needed to do
the following transformations. It's a real shame that aliases only
really become discoverable easily when they are removed.

* runCommandNoCC -> runCommand
* gmailieer -> lieer
  We also need to work around the fact that home-manager hasn't catched
  on to this rename.
* mysql -> mariadb
* pkgconfig -> pkg-config
  This also affects our Nix fork which needs to be bumped.
* prometheus_client -> prometheus-client
* rxvt_unicode -> rxvt-unicode-unwrapped
* nix-review -> nixpkgs-review
* oauth2_proxy -> oauth2-proxy

Additionally, some Go-related builders decided to drop support for
passing the sha256 hash in directly, so we need to use the generic hash
arguments.

Change-Id: I84aaa225ef18962937f8616a9ff064822f0d5dc3
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6792
Autosubmit: sterni <sternenseemann@systemli.org>
Tested-by: BuildkiteCI
Reviewed-by: grfn <grfn@gws.fyi>
Reviewed-by: flokli <flokli@flokli.de>
Reviewed-by: tazjin <tazjin@tvl.su>
Reviewed-by: wpcarro <wpcarro@gmail.com>
2022-09-28 08:02:31 +00:00
..
.buildkite subtree(3p/gerrit-queue): Vendor at commit '24f5a642' 2021-12-09 16:13:56 +03:00
frontend refactor(3p/gerrit-queue): use go:embed, bump go1.16, drop shell.nix 2021-12-14 17:14:31 +00:00
gerrit subtree(3p/gerrit-queue): Vendor at commit '24f5a642' 2021-12-09 16:13:56 +03:00
misc subtree(3p/gerrit-queue): Vendor at commit '24f5a642' 2021-12-09 16:13:56 +03:00
submitqueue fix(3p/gerrit-queue): submitqueue/runner.go: fix format string 2021-12-14 17:14:31 +00:00
.gitignore subtree(3p/gerrit-queue): Vendor at commit '24f5a642' 2021-12-09 16:13:56 +03:00
default.nix chore(3p/sources): Bump channels & overlays 2022-09-28 08:02:31 +00:00
go.mod refactor(3p/gerrit-queue): use go:embed, bump go1.16, drop shell.nix 2021-12-14 17:14:31 +00:00
go.sum refactor(3p/gerrit-queue): use go:embed, bump go1.16, drop shell.nix 2021-12-14 17:14:31 +00:00
LICENSE subtree(3p/gerrit-queue): Vendor at commit '24f5a642' 2021-12-09 16:13:56 +03:00
main.go refactor(3p/gerrit-queue): use go:embed, bump go1.16, drop shell.nix 2021-12-14 17:14:31 +00:00
README.md subtree(3p/gerrit-queue): Vendor at commit '24f5a642' 2021-12-09 16:13:56 +03:00

gerrit-queue

This daemon automatically rebases and submits changesets from a Gerrit instance, ensuring they still pass CI.

In a usual gerrit setup with a linear master history, different developers await CI feedback on a rebased changeset, then one clicks submit, and effectively makes everybody else rebase again. gerrit-queue is meant to remove these races to master.

Developers can set the Autosubmit label to +1 on all changesets in a series, and if all preconditions on are met ("submittable" in gerrit speech, this usually means passing CI and passing Code Review), gerrit-queue takes care of rebasing and submitting it to master

How it works

Gerrit only knows about Changesets (and some relations to other changesets), but usually developers think in terms of multiple changesets.

Fetching changesets

gerrit-queue fetches all changesets from gerrit, and tries to identify these chains of changesets. We call them Series. All changesets need to have strict parent/child relationships to be detected (so if only half of the stack gets rebased by the Gerrit Web interface, these are considered individual series.

Series are sorted by the number of changesets in them. This ensures longer series are merged faster, and less rebases are triggered. In the future, this might be extended to other metrics.

Submitting changesets

The submitqueue has a Trigger() function, which gets periodically executed.

It can keep a reference to one single serie across multiple runs. This is necessary if it previously rebased one serie to current HEAD and needs to wait some time until CI feedback is there. If it wouldn't keep that state, it would pick another series (with +1 from CI) and trigger a rebase on that one, so depending on CI run times and trigger intervals, if not keepig this information it'd end up rebasing all unrebased changesets on the same HEAD, and then just pick one, instead of waiting for the one to finish.

The Trigger() function first instructs the gerrit client to fetch changesets and assemble series. If there is a wipSerie from a previous run, we check if it can still be found in the newly assembled list of series (it still needs to contain the same number of series. Commit IDs may differ, because the code doesn't reassemble a wipSerie after scheduling a rebase. If the wipSerie could be refreshed, we update the pointer with the newly assembled series. If we couldn't find it, we drop it.

Now, we enter the main for loop. The first half of the loop checks various conditions of the current wipSerie, and if successful, does the submit ("Submit phase"), the second half will pick a suitable new wipSerie, and potentially do a rebase ("Pick phase").

Submit phase

We check if there is an existing wipSerie. If there isn't, we immediately go to the "pick" phase.

The wipSerie still needs to be rebased on HEAD (otherwise, the submit queue advanced outside of gerrit), and should not fail CI (logical merge conflict) - otherwise we discard it, and continue with the picking phase.

If the wipSerie still contains a changeset awaiting CI feedback, we return from the Trigger() function (and go back to sleep).

If the changeset is "submittable" in gerrit speech, and has the necessary submit queue tag set, we submit it.

Pick phase

The pick phase finds a new wipSerie. It'll first try to find one that already is rebased on the current HEAD (so the loop can just continue, and the next submit phase simply submit), and otherwise fall back to a not-yet-rebased serie. Because the rebase mandates waiting for CI, the code returns the Trigger() function, so it'll be called again after waiting some time.

Compile and Run

go generate
GERRIT_PASSWORD=mypassword go run main.go --url https://gerrit.mydomain.com --username myuser --project myproject