[!NOTE|label:references:]
.gitconfig
Copy $ git config --global gitreview.username < UserNam e >
$ git config --global gitreview.remote origin
[!TIP]
Special references
Magic references
get project.config
clone the repo
Copy $ git clone < repo ur l >
# or update the local repo to HEAD
$ git pull [--rebase]
checkout meta/config
Copy $ git fetch origin refs/meta/config:refs/remotes/origin/meta/config
$ git checkout meta/config
or
Copy $ git fetch ssh://localhost:29418/project refs/meta/config
$ git checkout FETCH_HEAD
publish to remote
Copy $ git add --all .
$ git commit -m "<add your comments here>"
submit directly
Copy $ git push origin meta/config:meta/config
or
Copy $ git push origin HEAD:refs/meta/config
submit review
[!NOTE|label:references:]
Copy $ git push origin HEAD:refs/for/refs/meta/config
or
Copy $ git push origin meta/config:refs/for/refs/meta/config
update meta/config if remotes update
Copy $ 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
Copy $ git fetch origin --force refs/meta/config:refs/remotes/origin/meta/config
$ git reset --hard remotes/origin/meta/config
useful refs
sandbox:
Copy refs/heads/sandbox/$ {username} /*
its-jira:
for project specific
Copy [commentlink "its-jira" ]
match = ^[ \\ t]*PROJECT- ([0-9]{ 1,5} ) :
link = https:// < jira-domai n > : < jira-por t > /browse/PROJECT- $1
for common setup
Copy [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-domai n > : < jira-por t > /browse/ $1
[commentlink "changeid" ]
match = (I[0-9a-f]{ 8,40} )
link = "#/q/$1"
verified label
Copy [label "Verified" ]
function = MaxWithBlock
defaultValue = 0
copyAllScoresIfNoCodeChange = true
value = -1 Fails
value = 0 No score
value = +1 Verified
change-id
Copy [receive]
requireChangeId = true
createNewChangeForAllNotInTarget = false
maxObjectSizeLimit = 6m
maxBatchChanges = 1
[commentlink "changeid" ]
match = (I[0-9a-f]{ 8,40} )
link = "#/q/$1"
freeze master
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
Copy [access "refs/for/refs/heads/master" ]
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
Copy ...
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
Copy [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
Copy [access "^refs/heads/backup/(master|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/(master|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
Copy ...
global:Project-Owners Project Owners
global:Registered-Users Registered Users
...
user:marslo user/Marslo Jiao ( marslo )
...
restriction for branches (feature1
, feature2
and master
) for only allow code review merge, forbidden code push
project.config
Copy [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|master)$" ]
push = block group Registered Users
pushMerge = block group Registered Users
submit = group Change Owner
groups
Copy ...
global:Project-Owners Project Owners
global:Registered-Users Registered Users
...
user:marslo user/Marslo Jiao ( marslo )
...
example of project.config
project.config
Copy [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
[!TIP] check also:
Copy 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
Copy [access "refs/*"]
label-Code-Review = block -2..+2 group Change Owner
exclusiveGroupPermissions = label-Code-Review
[!TIP] check also:
optional validation
Copy 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
Copy 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
Copy 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]).
api
regular options
Copy a might means [a]pi
⇡
$ curl -X PUT http://domain.name/a/path/to/api/
$ curl -X POST http://domain.name/a/path/to/api/
$ curl -X DELETE http://domain.name/a/path/to/api/
sending data
json with file
Copy $ curl -X PUT \
-d@testdata.json \
--header "Content-Type: application/json" \
http://domain.name/a/path/to/api/
json with string
Copy $ curl -X POST \
-H "Content-Type: application/json" https://domain.name/a/changes/ < numbe r > /move \
-d '{ "destination_branch" : "target/branch/name" }'
)]}'
{
"id" : "marslo-project~target%2Fbranch%2Fname~Id90057ab632eb93be2fa9128a9d624664008cb4a" ,
"project" : "marslo-project" ,
"branch" : "target/branch/name" ,
"hashtags" : [],
"change_id" : "Id90057ab632eb93be2fa9128a9d624664008cb4a" ,
"subject" : "marslo: testing api move" ,
"status" : "NEW" ,
"created" : "2022-01-21 05:21:25.000000000" ,
"updated" : "2022-05-17 06:56:37.000000000" ,
"submit_type" : "FAST_FORWARD_ONLY" ,
"mergeable" : false ,
"insertions" : 8,
"deletions" : 8,
"unresolved_comment_count" : 0,
"has_review_started" : true ,
"_number" : 94490,
"owner" : {
"_account_id" : 790
},
"requirements" : []
}
# or
$ curl -X POST \
-H "Content-Type: application/json" https://domain.name/a/changes/ < numbe r > /move \
-d '{
"destination_branch" : "target/branch/name"
}' |
tail -n +2 |
jq -r .branch
txt
Copy $ curl -X PUT \
--data-binary @testdata.txt \
--header "Content-Type: text/plain" \
http://domain.name/a/path/to/api/
verifying header content
Copy $ curl -v -n -X DELETE http://domain.name/a/path/to/api/
get change via change-id
Copy $ curl -X GET 'https://domina.name/a/changes/<change-id>'
get change via commit-id
Copy $ changeid = $(git show < commit - id > -- no - patch -- format = "%s%n%n%b" | sed - nre 's!Change-Id: (.*$)!\1!p' )
$ curl - X GET "https://domina.name/a/changes/${changeid}"
or
Copy $ project= $( echo 'path/to/project' | sed 's:/:%2F:g' )
$ branch= 'dev'
$ changeid= $( git show < commit-i d > --no-patch --format= "%s%n%n%b" | sed -nre 's!Change-Id: (.*$)!\1!p' )
$ curl -X GET "https://domina.name/a/changes/${project}~${branch}~${changeid}"
who approval the CR+2
Copy $ curl -s -X GET https://domain.name/a/changes/ ${changeid} /detail |
tail -n +2 |
jq -r '.labels."Code-Review".approved.name'
get all vote CR-2
example output for .labels.<tag>.all[]
Copy {
"value" : -2 ,
"date" : "2021-05-31 07:57:14.000000000" ,
"permitted_voting_range" : {
"min" : -2 ,
"max" : 2
} ,
"_account_id" : 790 ,
"name" : "Marslo Jiao" ,
"email" : "marslo.jiao@gmail.com" ,
"username" : "marslo"
}
{
"value" : 0 ,
"permitted_voting_range" : {
"min" : -2 ,
"max" : 2
} ,
"_account_id" : 124 ,
"name" : "John Doe" ,
"email" : "john@gmail.com" ,
"username" : "john"
}
reference:
Copy $ curl -s -X GET https://domain.name/a/changes/ ${changeid} /detail |
tail -n +2 |
jq -r '.labels."Code-Review".all[] | select ( .value == -2 ) | .username'
# : |⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂⠂| :
# : ⇣ :
# : select ".value"== -2 :
# : :
# ⇣ ⇣
# pipe pipe
# or
$ curl -s -X GET https://domain.name/a/changes/ ${changeid} /detail |
tail -n +2 |
jq -r '( .labels."Code-Review".all[] | select ( .value == -2 ) ).username'
: :
⇣ ⇣
expression expression
# or
$ curl -s -X GET https://domain.name/a/changes/ ${changeid} /detail |
tail -n +2 |
jq -r '[ .labels."Code-Review".all[] | select ( .value == -2 ) ][].username'
: :
⇣ ⇣
expression expression
# or
$ curl -s -X GET https://domain.name/a/changes/ ${changeid} /detail |
tail -n +2 |
jq -r '.labels."Code-Review".all[] | select ( .value == -2 )' |
jq -r .username :
⇣
pipe
who approval the V+1
Copy $ curl -s -X GET https://domain.name/a/changes/ ${changeid} /detail |
tail -n +2 |
jq -r .labels.Verified.approved.username
access list contains account
[!NOTE]
Copy # i.e. : check all repos who contains account marslo@sample.com
$ while read -r _proj ; do
output = $( curl -fsSL https://gerrit.sample.com/a/projects/ "${_proj}" /access |
tail -n+2 |
jq -r '.. | .rules? | select(. != null) | keys[] | ascii_downcase | select(contains("marslo@sample.com"))';
)
[[ -z "${output}" ]] || echo ">> https://gerrit.sample.com/admin/repos/$( sed 's:%2F:/:g' <<< "${_proj}")"
done < <( curl -fsSL https://gerrit.sample.com/a/projects/?d |
tail -n+2 |
jq -r '.[].id' |
grep --color=never -E 'keyword|keyword'
)
all reviews at a certain time
[!NOTE|label:references:]
Copy project = 'PROJECT'
branch = 'BRANCH'
start = '2023-01-01'
end = '2024-01-01'
curlOpt = '--silent --insecure --globoff --netrc-file ~/.netrc'
query = "project:${project}+branch:${branch}+after:${start}+before:${end}"
filter by status if necessary
query = "${query}+is:closed+-is:abandoned"
echo ">> ${project} ~ ${branch}"
while IFS = '|' read -r _change_id _id ; do
echo -e "\t- [${_id}] [_change_id]"
$( eval "curl ${curlOpt} 'https://gerrit.sample.com/a/changes/?q=${query}'" |
tail -n +2 |
jq -r '.[] | .change_id + "|" + .id'
)
get review rate in certain time
Copy sum = 0
rnum = 0
onum = 0
echo ">> ${project} ~ ${branch}"
while IFS = '|' read -r _change_id _id ; do
sum = $(( sum+1 ))
output = $( eval "curl ${curlOpt} 'https://gerrit.sample.com/a/changes/${_id}/detail' | tail -n+2" )
reviewed=$( jq -r '.labels."Code-Review".all[] | select(.value != null) | select( .value | contains(2) ) | .username' <<< "${output}" )
owned = $( jq -r '.owner.username' <<< "${output}" )
if grep 'marslo' <<< "${reviewed}" > /dev/null ; then rnum = $(( rnum+1 )); fi
if grep 'marslo' <<< "${owned}" > /dev/null ; then onum = $(( onum+1 )); fi
$( eval "curl ${curlOpt} 'https://gerrit.sample.com/a/changes/?q=${query}'" |
tail -n +2 |
jq -r '.[] | .change_id + "|" + .id'
)
echo "${sum} ${rnum} ${onum} $(( sum-onum ))" |
awk '{ sum=$1; reviewed=$2; owned=$3; rsum=$4; rate=$2*100/$4 } END { printf("\t- gerrit review: %s/(%s-%s) ( %s% )\n", reviewed, sum, owned, rate) }'
list gerrit projects with certain account
Copy $ account= 'marslo'
$ id= 1
$ gerritUrl= 'https://gerrit.sample.com'
$ while read -r _proj ; do
output = $( curl -fsSL "${gerritUrl}" /a/projects/ "${_proj}" /access |
tail -n+2 |
jq -r --arg ACCOUNT "${account}" '.. | ."rules"? | select(. != null) | keys[] | ascii_downcase | select(contains($ACCOUNT))';
)
[[ -n "${output}" ]] && echo "[${id}] >> " ${gerritUrl} "/admin/repos/$( sed 's:%2F:/:g' <<< "${_proj}")" && ((id ++ ));
done < <( curl -fsSL "${gerritUrl}" /a/projects/?d | tail -n+2 | jq -r '.[].id' )
reference
integrate in Jenkins
[!NOTE|label:references:]
stream-events
Copy # 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
Copy $ keyname= 'devops@jenkins'
$ ssh-keygen -m PEM -t rsa -f ~/.ssh/ ${keyname} -C "${keyname}" -P '' -q
css for code block
Copy .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 : 16 px !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 : .75 em !important ;
box-shadow : 0 4 px 8 px 0 rgb (0 0 0 / 20 % ) , 0 6 px 20 px 0 rgb (0 0 0 / 19 % ) ;
overflow : auto ;
display : block ;
padding : 12 px 12 px 1 px 12 px ;
margin : 0 px ;
}
Last updated 4 months ago