gerrit

[!NOTE|label:references:]

.gitconfig

$ git config --global gitreview.username <UserName>
$ git config --global gitreview.remote origin

default groups

[!TIP]

special references

magic references

  • refs/for/<branch ref>

get project.config

  • clone the repo

    $ git clone <repo url>
    # or update the local repo to HEAD
    $ git pull [--rebase]
  • checkout meta/config

    $ git fetch origin refs/meta/config:refs/remotes/origin/meta/config
    $ git checkout meta/config

    or

    $ git fetch ssh://localhost:29418/project refs/meta/config
    $ git checkout FETCH_HEAD

publish to remote

$ git add --all .
$ git commit -m "<add your comments here>"
  • submit directly

    $ git push origin meta/config:meta/config

    or

    $ git push origin HEAD:refs/meta/config
  • submit review

    [!NOTE|label:references:]

    $ git push origin HEAD:refs/for/refs/meta/config
    • or

      $ git push origin meta/config:refs/for/refs/meta/config

update meta/config if remotes update

$ git fetch origin --force refs/meta/config:refs/remotes/origin/meta/config

$ git pull origin refs/meta/config
# or
$ git merge meta/config

reset to remotes

$ git fetch origin --force refs/meta/config:refs/remotes/origin/meta/config
$ git reset --hard remotes/origin/meta/config

useful refs

sandbox:

refs/heads/sandbox/${username}/*

its-jira:

  • for project specific

    [commentlink "its-jira"]
      match = ^[ \\t]*PROJECT-([0-9]{1,5}):
      link = https://<jira-domain>:<jira-port>/browse/PROJECT-$1
  • for common setup

    [plugin "its-jira"]
      association = OPTIONAL
      branch = ^refs/heads/.*
      branch = ^refs/heads/stable-.*
      commentOnChangeAbandoned = false
      commentOnChangeCreated = true
      commentOnChangeMerged = true
      commentOnChangeRestored = false
      commentOnCommentAdded = false
      commentOnFirstLinkedPatchSetCreated = true
      commentOnPatchSetCreated = false
      commentOnRefUpdatedGitWeb = true
      enabled = enforced
    [commentlink "its-jira"]
      match = ^[ \\t]*([A-Za-z]*-[0-9]{1,5}):
      link = https://<jira-domain>:<jira-port>/browse/$1
    [commentlink "changeid"]
      match = (I[0-9a-f]{8,40})
      link = "#/q/$1"

verified label

[label "Verified"]
    function = MaxWithBlock
    defaultValue = 0
    copyAllScoresIfNoCodeChange = true
    value = -1 Fails
    value =  0 No score
    value = +1 Verified

change-id

[receive]
  requireChangeId = true
  createNewChangeForAllNotInTarget = false
  maxObjectSizeLimit = 6m
  maxBatchChanges = 1
[commentlink "changeid"]
  match = (I[0-9a-f]{8,40})
  link = "#/q/$1"

freeze main branch

[!TIP] One quirk is that the shortest possible pattern expansion must be a valid ref name thus ^refs/heads/.*/name will fail because refs/heads//name is not a valid reference but ^refs/heads/.+/name will work.

About the refs/for namespace

[!TIP] references:

