blob: f3541477adbc2f4574ea9ab77af20bda3c36c6eb [file] [log] [blame]
Paul Sokolovskyb1d86572015-03-05 22:48:18 +02001#!/usr/bin/python
2
3import os
4import shutil
5import signal
6import string
7import subprocess
8import sys
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +00009import xml.etree.ElementTree
Paul Sokolovskyb1d86572015-03-05 22:48:18 +020010from distutils.spawn import find_executable
11
Vishal Bhojafb87362016-08-22 19:31:08 +053012
13def findparentfiles(fname):
14 filelist = []
15 newlist = []
16 args = ['grep', '-rl', '--exclude-dir=.git', fname]
17 proc = subprocess.Popen(args,
18 stdin=subprocess.PIPE,
19 stdout=subprocess.PIPE,
20 universal_newlines=False,
21 preexec_fn=lambda:
22 signal.signal(signal.SIGPIPE, signal.SIG_DFL))
23 data = proc.communicate()[0]
24 if proc.returncode != 0:
25 return filelist
26 for filename in data.splitlines():
27 if filename.endswith('.yaml') and '/' not in filename:
28 filelist.append(filename)
29 else:
30 newlist = findparentfiles(filename)
31 for tempname in newlist:
32 filelist.append(tempname)
33 return filelist
34
35
Fathi Boudra340fc632017-04-06 12:30:46 +030036jjb_cmd = find_executable('jenkins-jobs') or sys.exit('jenkins-jobs is not found.')
Fathi Boudrac6fdc732017-04-07 14:56:54 +030037jjb_args = [jjb_cmd]
Fathi Boudraf25a3db2017-04-07 07:25:33 +030038
39jjb_user = os.environ.get('JJB_USER')
40jjb_password = os.environ.get('JJB_PASSWORD')
41if jjb_user is not None and jjb_password is not None:
42 jenkins_jobs_ini = ('[job_builder]\n'
43 'ignore_cache=True\n'
44 'keep_descriptions=False\n'
45 '\n'
46 '[jenkins]\n'
Fathi Boudraa85ff5f2017-04-07 10:16:50 +030047 'user=%s\n'
48 'password=%s\n'
49 'url=https://ci.linaro.org/\n' % (jjb_user, jjb_password))
Fathi Boudraf25a3db2017-04-07 07:25:33 +030050 with open('jenkins_jobs.ini', 'w') as f:
51 f.write(jenkins_jobs_ini)
Fathi Boudrac6fdc732017-04-07 14:56:54 +030052 jjb_args.append('--conf=jenkins_jobs.ini')
Fathi Boudraf25a3db2017-04-07 07:25:33 +030053
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +000054jjb_test_args = list(jjb_args)
55jjb_delete_args = list(jjb_args)
56
57# !!! "update" below and through out this file is replaced by "test" (using sed)
58# !!! in the sanity-check job.
59main_action = 'update'
60jjb_args.extend([main_action, 'template.yaml'])
61jjb_test_args.extend(['test', '-o', 'out/', 'template.yaml'])
62jjb_delete_args.extend(['delete'])
63
64if main_action == 'test':
65 # Dry-run, don't delete jobs.
66 jjb_delete_args.insert(0, 'echo')
Paul Sokolovskyb1d86572015-03-05 22:48:18 +020067
68try:
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +053069 git_args = ['git', 'diff', '--raw',
Fathi Boudrac6fdc732017-04-07 14:56:54 +030070 os.environ.get('GIT_PREVIOUS_COMMIT'),
71 os.environ.get('GIT_COMMIT')]
72 proc = subprocess.Popen(git_args,
Paul Sokolovskyb1d86572015-03-05 22:48:18 +020073 stdin=subprocess.PIPE,
74 stdout=subprocess.PIPE,
75 universal_newlines=False,
76 preexec_fn=lambda:
77 signal.signal(signal.SIGPIPE, signal.SIG_DFL))
78except (OSError, ValueError) as e:
79 raise ValueError("%s" % e)
80
81data = proc.communicate()[0]
82if proc.returncode != 0:
83 raise ValueError("command has failed with code '%s'" % proc.returncode)
84
Vishal Bhojafb87362016-08-22 19:31:08 +053085filelist = []
86files = []
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +053087for line in data.splitlines():
88 # Format of the git-diff; we only need OPERATION and FILE1
89 #
90 # :<OLD MODE> <NEW MODE> <OLD REF> <NEW REF> <OPERATION> <FILE1> <FILE2>
91 elems = line.split()
92 operation = elems[4][0]
93 filename = elems[5]
94
Vishal Bhojafb87362016-08-22 19:31:08 +053095 if filename.endswith('.yaml') and '/' not in filename:
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +053096 # No point trying to test deleted jobs because they don't exist any
97 # more.
98 if operation == 'D':
99 continue
Vishal Bhojafb87362016-08-22 19:31:08 +0530100 filelist.append(filename)
101 else:
102 files = findparentfiles(filename)
103 for tempname in files:
104 filelist.append(tempname)
105
Riku Voipioc0e6b132019-06-27 13:52:04 +0300106# Remove duplicate entries in the list
Vishal Bhojafb87362016-08-22 19:31:08 +0530107filelist = list(set(filelist))
108
109for conf_filename in filelist:
110 with open(conf_filename) as f:
111 buffer = f.read()
112 template = string.Template(buffer)
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200113 buffer = template.safe_substitute(
Fathi Boudrafdd9f212015-04-18 19:28:55 +0300114 AUTH_TOKEN=os.environ.get('AUTH_TOKEN'),
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200115 LT_QCOM_KEY=os.environ.get('LT_QCOM_KEY'),
116 LAVA_USER=os.environ.get('LAVA_USER'),
117 LAVA_TOKEN=os.environ.get('LAVA_TOKEN'))
118 with open('template.yaml', 'w') as f:
119 f.write(buffer)
120 try:
Fathi Boudrac6fdc732017-04-07 14:56:54 +0300121 proc = subprocess.Popen(jjb_args,
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200122 stdin=subprocess.PIPE,
123 stdout=subprocess.PIPE,
124 universal_newlines=False,
125 preexec_fn=lambda:
126 signal.signal(signal.SIGPIPE, signal.SIG_DFL))
127 except (OSError, ValueError) as e:
128 raise ValueError("%s" % e)
129
130 data = proc.communicate()[0]
131 if proc.returncode != 0:
132 raise ValueError("command has failed with code '%s'" % proc.returncode)
133
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +0000134 try:
135 shutil.rmtree('out/', ignore_errors=True)
136
137 proc = subprocess.Popen(jjb_test_args,
138 stdin=subprocess.PIPE,
139 stdout=subprocess.PIPE,
140 universal_newlines=False,
141 preexec_fn=lambda:
142 signal.signal(signal.SIGPIPE, signal.SIG_DFL))
143 data = proc.communicate()[0]
144 if proc.returncode != 0:
145 raise ValueError("command has failed with code '%s'" % proc.returncode)
146
147 proc = subprocess.Popen(['ls', 'out/'],
148 stdin=subprocess.PIPE,
149 stdout=subprocess.PIPE,
150 universal_newlines=False,
151 preexec_fn=lambda:
152 signal.signal(signal.SIGPIPE, signal.SIG_DFL))
153 data = proc.communicate()[0]
154 if proc.returncode != 0:
155 raise ValueError("command has failed with code '%s'" % proc.returncode)
156
157 for filename in data.splitlines():
Riku Voipioc0e6b132019-06-27 13:52:04 +0300158 conf_name=os.path.splitext(conf_filename)[0]
159 if not filename.startswith(conf_name):
160 raise ValueError("Job name %s does not match the file it is in: %s" % (filename, conf_name))
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +0000161 try:
162 xmlroot = xml.etree.ElementTree.parse('out/' + filename).getroot()
163 disabled = next(xmlroot.iterfind('disabled')).text
164 if disabled != 'true':
165 continue
166 displayName = next(xmlroot.iterfind('displayName')).text
167 if displayName != 'DELETE ME':
168 continue
169 except:
170 continue
171
172 delete_args = list(jjb_delete_args)
173 delete_args.extend([filename])
174 proc = subprocess.Popen(delete_args,
175 stdin=subprocess.PIPE,
176 stdout=subprocess.PIPE,
177 universal_newlines=False,
178 preexec_fn=lambda:
179 signal.signal(signal.SIGPIPE, signal.SIG_DFL))
180 data = proc.communicate()[0]
181 if proc.returncode != 0:
182 raise ValueError("command has failed with code '%s'" % proc.returncode)
183 print data
184 except (OSError, ValueError) as e:
185 raise ValueError("%s" % e)
186
187 shutil.rmtree('out/', ignore_errors=True)
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200188 os.remove('template.yaml')
Fathi Boudraf25a3db2017-04-07 07:25:33 +0300189
190if os.path.exists('jenkins_jobs.ini'):
191 os.remove('jenkins_jobs.ini')