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 ##############################################################################
11 Create Gerrit Branches
22 from ruamel.yaml import YAML
25 logging.basicConfig(level=logging.INFO)
28 def has_string(filepath, string):
30 Return True if the given filepath contains the regex string
32 with open(filepath) as yaml_file:
33 for line in yaml_file:
34 if string.search(line):
39 def jjb_files(project, release):
41 Return sets of YAML file names that contain 'stream' for a given
42 project, and file that already contain the stream.
44 files, skipped = set(), set()
45 file_ending = re.compile(r'ya?ml$')
46 search_string = re.compile(r'^\s+stream:')
47 release_string = re.compile(r'- %s:' % release)
48 jjb_path = os.path.join('jjb', project)
50 if not os.path.isdir(jjb_path):
51 logging.warn("JJB directory does not exist at %s, skipping job "
53 return (files, skipped)
55 for file_name in os.listdir(jjb_path):
56 file_path = os.path.join(jjb_path, file_name)
57 if os.path.isfile(file_path) and file_ending.search(file_path):
58 if has_string(file_path, release_string):
59 skipped.add(file_path)
60 elif has_string(file_path, search_string):
62 return (files, skipped)
67 Create Jenkins Jobs for stable branches in Release File
69 parser = argparse.ArgumentParser()
70 parser.add_argument('--file', '-f',
71 type=argparse.FileType('r'),
73 args = parser.parse_args()
75 project_yaml = yaml.safe_load(args.file)
77 # Get the release name from the file path
78 release = os.path.split(os.path.dirname(args.file.name))[1]
80 create_jobs(release, project_yaml)
83 def create_jobs(release, project_yaml):
84 """Add YAML to JJB files for release stream"""
85 logger = logging.getLogger(__file__)
87 # We assume here project keep their subrepo jobs under the part
88 # project name. Otherwise we'll have to look for jjb/<repo> for each
90 project, _ = next(iter(project_yaml['branches'][0]['location'].items()))
93 yaml_parser.preserve_quotes = True
94 yaml_parser.explicit_start = True
95 # yaml_parser.indent(mapping=4, sequence=0, offset=0)
96 # These are some esoteric values that produce indentation matching our jjb
98 # yaml_parser.indent(mapping=3, sequence=3, offset=2)
99 # yaml_parser.indent(sequence=4, offset=2)
100 yaml_parser.indent(mapping=2, sequence=4, offset=2)
102 (job_files, skipped_files) = jjb_files(project, release)
105 logger.info("Jobs already exists for %s in files: %s",
106 project, ', '.join(skipped_files))
107 # Exit if there are not jobs to create
110 logger.info("Creating Jenkins Jobs for %s in files: %s",
111 project, ', '.join(job_files))
113 stable_branch_stream = """\
115 branch: 'stable/{stream}'
116 gs-pathname: '/{stream}'
120 stable_branch_yaml = yaml_parser.load(stable_branch_stream)
121 stable_branch_yaml[release].yaml_set_anchor(release, always_dump=True)
123 for job_file in job_files:
124 yaml_jjb = yaml_parser.load(open(job_file))
125 if 'stream' not in yaml_jjb[0]['project']:
128 # TODO: Some JJB files don't have 'stream'
129 project_config = yaml_jjb[0]['project']['stream']
130 # There is an odd issue where just appending adds a newline before the
131 # branch config, so we append (presumably after master) instead.
132 project_config.insert(1, stable_branch_yaml)
134 # NOTE: In the future, we may need to override one or multiple of the
135 # following ruamal Emitter methods:
136 # * ruamel.yaml.emitter.Emitter.expect_block_sequence_item
137 # * ruamel.yaml.emitter.Emitter.write_indent
138 # To hopefully replace the need to shell out to sed...
139 yaml_parser.dump(yaml_jjb, open(job_file, 'w'))
140 args = ['sed', '-i', 's/^ //', job_file]
141 subprocess.Popen(args, stdout=subprocess.PIPE, shell=False)
144 if __name__ == "__main__":