refs/for/* syntax is just a short name for refs/for/refs/*:

  • project.config

    [access "refs/for/refs/heads/main"]
      push = block group user/Marslo Jiao (marslo)
      push = block group Registered Users
      submit = block group Registered Users
      submit = block group group user/Marslo Jiao (marslo)
      addPatchSet = block group user/Marslo Jiao (marslo)
      addPatchSet = block group Registered Users
      pushMerge = block group user/Marslo Jiao (marslo)
      pushMerge = block group Registered Users
  • groups

    ...
    global:Project-Owners      Project Owners
    global:Registered-Users    Registered Users
    ...
    user:marslo                user/Marslo Jiao(marslo)
    ...

freeze multiple branches (stable & release) for the specific account

  • project.config

    [access "^refs/for/refs/heads/(stable|release)$"]
      push = block group Registered Users
      submit = block group Registered Users
      addPatchSet = block group Registered Users
      pushMerge = block group Registered Users
    [access "^refs/heads/(stable|release)$"]
      read = group user/Marslo Jiao (marslo)
      push = +force group user/Marslo Jiao (marslo)
      pushMerge = group user/Marslo Jiao (marslo)
    • or using exclusiveGroupPermissions

      [access "^refs/heads/backup/(main|dev|staging|stable)/.+$"]
             exclusiveGroupPermissions = create delete push pushMerge
             create = group Project Owners
             create = block group Registered Users
             delete = block group Registered Users
             push = block group Registered Users
             pushMerge = block group Registered Users
      [access "^refs/for/refs/heads/backup/(main|dev|staging|stable)/.+$"]
             exclusiveGroupPermissions = addPatchSet create push pushMerge submit
             addPatchSet = block group Registered Users
             create = block group Registered Users
             push = block group Registered Users
             pushMerge = block group Registered Users
             submit = block group Registered Users
  • groups

    ...
    global:Project-Owners      Project Owners
    global:Registered-Users    Registered Users
    ...
    user:marslo                user/Marslo Jiao(marslo)
    ...

only allow code review merge, forbidden code push

[!TIP|label:references:]

  • restriction for branches (feature1, feature2 and main)

  • project.config

    [access "refs/*"]
      read = group Project Owners
      read = group user/Marslo Jiao (marslo)
    [access "refs/for/*"]
      addPatchSet = group Project Owners
      addPatchSet = group user/Marslo Jiao (marslo)
      push = group Project Owners
      push = group user/Marslo Jiao (marslo)
      pushMerge = group Project Owners
      pushMerge = group user/Marslo Jiao (marslo)
    [access "^refs/heads/(feature1|feature2|main)$"]
      push = block group Registered Users
      pushMerge = block group Registered Users
      submit = group Change Owner
  • groups

    ...
    global:Project-Owners      Project Owners
    global:Registered-Users    Registered Users
    ...
    user:marslo                user/Marslo Jiao(marslo)
    ...
  • example

    [!TIP|label:references:]

    [project]
      description = Gerrit Code Review
    [access "refs/*"]
      owner = group google/gerritcodereview-maintainers@googlegroups.com
    [access "refs/heads/*"]
      label-Code-Review = -2..+2 group google/gerritcodereview-maintainers@googlegroups.com
      label-Code-Review = -2..+2 group polygerrit-maintainers
      label-Verified = -1..+1 group Change Owner
      label-Verified = -1..+1 group gerrit-verifiers
      label-Code-Style = -1..+1 group gerrit-verifiers
      label-Verified-Notedb = -1..+1 group gerrit-verifiers
      label-Library-Compliance = -1..+1 group gerrit-lib
      label-Library-Compliance = -1..+0 group google/gerritcodereview-maintainers@googlegroups.com
      submit = group Change Owner
      submit = group google/gerritcodereview-maintainers@googlegroups.com
      create = group google/gerritcodereview-maintainers@googlegroups.com
      abandon = group gerrit-verifiers
      editTopicName = +force group google/gerritcodereview-maintainers@googlegroups.com
      removeReviewer = group google/gerritcodereview-maintainers@googlegroups.com
      publishDrafts = group google/gerritcodereview-maintainers@googlegroups.com
    [access "refs/tags/*"]
      create = group gerrit-release-creators
      create = group google/gerritcodereview-maintainers@googlegroups.com
      createTag = group gerrit-release-creators
      createTag = group google/gerritcodereview-maintainers@googlegroups.com
      createSignedTag = group gerrit-release-creators
      createSignedTag = group google/gerritcodereview-maintainers@googlegroups.com
    [access]
      inheritFrom = Public-Projects
    [receive]
      rejectImplicitMerges = true
    [reviewer]
      enableByEmail = true
    [label "Verified"]
      function = MaxNoBlock
      copyAllScoresIfNoCodeChange = true
      value = -1 Fails
      value = 0 No score
      value = +1 Verified
      defaultValue = 0
    [label "Code-Style"]
      function = MaxWithBlock
      copyAllScoresIfNoCodeChange = true
      value = -1 Wrong Style or Formatting
      value = 0 No score
      value = +1 Style Verified
      defaultValue = 0
    [label "Library-Compliance"]
      function = MaxWithBlock
      copyAllScoresIfNoCodeChange = true
      copyAllScoresOnTrivialRebase = true
      value = -1 Do not submit
      value = 0 No score
      value = +1 Approved
      defaultValue = 0
    [access "refs/for/refs/meta/dashboards/*"]
      push = group google/gerritcodereview-maintainers@googlegroups.com
    [access "refs/meta/dashboards/*"]
      label-Code-Review = -2..+2 group google/gerritcodereview-maintainers@googlegroups.com
      label-Code-Review = -1..+1 group Registered Users
      label-Verified = -1..+1 group gerrit-verifiers
      label-Verified = -1..+1 group google/gerritcodereview-maintainers@googlegroups.com
      submit = group google/gerritcodereview-maintainers@googlegroups.com
      forgeAuthor = group google/gerritcodereview-maintainers@googlegroups.com
      label-Code-Style = -1..+1 group google/gerritcodereview-maintainers@googlegroups.com
    [access "refs/for/refs/meta/config"]
      push = group gerrit-verifiers
    [notify "polygerrit-reviews"]
      email = polygerrit-reviews@google.com
      type = all_comments
      type = submitted_changes
      header = cc
      filter = file:polygerrit-ui
    [access "refs/heads/infra/config"]
      push = group gerrit-tricium-admins

Code-Review 1+1=2

[!NOTE|label:references:]

[label "Code-Review"]
  function = NoOp
  copyMinScore = true
  value = -2 This shall not be merged
  value = -1 I would prefer this is not merged as is
  value = 0 No score
  value = +1 Looks good to me, but someone else must approve
  value = +2 Looks good to me, approved
  defaultValue = 0
[submit-requirement "Code-Review"]
  submittableIf = (label:Code-Review=+1,count>=2 OR label:Code-Review=MAX) AND -label:Code-Review=MIN

optional label vote

[!NOTE|label:references:]

[label "Klocwork"]
  function = NoOp
  value = -1 Fails
  value = 0 No score
  value = +1 Success
  defaultValue = 0
  copyAllScoresIfNoCodeChange = true

sections

[!NOTE|label:references:]

commentlink

[commentlink "changeid"]
  match = (I[0-9a-f]{8,40})
  link = "/q/$1"

[commentlink "bugzilla"]
  match = "(^|\\s)(bug\\s+#?)(\\d+)($|\\s)"
  link = http://bugs.example.com/show_bug.cgi?id=$3
  prefix = $1
  suffix = $4
  text = $2$3

[commentlink "its-jira"]
  match = ^[ \\t]*([A-Za-z]*-[0-9]{1,5}):
  link = https://jira.domain.com/browse/$1

receive

[receive]
  requireChangeId = true
  createNewChangeForAllNotInTarget = false
  rejectImplicitMerges = false
  requireSignedOffBy = true
  maxObjectSizeLimit = 6m
  maxBatchChanges = 1

change

[change]
  privateByDefault = false
  workInProgressByDefault = false

[!NOTE|label:references:]

  • exempt a branch example

    [submit-requirement "Code-Style"]
      description = Code is properly styled and formatted
      applicableIf = -branch:refs/meta/config
      submittableIf = label:Code-Style=+1 AND -label:Code-Style=-1
      canOverrideInChildProjects = true
    • or setup in label: LABEL

      [label "Verified"]
        branch = refs/heads/release/*
      
      # same as
      [submit-requirement "Verified"]
        submittableIf = label:Verified=MAX AND -label:Verified=MIN
        applicableIf = branch:^refs/heads/release/.*
  • complex rule

    [!NOTE|label:references:]

     [submit-requirement "Core-Library-Review"]
        description = "SDK core library changes need to be approved for each platform or have a 'CoreLibraryReviewExempt: <reason>' footer. See also: https://github.com/dart-lang/sdk/wiki/Gerrit-Submit-Requirements#core-library-review"
        applicableIf = NOT ownerin:bots AND NOT is:pure-revert AND path:\"^sdk/lib/[^_].*\\.dart$\"
        submittableIf = hasfooter:CoreLibraryReviewExempt OR ((label:Code-Review=+1,group=mdb/dart-core-library-change-approvers-api OR ownerin:mdb/dart-core-library-change-approvers-api) AND (label:Code-Review=+1,group=mdb/dart-core-library-change-approvers-vm OR ownerin:mdb/dart-core-library-change-approvers-vm) AND (label:Code-Review=+1,group=mdb/dart-core-library-change-approvers-wasm OR ownerin:mdb/dart-core-library-change-approvers-wasm) AND (label:Code-Review=+1,group=mdb/dart-core-library-change-approvers-web OR ownerin:mdb/dart-core-library-change-approvers-web))
        canOverrideInChildProjects = false
  • commit message format

    applicableIf = message:\"^.*(D|d)(O|o) (N|n)(O|o)(T|t) (R|r)(E|e)(V|v)(I|i)(E|e)(W|w).*\"
  • branch regex

    applicableIf = branch:\"^refs/heads/release-branch.+\"

plugin

[plugin "its-jira"]
  association = OPTIONAL
  branch = ^refs/heads/.*
  commentOnChangeAbandoned = false
  commentOnChangeCreated = true
  commentOnChangeMerged = true
  commentOnChangeRestored = false
  commentOnCommentAdded = true
  commentOnFirstLinkedPatchSetCreated = true
  commentOnPatchSetCreated = false
  commentOnRefUpdatedGitWeb = true
  enabled = enforced

[!NOTE|label:references:]

[!TIP|label:references:]

  • by rules.pl

    submit_rule(S) :-
        gerrit:default_submit(X),
        X =.. [submit | Ls],
        add_non_author_approval(Ls, R),
        S =.. [submit | R].
    
    add_non_author_approval(S1, S2) :-
        gerrit:commit_author(A),
        gerrit:commit_label(label('Code-Review', 2), R),
        R \= A, !,
        S2 = [label('Non-Author-Code-Review', ok(R)) | S1].
    add_non_author_approval(S1, [label('Non-Author-Code-Review', need(_)) | S1]).
  • by project.config

    [access "refs/*"]
      label-Code-Review = block -2..+2 group Change Owner
      exclusiveGroupPermissions = label-Code-Review
  • by submit-requirement

    [submit-requirement "Code-Review"]
      description = A maximum vote from a non-uploader is required for the \
                    'Code-Review' label. A minimum vote is blocking.
      submittableIf = label:Code-Review=MAX,user=non_uploader AND -label:Code-Review=MIN
      canOverrideInChildProjects = true

[label "Code-Review"]
  function = NoBlock
  value = -2 This shall not be submitted
  value = -1 I would prefer this is not merged as is
  value = 0 No score
  value = +1 Looks good to me, but someone else must approve
  value = +2 Looks good to me, approved
  defaultValue = 0
[submit-requirement "Code-Review"]
  description = At least one maximum vote for label 'Code-Review' is required
  submittableIf = label:Code-Review=MAX,user=non_uploader AND -label:Code-Review=MIN
  canOverrideInChildProjects = true

[!TIP] check also:

  • optional validation

    submit_rule(S) :-
        gerrit:default_submit(X),
        X =.. [submit | Ls],
        require_ticket_check_for_ticket(Ls, Nls),
        S =.. [submit | Nls].
    
    require_ticket_check_for_ticket(S1, S2) :-
        gerrit:commit_message_matches('^issue-[\\d]+\\s?:\\s?[\\w\\W]+'),
        !,
        S2 = [label('Ticket-Checked', need(_)) | S1].
    
    require_ticket_check_for_ticket(S1, S2) :-
        !, S2 = S1.
  • optional validation with auto vote

    submit_rule(S) :-
        gerrit:default_submit(X),
        X =.. [submit | Ls],
        require_ticket_check_for_ticket(Ls, Nls),
        S =.. [submit | Nls].
    
    require_ticket_check_for_ticket(S1, S2) :-
        gerrit:commit_message_matches('\\[issue-[\\d]{2}\\]\\s?:\\s?[\\w\\W]+'),
        !,
        S2 = [label('Ticket-Checked', ok(user(824))) | S1].
    
    require_ticket_check_for_ticket(S1, S2) :-
        !, S2 = S1.
  • mandatory validation

    submit_rule(S) :-
      gerrit:default_submit(X), % get the current submit structure
      X=.. [submit | Ls],
      require_ticket_check_for_ticket(Ls, Nls),
      S=.. [submit | Nls].
    
    require_ticket_check_for_ticket(S1, S2) :-
       gerrit:commit_message_matches('\\[issue-[\\d]{2}\\][\\s\\S]+'),
       !,
       S2 = [label('Ticket-Checked', ok(user(790))) | S1]. % Add the label and automatically approval by user-id: 790
    
    require_ticket_check_for_ticket(S1, [label('Ticket-Checked', need(_)) | S1]).

tips

$ echo Change-Id: I$({ git var GIT_COMMITTER_IDENT ; echo "$refhash" ; git show HEAD; } | git hash-object --stdin)
Change-Id: I86a371ebf8d29fd1634ed9191d594ce22b1f0953

if(manager.build.result.isBetterThan(hudson.model.Result.UNSTABLE)) {
    def cmd = 'ssh -p 29418 HOST gerrit review --verified +1 --code-review +2 --submit --project $GERRIT_PROJECT $GIT_COMMIT'
    cmd = manager.build.environment.expand(cmd)
    manager.listener.logger.println("Merge review: '$cmd'")
    def p = "$cmd".execute()
    manager.listener.logger.println(p.in.text)
    manager.addShortText("M")
}

$ # setup (only needed once)
$ git config --global alias.gerrit-id '!f() { git log |egrep "^(commit | *Change-Id:)" |grep -B1 $1 |head -1 |sed "s,^commit ,,"; }; f'
$ # use:
$ git gerrit-id Ifeb277
a3ea1e45902b64b45e141ebae2f59b94e745d187

[!NOTE|label:references:]

integrate in Jenkins

[!NOTE|label:references:]

  • stream-events

    # permission requires
    $ ssh -i id_rsa jenkins@gerrit.domain.com -p 29418 gerrit stream-events
    stream events not permitted
    
    # verify
    $ ssh -i id_rsa jenkins@gerrit.domain.com -p 29418 gerrit stream-events | jq -r .type
    ref-updated
    comment-added
  • build current patches only

    [!NOTE] Warning: The current implementation takes into account that 'Build Current Patches Only' with 'Abort new patch sets' and 'Abort patch sets with same topic' are enabled (see help for more).

  • generate ssh-key

    $ keyname='devops@jenkins'
    $ ssh-keygen -m PEM -t rsa -f ~/.ssh/${keyname} -C "${keyname}" -P '' -q

css for code block

.gr-formatted-text-0 gr-linked-text.pre.gr-formatted-text,
gr-linked-text[class*="pre"], gr-linked-text[class*="pre"] #output {
  font-family: "Comic Mono", "Monaco", "Menlo", "Andale Mono", "Ubuntu Mono", "monofur" !important;
  font-size: 16px !important;
}
.gr-formatted-text-0 gr-linked-text.pre.gr-formatted-text,
gr-linked-text[class*="pre"] {
  color: #c8c8c8 !important;
  background: #272727 !important;
  border-radius: .75em !important;
  box-shadow: 0 4px 8px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%);
  overflow: auto;
  display: block;
  padding: 12px 12px 1px 12px;
  margin: 0px;
}
  • gruvbox

    • background : #272727

    • front-color: #e8dbb6

  • ubunut

    • background : #3a122e

    • front-color: #eee

  • solarized

    • background : #0d2a34

    • front-color: #869395

Last updated