blob: 62b200b1d6d8d8bdf0086f0270bb304b821f1859 [file] [log] [blame]
Riku Voipiob866d3c2021-10-25 10:23:07 +03001#!/usr/bin/python3
Paul Sokolovskyb1d86572015-03-05 22:48:18 +02002
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
Kelley Spoone1e1f382022-06-23 07:53:05 -050013# provide a convenience wrapper for running a command. If command
14# fails for any reason, it should raise a ValueError and let caller
15# handle it
Kelley Spoon9c6be152022-06-27 08:05:16 -050016def safe_run(args, check=True):
Kelley Spoone1e1f382022-06-23 07:53:05 -050017 try:
18 proc = subprocess.run(
19 args,
20 stdout=subprocess.PIPE,
21 stderr=subprocess.STDOUT,
Kelley Spoon9c6be152022-06-27 08:05:16 -050022 check=check)
Kelley Spoone1e1f382022-06-23 07:53:05 -050023 except(OSError, ValueError) as e:
24 raise ValueError("command '%s' failed: %s" % (" ".join(args), e))
25 except(subprocess.CalledProcessError) as e:
26 raise ValueError("command '%s' failed with %s:\n%s" % (
27 e.cmd, e.returncode, e.output.decode()))
28 except(Exception) as e:
29 raise ValueError("unknown error running command '%s':\n%s" %
30 (" ".join(args), e))
31
32 return proc
33
34
Vishal Bhojafb87362016-08-22 19:31:08 +053035def findparentfiles(fname):
36 filelist = []
37 newlist = []
38 args = ['grep', '-rl', '--exclude-dir=.git', fname]
Kelley Spoone1e1f382022-06-23 07:53:05 -050039
Kelley Spoon9c6be152022-06-27 08:05:16 -050040 # Set False for the check argument to subprocess run... we don't care
41 # if grep doesn't find any files
42 proc = safe_run(args, False)
Riku Voipiob866d3c2021-10-25 10:23:07 +030043 data = proc.stdout.decode()
Kelley Spoone1e1f382022-06-23 07:53:05 -050044
Vishal Bhojafb87362016-08-22 19:31:08 +053045 for filename in data.splitlines():
46 if filename.endswith('.yaml') and '/' not in filename:
47 filelist.append(filename)
48 else:
49 newlist = findparentfiles(filename)
50 for tempname in newlist:
51 filelist.append(tempname)
52 return filelist
53
54
Fathi Boudra340fc632017-04-06 12:30:46 +030055jjb_cmd = find_executable('jenkins-jobs') or sys.exit('jenkins-jobs is not found.')
Fathi Boudrac6fdc732017-04-07 14:56:54 +030056jjb_args = [jjb_cmd]
Fathi Boudraf25a3db2017-04-07 07:25:33 +030057
58jjb_user = os.environ.get('JJB_USER')
59jjb_password = os.environ.get('JJB_PASSWORD')
60if jjb_user is not None and jjb_password is not None:
61 jenkins_jobs_ini = ('[job_builder]\n'
62 'ignore_cache=True\n'
63 'keep_descriptions=False\n'
64 '\n'
65 '[jenkins]\n'
Fathi Boudraa85ff5f2017-04-07 10:16:50 +030066 'user=%s\n'
67 'password=%s\n'
68 'url=https://ci.linaro.org/\n' % (jjb_user, jjb_password))
Fathi Boudraf25a3db2017-04-07 07:25:33 +030069 with open('jenkins_jobs.ini', 'w') as f:
70 f.write(jenkins_jobs_ini)
Fathi Boudrac6fdc732017-04-07 14:56:54 +030071 jjb_args.append('--conf=jenkins_jobs.ini')
Fathi Boudraf25a3db2017-04-07 07:25:33 +030072
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +000073jjb_test_args = list(jjb_args)
74jjb_delete_args = list(jjb_args)
75
76# !!! "update" below and through out this file is replaced by "test" (using sed)
77# !!! in the sanity-check job.
78main_action = 'update'
79jjb_args.extend([main_action, 'template.yaml'])
80jjb_test_args.extend(['test', '-o', 'out/', 'template.yaml'])
81jjb_delete_args.extend(['delete'])
82
83if main_action == 'test':
84 # Dry-run, don't delete jobs.
85 jjb_delete_args.insert(0, 'echo')
Paul Sokolovskyb1d86572015-03-05 22:48:18 +020086
87try:
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +053088 git_args = ['git', 'diff', '--raw',
Fathi Boudrac6fdc732017-04-07 14:56:54 +030089 os.environ.get('GIT_PREVIOUS_COMMIT'),
90 os.environ.get('GIT_COMMIT')]
Kelley Spoone1e1f382022-06-23 07:53:05 -050091 proc = safe_run(git_args)
92 data = proc.stdout.decode()
93except (ValueError) as e:
Paul Sokolovskyb1d86572015-03-05 22:48:18 +020094 raise ValueError("%s" % e)
95
Vishal Bhojafb87362016-08-22 19:31:08 +053096filelist = []
Riku Voipio2ad62762020-06-16 13:32:52 +030097deletelist = []
Vishal Bhojafb87362016-08-22 19:31:08 +053098files = []
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +053099for line in data.splitlines():
100 # Format of the git-diff; we only need OPERATION and FILE1
101 #
102 # :<OLD MODE> <NEW MODE> <OLD REF> <NEW REF> <OPERATION> <FILE1> <FILE2>
103 elems = line.split()
104 operation = elems[4][0]
105 filename = elems[5]
106
Vishal Bhojafb87362016-08-22 19:31:08 +0530107 if filename.endswith('.yaml') and '/' not in filename:
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +0530108 # No point trying to test deleted jobs because they don't exist any
109 # more.
110 if operation == 'D':
Riku Voipio2ad62762020-06-16 13:32:52 +0300111 deletelist.append(filename[:-5])
Siddhesh Poyarekar8d25b3d2019-08-08 19:42:21 +0530112 continue
Riku Voipioa23bc402019-09-16 16:38:18 +0300113 # operation R100 is 100% rename, which means sixth element is the renamed file
114 if operation == 'R':
115 filename = elems[6]
Dmitry Baryshkovf30653b2021-01-13 13:38:31 +0300116 # delete old job name
117 deletelist.append(elems[5][:-5])
Vishal Bhojafb87362016-08-22 19:31:08 +0530118 filelist.append(filename)
119 else:
120 files = findparentfiles(filename)
121 for tempname in files:
122 filelist.append(tempname)
123
Riku Voipioc0e6b132019-06-27 13:52:04 +0300124# Remove duplicate entries in the list
Vishal Bhojafb87362016-08-22 19:31:08 +0530125filelist = list(set(filelist))
126
127for conf_filename in filelist:
128 with open(conf_filename) as f:
129 buffer = f.read()
130 template = string.Template(buffer)
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200131 buffer = template.safe_substitute(
Fathi Boudrafdd9f212015-04-18 19:28:55 +0300132 AUTH_TOKEN=os.environ.get('AUTH_TOKEN'),
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200133 LT_QCOM_KEY=os.environ.get('LT_QCOM_KEY'),
134 LAVA_USER=os.environ.get('LAVA_USER'),
135 LAVA_TOKEN=os.environ.get('LAVA_TOKEN'))
136 with open('template.yaml', 'w') as f:
137 f.write(buffer)
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200138
Kelley Spoone1e1f382022-06-23 07:53:05 -0500139 proc = safe_run(jjb_args)
Riku Voipiob866d3c2021-10-25 10:23:07 +0300140 data = proc.stdout.decode()
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200141
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +0000142 try:
143 shutil.rmtree('out/', ignore_errors=True)
144
Kelley Spoone1e1f382022-06-23 07:53:05 -0500145 proc = safe_run(jjb_test_args)
Riku Voipiob866d3c2021-10-25 10:23:07 +0300146 data = proc.stdout.decode()
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +0000147
Kelley Spoone1e1f382022-06-23 07:53:05 -0500148 proc = safe_run(['ls', 'out/'])
Riku Voipiob866d3c2021-10-25 10:23:07 +0300149 data = proc.stdout.decode()
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +0000150
151 for filename in data.splitlines():
Dmitry Baryshkovf30653b2021-01-13 13:38:31 +0300152 # old job conf might have been removed because the job is now generated through the template
153 # do not delete the job in this case
154 if filename in deletelist:
155 deletelist.remove(filename)
156
Riku Voipioc0e6b132019-06-27 13:52:04 +0300157 conf_name=os.path.splitext(conf_filename)[0]
Maxim Kuvyrkovcffdf252020-05-15 16:07:51 +0000158 conf_name=conf_name[:len(filename)]
Riku Voipioc0e6b132019-06-27 13:52:04 +0300159 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
Maxim Kuvyrkov4a4f6762021-08-05 16:26:00 +0000172 deletelist.append(filename)
Riku Voipio2ad62762020-06-16 13:32:52 +0300173
Maxim Kuvyrkov56cc7fe2018-10-09 15:23:12 +0000174 except (OSError, ValueError) as e:
175 raise ValueError("%s" % e)
176
177 shutil.rmtree('out/', ignore_errors=True)
Paul Sokolovskyb1d86572015-03-05 22:48:18 +0200178 os.remove('template.yaml')
Fathi Boudraf25a3db2017-04-07 07:25:33 +0300179
Riku Voipio2ad62762020-06-16 13:32:52 +0300180
181for deletejob in deletelist:
182 delete_args = list(jjb_delete_args)
183 delete_args.extend([deletejob])
Kelley Spoone1e1f382022-06-23 07:53:05 -0500184
185 proc = safe_run(delete_args)
186 data = proc.stdout.decode()
187
188 print(data)
Riku Voipio2ad62762020-06-16 13:32:52 +0300189
Fathi Boudraf25a3db2017-04-07 07:25:33 +0300190if os.path.exists('jenkins_jobs.ini'):
191 os.remove('jenkins_jobs.ini')