blob: 6ee86a09a9b57fa77bfde6487510b34a924994db [file] [view] [edit]
---
title: "Design Doc - Push Reviews: Solution 2 proposed by Google"
permalink: design-docs/push-reviews-solution-google-2.html
hide_sidebar: true
hide_navtoggle: true
toc: false
---
# Solution 2 proposed by Google
## <a id="objective"> Objective
Address the [problems](/design-docs/push-reviews-use-cases.html#problem-statement)
and [use cases](/design-docs/push-reviews-use-cases.html#use-cases) through a
new `push-review` push option which creates a change for a push to a real
(non-magic/non-symbolic) ref. These "push-review changes" store the head at
upload time as the base commit for computing diffs in the change metadata to
make the push reviewable like any other Gerrit change. Submitting this change
sets the target branch to the pushed commit.
## <a id="design"> Design
The same as [solution 1](/design-docs/push-reviews-solution-google-1.html) but
with the following differences:
* Pushing with the `push-review` option creates a normal change that has the
pushed commit as the patch set and that stores the head of the target branch
at upload time as base commit in a new
`refs/changes/\<sharded-change-ID\>/base` meta ref.
* Creating a ref for the base commit is necessary so that this commit is
guaranteed to be still referenced from a ref after the push review change is
submitted. Submitting a push review change may remove the base commit from the
history of the target branch, and without the new
`refs/changes/\<sharded-change-ID\>/base` meta ref it may become unreachable
in this case, so that it would be garbage-collected at some point. This would
break the acceptance criteria that requires the old SHA1 to stay available for
auditing purposes.
* The new `refs/changes/\<sharded-change-ID\>/base` meta ref that stores the
base commit is read whenever the change meta ref is read. For perfomance
reasons we may store a flag in the change metadata to identify push review
changes so that the `refs/changes/\<sharded-change-ID\>/base` meta ref only
needs to be read for push review changes, and not for all changes.
* When the list of changed files is computed the stored base commit is used as
the base for the comparison (`FileInfoJsonImpl` calls
`DiffOperations#listModifiedFiles` with `oldCommit` = stored base commit if
present).
* When a file diff is computed the stored base commit is used as the base for
the comparison (when `PatchScriptFactory#create` is created with `patchSetA`
= null it uses the stored base commit if present).
* Disallow submit if the stored base commit doesn't match the current head of
the target branch (submission requires a rebase that updates the stored base
commit).
* The UI has a special visualization for push review changes so that users
clearly understand that this change is applying a direct update. Note that the
commit message is the one of the pushed commit and that there is no dedicated
message explaining the direct update (also see [cons](#cons) section).
All the rest is the same as with
[solution 1](/design-docs/push-reviews-solution-google-1.html), in particular we
still add a new submit strategy that (re)sets the target branch to the pushed
commit that is applied when a push review change is submitted.
### <a id="unsolved-issues"> Unsolved Issues
* Creating a push review for a commit that contains a Change-Id in the commit
message (e.g. when doing a branch rewind) likely causes confusion to users &
tooling, because the Change-Id in the commit message doesn't match the
Change-Id of the push review change.
### <a id="pros-and-cons"> Pros & Cons
A quick summary of the pros and cons of this solution.
Pros:
* The patch set commit is the pushed commit:
* Clients that fetch the commit get exactly the same commit to which the
branch will be (re)set (same SHA1). This may matter for CI systems that
expect to do verifications on the exact commit that is being submitted.
* It's possible to have changes that depend on a push review change
(successor changes) and submit them without needing to rebase them.
* Since push review changes are normal commits, not merge commits as with
solution 1, we do not need special casing in the UI to hide the AutoMerge and
the second parent commit in the base selection that are of no interest for
push review changes.
<a id="cons">Cons:
* It's not possible to attach a message to the direct push to explain what the
push is about (the shown commit message is the one of the pushed commit which
cannot be altered as this would change the SHA1).
* Higher effort than implementing solution 1:
* We must implement support for a new change meta ref which is expected to
be a signifacant amount of extra work.
* The UI must implement a special visualization for push review changes.
* We need special casing when computing the file list and file diffs. The
implementation looks quite straight-forward, but we need good test
coverage for the new logic.
* Inventing a new change meta ref makes the storage scheme more complicated:
* The additional complexity means that the code gets more difficult to read
and maintain and makes future extensions more difficult.
* Caches that use the SHA1 of the change meta branch as key may need to be
reworked if an additional change meta ref is added.
* All code that computes the list of changed files (via `DiffOperations`) must
be aware of push reviews (including plugins, e.g. the `code-owners` plugin).
It might be difficult to find all relevant places and make sure that new code
doesn't forget about the push review case. To prevent this we may need to
rework the `DiffOperations` API.