@@ -13,17 +13,9 @@ OR adding an entry like the following to `~/.netrc`:
1313 machine github.com
1414 password ghp_E7ln0tAR34LtoK3nIsw34RyTve2moM3BvK
1515 ```
16-
17-
18- Usage:
19- build-integration-branch <label> [--no-date]
20- build-integration-branch -h | --help
21-
22- Options:
23- -h --help Show this screen.
24- --no-date Don't add `{postfix}` to the branch name.
2516"""
2617
18+ import argparse
2719import json
2820import os
2921import requests
@@ -35,107 +27,167 @@ from subprocess import call, check_output
3527from urllib .parse import urljoin
3628
3729TIME_FORMAT = '%Y-%m-%d-%H%M'
38- postfix = "-" + time .strftime (TIME_FORMAT , time .localtime ())
39-
40- current_branch = check_output ('git rev-parse --abbrev-ref HEAD' ,
41- shell = True ).strip ().decode ()
42- if current_branch in 'mimic nautilus octopus pacific quincy reef squid tentacle' .split ():
43- postfix += '-' + current_branch
44- print (f"Adding current branch name '-{ current_branch } ' as a postfix" )
45-
46- repo = "ceph/ceph"
47-
48- try :
49- from docopt import docopt
50- arguments = docopt (__doc__ .format (postfix = postfix ))
51- label = arguments ['<label>' ]
52- branch = label
53- if not arguments ['--no-date' ]:
54- branch += postfix
55- except ImportError :
56- # Fallback without docopt.
57- label = sys .argv [1 ]
58- assert len (sys .argv ) == 2
59- branch = label + postfix
60-
61- token = ''
62- try :
63- nrc = netrc .netrc ()
64- nrauth = nrc .authenticators ("api.github.com" )
65- if nrauth :
66- token = nrauth [2 ]
67- if not token :
68- nrauth = nrc .authenticators ("github.com" )
30+ CODENAMES = 'mimic nautilus octopus pacific quincy reef squid tentacle'
31+ REPO = "ceph/ceph"
32+
33+
34+ def get_postfix ():
35+ postfix = "-" + time .strftime (TIME_FORMAT , time .localtime ())
36+ current_branch = (
37+ check_output ('git rev-parse --abbrev-ref HEAD' , shell = True )
38+ .strip ()
39+ .decode ()
40+ )
41+ if current_branch in CODENAMES .split ():
42+ postfix += '-' + current_branch
43+ print (f"Adding current branch name '-{ current_branch } ' as a postfix" )
44+ return postfix
45+
46+
47+ def parse_args ():
48+ parser = argparse .ArgumentParser (usage = __doc__ )
49+ parser .add_argument (
50+ "--no-date" ,
51+ "--no-postfix" ,
52+ action = "store_true" ,
53+ help = "Don't add `{postfix}` to the branch name." ,
54+ )
55+ parser .add_argument (
56+ "--trailer" ,
57+ action = "append" ,
58+ dest = 'trailers' ,
59+ help = "Allow user to set arbitrary git trailers on final commit." ,
60+ )
61+ parser .add_argument (
62+ '--ceph-build-job' ,
63+ action = "append" ,
64+ dest = 'trailers' ,
65+ type = lambda v : f'CEPH-BUILD-JOB:{ v } ' ,
66+ help = "Set CEPH-BUILD-JOB trailer on final commit." ,
67+ )
68+ parser .add_argument (
69+ '--distros' ,
70+ action = "append" ,
71+ dest = 'trailers' ,
72+ type = lambda v : f'DISTROS:{ v } ' ,
73+ help = "Set DISTROS trailer on final commit." ,
74+ )
75+ parser .add_argument (
76+ '--archs' ,
77+ action = "append" ,
78+ dest = 'trailers' ,
79+ type = lambda v : f'ARCHS:{ v } ' ,
80+ help = "Set DISTROS trailer on final commit." ,
81+ )
82+ parser .add_argument (
83+ "--repo" ,
84+ default = REPO ,
85+ help = "GitHub repository (in `<org>/<name>` form)" ,
86+ )
87+ parser .add_argument (
88+ "label" ,
89+ help = "GitHub label to search for" ,
90+ )
91+ return parser .parse_args ()
92+
93+
94+ def main ():
95+ cli = parse_args ()
96+ if cli .no_date :
97+ branch = cli .label
98+ else :
99+ branch = cli .label + get_postfix ()
100+ label = cli .label
101+ repo = cli .repo
102+
103+ token = ''
104+ try :
105+ nrc = netrc .netrc ()
106+ nrauth = nrc .authenticators ("api.github.com" )
69107 if nrauth :
70108 token = nrauth [2 ]
71- except FileNotFoundError :
72- pass
73- if not token :
74- try :
75- with open (os .path .expanduser ('~/.github_token' )) as myfile :
76- token = myfile .readline ().strip ()
109+ if not token :
110+ nrauth = nrc .authenticators ("github.com" )
111+ if nrauth :
112+ token = nrauth [2 ]
77113 except FileNotFoundError :
78114 pass
79- if not token :
80- print ('No github api access token found' )
81- print (' Add a token to .netrc for [api.]github.com' )
82- print (' OR add a token to $HOME/.github_token' )
83-
84- # get prs
85- baseurl = urljoin ('https://api.github.com' ,
86- ('repos/{repo}/issues?labels={label}'
87- '&sort=created'
88- '&direction=asc' ))
89- url = baseurl .format (label = label ,
90- repo = repo )
91- r = requests .get (url ,
92- headers = {'Authorization' : 'token %s' % token })
93- if not r .ok :
94- print ("Failed to access github api" )
95- print ("(Do you have a valid, unexpired github api token?)" )
96- sys .exit (1 )
97-
98- j = json .loads (r .text or r .content )
99- print ("--- found %d issues tagged with %s" % (len (j ), label ))
100-
101- prs = []
102- prtext = []
103- for issue in j :
104- if 'pull_request' not in issue :
105- continue
106- r = requests .get (issue ['pull_request' ]['url' ],
115+ if not token :
116+ try :
117+ with open (os .path .expanduser ('~/.github_token' )) as myfile :
118+ token = myfile .readline ().strip ()
119+ except FileNotFoundError :
120+ pass
121+ if not token :
122+ print ('No github api access token found' )
123+ print (' Add a token to .netrc for [api.]github.com' )
124+ print (' OR add a token to $HOME/.github_token' )
125+
126+ # get prs
127+ baseurl = urljoin ('https://api.github.com' ,
128+ ('repos/{repo}/issues?labels={label}'
129+ '&sort=created'
130+ '&direction=asc' ))
131+ url = baseurl .format (label = label ,
132+ repo = repo )
133+ r = requests .get (url ,
107134 headers = {'Authorization' : 'token %s' % token })
108- pr = json .loads (r .text or r .content )
109- prs .append (pr )
110- prtext .append (pr ['html_url' ] + ' - ' + pr ['title' ])
111- print ("--- queried %s prs" % len (prs ))
112-
113- print ("branch %s" % branch )
114-
115- # assemble
116- print ('--- creating branch %s' % branch )
117- r = call (['git' , 'branch' , '-D' , branch ])
118- r = call (['git' , 'checkout' , '-b' , branch ])
119- assert not r
120- for pr in prs :
121- pr_number = pr ['number' ]
122- pr_url = pr ['head' ]['repo' ]['clone_url' ]
123- pr_ref = pr ['head' ]['ref' ]
124- print (f'--- pr { pr_number } --- pulling { pr_url } branch { pr_ref } ' )
125- while True :
126- r = call (['git' , 'pull' , '--no-ff' , '--no-edit' , pr_url , pr_ref ])
127- if r == 0 :
128- break
129- elif r == 1 :
130- print (f'Unable to access { pr_url } , retrying..' )
131- elif r == 128 :
132- message = f'Unable to resolve conflict when merging PR#{ pr_number } '
133- raise Exception (message )
134- else :
135- message = ('Exiting due to an unknown failure when pulling '
136- f'PR#{ pr_number } ' )
137- raise Exception (message )
138-
139- print ('--- done. these PRs were included:' )
140- print ('\n ' .join (prtext ).encode ('ascii' , errors = 'ignore' ).decode ())
141- print ('--- perhaps you want to: ./run-make-check.sh && git push ci %s' % branch )
135+ if not r .ok :
136+ print ("Failed to access github api" )
137+ print ("(Do you have a valid, unexpired github api token?)" )
138+ sys .exit (1 )
139+
140+ j = json .loads (r .text or r .content )
141+ print ("--- found %d issues tagged with %s" % (len (j ), label ))
142+
143+ prs = []
144+ prtext = []
145+ for issue in j :
146+ if 'pull_request' not in issue :
147+ continue
148+ r = requests .get (issue ['pull_request' ]['url' ],
149+ headers = {'Authorization' : 'token %s' % token })
150+ pr = json .loads (r .text or r .content )
151+ prs .append (pr )
152+ prtext .append (pr ['html_url' ] + ' - ' + pr ['title' ])
153+ print ("--- queried %s prs" % len (prs ))
154+
155+ print ("branch %s" % branch )
156+
157+ # assemble
158+ print ('--- creating branch %s' % branch )
159+ r = call (['git' , 'branch' , '-D' , branch ])
160+ r = call (['git' , 'checkout' , '-b' , branch ])
161+ assert not r
162+ for pr in prs :
163+ pr_number = pr ['number' ]
164+ pr_url = pr ['head' ]['repo' ]['clone_url' ]
165+ pr_ref = pr ['head' ]['ref' ]
166+ print (f'--- pr { pr_number } --- pulling { pr_url } branch { pr_ref } ' )
167+ while True :
168+ r = call (['git' , 'pull' , '--no-ff' , '--no-edit' , pr_url , pr_ref ])
169+ if r == 0 :
170+ break
171+ elif r == 1 :
172+ print (f'Unable to access { pr_url } , retrying..' )
173+ elif r == 128 :
174+ message = f'Unable to resolve conflict when merging PR#{ pr_number } '
175+ raise Exception (message )
176+ else :
177+ message = ('Exiting due to an unknown failure when pulling '
178+ f'PR#{ pr_number } ' )
179+ raise Exception (message )
180+ if cli .trailers :
181+ cmd = ['git' , 'commit' , '--am' , '--no-edit' ]
182+ cmd .extend (f'--trailer={ t } ' for t in cli .trailers )
183+ if call (cmd ) != 0 :
184+ print ('Failed to set git trailers!' )
185+ sys .exit (1 )
186+
187+ print ('--- done. these PRs were included:' )
188+ print ('\n ' .join (prtext ).encode ('ascii' , errors = 'ignore' ).decode ())
189+ print ('--- perhaps you want to: ./run-make-check.sh && git push ci %s' % branch )
190+
191+
192+ if __name__ == '__main__' :
193+ main ()
0 commit comments