Merge "xci: Record additional promotion metadata for further use"
[releng.git] / releases / scripts / create_branch.py
1 #!/usr/bin/env python2
2 # SPDX-License-Identifier: Apache-2.0
3 ##############################################################################
4 # Copyright (c) 2018 The Linux Foundation and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
10 """
11 Create Gerrit Branchs
12 """
13
14 import argparse
15
16 try:
17     import ConfigParser
18 except ImportError:
19     import configparser as ConfigParser
20
21 import logging
22 import os
23 import yaml
24
25 from requests.compat import quote
26 from requests.exceptions import RequestException
27
28 from pygerrit2.rest import GerritRestAPI
29 from pygerrit2.rest.auth import HTTPDigestAuthFromNetrc, HTTPBasicAuthFromNetrc
30
31
32 logging.basicConfig(level=logging.INFO)
33
34
35 def quote_branch(arguments):
36     """
37     Quote is used here to escape the '/' in branch name. By
38     default '/' is listed in 'safe' characters which aren't escaped.
39     quote is not used in the data of the PUT request, as quoting for
40     arguments is handled by the request library
41     """
42     new_args = arguments.copy()
43     new_args['branch'] = quote(new_args['branch'], '')
44     return new_args
45
46
47 def create_branch(api, arguments):
48     """
49     Create a branch using the Gerrit REST API
50     """
51     logger = logging.getLogger(__file__)
52
53     branch_data = """
54     {
55       "ref": "%(branch)s"
56       "revision": "%(commit)s"
57     }""" % arguments
58
59     # First verify the commit exists, otherwise the branch will be
60     # created at HEAD
61     try:
62         request = api.get("/projects/%(project)s/commits/%(commit)s" %
63                           arguments)
64         logger.debug(request)
65         logger.debug("Commit exists: %(commit)s", arguments)
66     except RequestException as err:
67         if hasattr(err, 'response') and err.response.status_code in [404]:
68             logger.warn("Commit %(commit)s for %(project)s:%(branch)s does"
69                         " not exist. Not creating branch.", arguments)
70         else:
71             logger.error("Error: %s", str(err))
72         # Skip trying to create the branch
73         return
74
75     # Try to create the branch and let us know if it already exist.
76     try:
77         request = api.put("/projects/%(project)s/branches/%(branch)s" %
78                           quote_branch(arguments), branch_data)
79         logger.info("Branch %(branch)s for %(project)s successfully created",
80                     arguments)
81     except RequestException as err:
82         if hasattr(err, 'response') and err.response.status_code in [412, 409]:
83             logger.info("Branch %(branch)s already created for %(project)s",
84                         arguments)
85         else:
86             logger.error("Error: %s", str(err))
87
88
89 def main():
90     """Given a yamlfile that follows the release syntax, create branches
91     in Gerrit listed under branches"""
92
93     config = ConfigParser.ConfigParser()
94     config.read(os.path.join(os.path.abspath(os.path.dirname(__file__)),
95                 'defaults.cfg'))
96     config.read([os.path.expanduser('~/releases.cfg'), 'releases.cfg'])
97
98     gerrit_url = config.get('gerrit', 'url')
99
100     parser = argparse.ArgumentParser()
101     parser.add_argument('--file', '-f',
102                         type=argparse.FileType('r'),
103                         required=True)
104     parser.add_argument('--basicauth', '-b', action='store_true')
105     args = parser.parse_args()
106
107     GerritAuth = HTTPDigestAuthFromNetrc
108     if args.basicauth:
109         GerritAuth = HTTPBasicAuthFromNetrc
110
111     try:
112         auth = GerritAuth(url=gerrit_url)
113     except ValueError as err:
114         logging.error("%s for %s", err, gerrit_url)
115         quit(1)
116     restapi = GerritRestAPI(url=gerrit_url, auth=auth)
117
118     project = yaml.safe_load(args.file)
119
120     create_branches(restapi, project)
121
122
123 def create_branches(restapi, project):
124     """Create branches for a specific project defined in the release
125     file"""
126
127     branches = []
128     for branch in project['branches']:
129         repo, ref = next(iter(branch['location'].items()))
130         branches.append({
131             'project': repo,
132             'branch': branch['name'],
133             'commit': ref
134         })
135
136     for branch in branches:
137         create_branch(restapi, branch)
138
139
140 if __name__ == "__main__":
141     main()