blob: e78b56bdd660801c90d77f67a40491e90e1453f1 [file] [log] [blame]
Arthur Sheb786abd2023-07-17 11:01:59 -07001#!/usr/bin/python3
2
3import os
4import shutil
5import signal
6import string
7import subprocess
8import sys
9import xml.etree.ElementTree
10from distutils.spawn import find_executable
11
12
13def findparentfiles(fname):
14 filelist = []
15 newlist = []
16 args = ['grep', '-rl', '--exclude-dir=.git', fname]
17 proc = subprocess.run(args, capture_output=True)
18 data = proc.stdout.decode()
19 if proc.returncode != 0:
20 return filelist
21 for filename in data.splitlines():
22 if filename.endswith('.yaml') and '/' not in filename:
23 filelist.append(filename)
24 else:
25 newlist = findparentfiles(filename)
26 for tempname in newlist:
27 filelist.append(tempname)
28 return filelist
29
30
31jjb_cmd = find_executable('jenkins-jobs') or sys.exit('jenkins-jobs is not found.')
32jjb_args = [jjb_cmd]
33
34jjb_user = os.environ.get('JJB_USER')
35jjb_password = os.environ.get('JJB_PASSWORD')
36if jjb_user is not None and jjb_password is not None:
37 jenkins_jobs_ini = ('[job_builder]\n'
38 'ignore_cache=True\n'
39 'keep_descriptions=False\n'
40 '\n'
41 '[jenkins]\n'
42 'user=%s\n'
43 'password=%s\n'
Arthur She6f57ed02023-07-17 11:15:36 -070044 'url=https://mbedtls.trustedfirmware.org/\n' % (jjb_user, jjb_password))
Arthur Sheb786abd2023-07-17 11:01:59 -070045 with open('jenkins_jobs.ini', 'w') as f:
46 f.write(jenkins_jobs_ini)
47 jjb_args.append('--conf=jenkins_jobs.ini')
48
49jjb_test_args = list(jjb_args)
50jjb_delete_args = list(jjb_args)
51
52# !!! "update" below and through out this file is replaced by "test" (using sed)
53# !!! in the sanity-check job.
54main_action = 'update'
55jjb_args.extend([main_action, 'template.yaml'])
56jjb_test_args.extend(['test', '-o', 'out/', 'template.yaml'])
57jjb_delete_args.extend(['delete'])
58
59if main_action == 'test':
60 # Dry-run, don't delete jobs.
61 jjb_delete_args.insert(0, 'echo')
62
63try:
64 git_args = ['git', 'diff', '--raw',
65 os.environ.get('GIT_PREVIOUS_COMMIT'),
66 os.environ.get('GIT_COMMIT')]
67 proc = subprocess.run(git_args, capture_output=True)
68except (OSError, ValueError) as e:
69 raise ValueError("%s" % e)
70
71data = proc.stdout.decode()
72if proc.returncode != 0:
73 raise ValueError("command has failed with code '%s'" % proc.returncode)
74
75filelist = []
76deletelist = []
77files = []
78for line in data.splitlines():
79 # Format of the git-diff; we only need OPERATION and FILE1
80 #
81 # :<OLD MODE> <NEW MODE> <OLD REF> <NEW REF> <OPERATION> <FILE1> <FILE2>
82 elems = line.split()
83 operation = elems[4][0]
84 filename = elems[5]
85
86 if filename.endswith('.yaml') and '/' not in filename:
87 # No point trying to test deleted jobs because they don't exist any
88 # more.
89 if operation == 'D':
90 deletelist.append(filename[:-5])
91 continue
92 # operation R100 is 100% rename, which means sixth element is the renamed file
93 if operation == 'R':
94 filename = elems[6]
95 # delete old job name
96 deletelist.append(elems[5][:-5])
97 filelist.append(filename)
98 else:
99 files = findparentfiles(filename)
100 for tempname in files:
101 filelist.append(tempname)
102
103# Remove duplicate entries in the list
104filelist = list(set(filelist))
105
106for conf_filename in filelist:
107 with open(conf_filename) as f:
108 buffer = f.read()
109 template = string.Template(buffer)
110 buffer = template.safe_substitute(
111 AUTH_TOKEN=os.environ.get('AUTH_TOKEN'),
112 LT_QCOM_KEY=os.environ.get('LT_QCOM_KEY'),
113 LAVA_USER=os.environ.get('LAVA_USER'),
114 LAVA_TOKEN=os.environ.get('LAVA_TOKEN'))
115 with open('template.yaml', 'w') as f:
116 f.write(buffer)
117 try:
118 proc = subprocess.run(jjb_args, capture_output=True)
119 except (OSError, ValueError) as e:
120 raise ValueError("%s" % e)
121
122 data = proc.stdout.decode()
123 if proc.returncode != 0:
124 raise ValueError("command has failed with code '%s'" % proc.returncode)
125
126 try:
127 shutil.rmtree('out/', ignore_errors=True)
128
129 proc = subprocess.run(jjb_test_args, capture_output=True)
130 data = proc.stdout.decode()
131 if proc.returncode != 0:
132 raise ValueError("command has failed with code '%s'" % proc.returncode)
133
134 proc = subprocess.run(['ls', 'out/'], capture_output=True)
135 data = proc.stdout.decode()
136 if proc.returncode != 0:
137 raise ValueError("command has failed with code '%s'" % proc.returncode)
138
139 for filename in data.splitlines():
140 # old job conf might have been removed because the job is now generated through the template
141 # do not delete the job in this case
142 if filename in deletelist:
143 deletelist.remove(filename)
144
145 conf_name=os.path.splitext(conf_filename)[0]
146 conf_name=conf_name[:len(filename)]
147 if not filename.startswith(conf_name):
148 raise ValueError("Job name %s does not match the file it is in: %s" % (filename, conf_name))
149 try:
150 xmlroot = xml.etree.ElementTree.parse('out/' + filename).getroot()
151 disabled = next(xmlroot.iterfind('disabled')).text
152 if disabled != 'true':
153 continue
154 displayName = next(xmlroot.iterfind('displayName')).text
155 if displayName != 'DELETE ME':
156 continue
157 except:
158 continue
159
160 deletelist.append(filename)
161
162 except (OSError, ValueError) as e:
163 raise ValueError("%s" % e)
164
165 shutil.rmtree('out/', ignore_errors=True)
166 os.remove('template.yaml')
167
168
169for deletejob in deletelist:
170 delete_args = list(jjb_delete_args)
171 delete_args.extend([deletejob])
172 try:
173 proc = subprocess.run(delete_args, capture_output=True)
174 data = proc.stdout.decode()
175 if proc.returncode != 0:
176 raise ValueError("command has failed with code '%s'" % proc.returncode)
177 print(data)
178 except (OSError, ValueError) as e:
179 raise ValueError("%s" % e)
180
181if os.path.exists('jenkins_jobs.ini'):
182 os.remove('jenkins_jobs.ini')
183