blob: 7077b534840b25fb3a84e39e6def165f6d4f385e [file] [log] [blame] [view]
The @PLUGIN@ plugin provides a mechanism for building and previewing
sets of proposed updates to multiple projects/refs that should be
applied in a batch. These updates are built with Gerrit changes.
While a large focus of Gerrit changes is reviewing, the focus of
batch updates tend to be verification (by CI systems). Batch
updates are not reviewable in the Gerrit UI, but they are
downloadable as git refs. The @PLUGIN@ update service provides the
tools to build these refs by merging changes to temporary "snapshot"
refs, which can then be tested and finally "submitted" as a "unit"
if desired. The intent is to make the same exact (same git SHA1s)
updates testable across potentially many machines, and to apply
those exact SHA1s to the final destination refs on batch submittal.
Creating Batches
----------------
A simple use case for a @PLUGIN@ update might look like this:
a CI systems wants to verify a build for changes 123 (patchset 3),
and 456 (patchset 7) at the same time. These changes are destined
for projectA/branchX, and projectB/branchY respectively. The CI
system (jenkins gerrit user) may start by opening a batch,
merging changes to it, and closing the batch, all in one simple
command like this:
<a name="batchexample"></a>
```
$ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ merge-change 123,3 456,7 --close
{
"destinations": [
{
"changes": [
{
"number": 123,
"patch_set": 3
}
],
"download_ref": "refs/batch/users/jenkins/0644a132-5b79-4c88-bf22-9364a1d02deb/refs/heads/branchX",
"project": "projectA",
"ref": "refs/heads/branchX",
"sha1": "00de3cf878b8bd51fa56aa9a8d5e8631ae71ad60"
},
{
"changes": [
{
"number": 456,
"patch_set": 7
}
],
"download_ref": "refs/batch/users/jenkins/0644a132-5b79-4c88-bf22-9364a1d02deb/refs/heads/branchY",
"project": "projectB",
"ref": "refs/heads/branchY",
"sha1": "bd26d343b99c25a0704d0ffe5c431900b1cf5c89"
}
],
"id": "0644a132-5b79-4c88-bf22-9364a1d02deb",
"last_modified": "July 22, 2014 10:43:28 AM",
"owner": {
"id": 1000000
},
"state": "CLOSED"
}
```
Downloading Batches
-------------------
The CI system may then parse this json to get the refs to download the
batch updates from, download and test the batches.
Download Ref Location
---------------------
Download refs have two possible locations. By default the username will be
checked and if present it will be used, and the ref will be stored under the
refs/batch/users/* namespace. In the case that the username is not present
the account id will be used instead, and the ref will be stored under the
refs/batch/accounts/* namespace.
Username present:
`refs/batch/users/{username}/...`
Username not present:
`refs/batch/accounts/{account id}/...`
The format above may be counted on and should be used to set read access
permissons on. The format of the download_ref after the "..."s is internal
and should not be counted on to be stable, use the download_ref field to
access the batch data instead of guessing at the format of this ref.
Submitting Batches
------------------
As a final step, the CI system may, on success, submit the batch (using the
batch id that it parsed from the json) like this:
```
$ ssh -p @SSH_PORT@ @SSH_HOST@ @PLUGIN@ submit --force \
0644a132-5b79-4c88-bf22-9364a1d02deb
```
This will then predictably apply the exact commits in the "sha1"
entries to the respective destinations using a force push approach. This
allows CI systems to test changes as if they were already merged on the
destination branches instead of testing them "as is", which might
otherwise mean testing changes which are outdated with respect to the
destination branches.
Because neither git nor Gerrit supports updating refs atomically across
repositories, the forced push approach has been found to be the most
reliable approach for CI systems to use to ensure that what they tested
gets applied to their branches. Using a forced push strategy requires
that the account submitting batches have FORCE PUSH permissons. To
make this work reliably and to ensure that no history is ever lost, it
is important that batches are only ever built from the current tips, and
that those batches get submitted before any of the tips change. If other
batches or changes are submitted to the batch's destination branches
after the batch was created but before it is submitted using force push,
then some history will likely be lost. The risk of this occurring is a
generally seen as a worthwhile tradeoff to ensure that only what has been
tested ever gets merged into a branch's history. It is advisable to only
ever update branches that will have batches submitted to them by an actor
that can create and submit batches "serially" and be the only actor
updating these branches. This can be achieved by removing SUBMIT
permissions from all accounts and giving a single account, used by a
single process, FORCE PUSH permission to create and submit batches
following the guidelines above.
Batch Storage
-------------
In order to maintain state about which changes are in a batch, and where the
download refs are stored for each batch, the batch data is stored as json on
the special refs/meta/batch/<batch_id> ref in the All-Projects project. This
is internal meta data to the batch plugin and these refs should not be
accessed or altered by users directly.
Batch Cleanup
-------------
Batches are temporary proposed updates. They are meant to be
created, tested, and then submitted to their destinations if
they pass, or deleted if they fail. Since the output of good
batches will likely persist on destination branches, and
the results of bad batches are not typically desirable to keep
around, the batch service has a background *cleaner* task
which finds expired batches and deletes them automatically.
This cleaning helps to ensure that resources are released when
they are no longer needed.
The cleaner task runs by default daily, and batches are expired
by default after 3 days from their last modification. It is
possible to configure expiration times, and the cleaner using
the `All-Projects` `refs/meta/config` `@PLUGIN@.config` file.
The `@PLUGIN@.config` file is a "git-config" style file
and supports the following parameters:
*`cleaner.maxAge`*
: Age after which a batch is considered expired. Values should
use common unit suffixes to express their setting:
* s, sec, second, seconds (default unit)
* m, min, minute, minutes
* h, hr, hour, hours
* d, day, days
* w, week, weeks (1 week is treated as 7 days)
* mon, month, months (1 month is treated as 30 days)
* y, year, years (1 year is treated as 365 days)
: If a unit suffix is not specified, seconds is assumed. If 0 is
supplied, the maximum age is infinite and items are never
expired (they must be deleted manually). The default maxAge is
3 days.
*`cleaner.interval`*
: Interval for periodic repetition of triggering the batch
cleanups. The interval must be larger than zero. The following
suffixes are supported to define the time unit for the interval:
* m, min, minute, minutes (default suffix)
* h, hr, hour, hours
* d, day, days
* w, week, weeks (1 week is treated as 7 days)
* mon, month, months (1 month is treated as 30 days)
* y, year, years (1 year is treated as 365 days)
: If a unit suffix is not specified, minutes is assumed. The
default interval is 1 day.
*`cleaner.startDelay`*
: One time delay to wait after plugin load before starting
the periodic cleaner. The following suffixes are supported
to define the time unit for the delay:
* m, min, minute, minutes (default suffix)
* h, hr, hour, hours
* d, day, days
* w, week, weeks (1 week is treated as 7 days)
* mon, month, months (1 month is treated as 30 days)
* y, year, years (1 year is treated as 365 days)
: If a unit suffix is not specified, minutes is assumed. The
default startDelay is 1 minute.