zuul-jobs/tools/update-test-platforms.py
Sorin Sbarnea 0d886253f6 Add managed jobs to periodic-weekly
To avoid getting zuul-jobs getting rotten without known, we need
to run them weekly.

This should solve issue where some less common job get broken and
we find out much later, when we have to make other unrelated changes.

Change-Id: I3a95526fdb83b8aef12ee2ee09a089990e75cb59
Depends-On: https://review.opendev.org/#/c/748706
2020-09-17 08:33:50 +00:00

159 lines
5.2 KiB
Python
Executable File

#!/usr/bin/env python
#
# Copyright 2019 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# Update job definitions for multi-platform jobs, and make sure every
# in-repo test job appears in a project definition. This script
# re-writes the files in zuul-tests.d. It should be run from the root
# of the repo.
import os
from ruamel.yaml.comments import CommentedMap
import ruamellib
# There are fedora- and debian-latest nodesets, but they can't be used
# in the multinode jobs, so just use the real labels everywhere.
PLATFORMS = [
'centos-7',
'centos-8',
'debian-stretch',
'fedora-32',
'gentoo-17-0-systemd',
'opensuse-15',
'opensuse-tumbleweed',
'ubuntu-bionic',
'ubuntu-xenial',
'ubuntu-focal',
]
# insert a platform from above to make it non-voting
NON_VOTING = [
'opensuse-tumbleweed',
]
# Insert a job to make that single job non-voting
NON_VOTING_JOBS = [
'zuul-jobs-test-multinode-roles-gentoo-17-0-systemd',
]
def get_nodeset(platform, multinode):
d = CommentedMap()
if not multinode:
d['nodes'] = [
CommentedMap([('name', platform), ('label', platform)]),
]
else:
d['nodes'] = [
CommentedMap([('name', 'primary'), ('label', platform)]),
CommentedMap([('name', 'secondary'), ('label', platform)]),
]
d['groups'] = [
CommentedMap([('name', 'switch'), ('nodes', ['primary'])]),
CommentedMap([('name', 'peers'), ('nodes', ['secondary'])]),
]
return d
def handle_file(fn):
yaml = ruamellib.YAML()
data = yaml.load(open(fn))
outdata = []
outprojects = []
joblist_check = []
joblist_gate = []
has_non_voting = False
for obj in data:
if 'job' in obj:
job = obj['job']
if 'auto-generated' in job.get('tags', []):
continue
outdata.append(obj)
tags = job.get('tags', [])
all_platforms = False
if 'all-platforms-multinode' in tags:
multinode = True
all_platforms = True
elif 'all-platforms' in tags:
all_platforms = True
multinode = False
if all_platforms:
for platform in PLATFORMS:
voting = False if platform in NON_VOTING else True
ojob = CommentedMap()
ojob['name'] = job['name'] + '-' + platform
if ojob['name'] in NON_VOTING_JOBS:
voting = False
if not voting:
ojob['name'] += '-nv'
ojob['voting'] = False
has_non_voting = True
desc = job['description'].split('\n')[0]
ojob['description'] = desc + ' on ' \
+ platform
ojob['parent'] = job['name']
ojob['tags'] = 'auto-generated'
ojob['nodeset'] = get_nodeset(platform, multinode)
outdata.append({'job': ojob})
joblist_check.append(ojob['name'])
if voting:
joblist_gate.append(ojob['name'])
elif not job.get('abstract', False):
joblist_check.append(job['name'])
# don't append non-voting jobs to gate
if job.get('voting', True):
joblist_gate.append(job['name'])
else:
has_non_voting = True
elif 'project' in obj:
outprojects.append(obj)
else:
outdata.append(obj)
# We control the last project stanza
outdata.extend(outprojects)
project = outprojects[-1]['project']
project['check']['jobs'] = joblist_check
# Use the same dictionary if there are no non-voting jobs
# (i.e. check is the same as gate); this gives nicer YAML output
# using dictionary anchors
project['gate']['jobs'] = joblist_gate if has_non_voting else joblist_check
# gate jobs should also be in periodic in order to assure they do not rot
periodic_pipeline = 'periodic-weekly'
if periodic_pipeline not in project:
project[periodic_pipeline] = {}
if 'jobs' not in project[periodic_pipeline]:
project[periodic_pipeline]['jobs'] = []
project[periodic_pipeline]['jobs'] = joblist_gate \
if has_non_voting else joblist_check
with open(fn, 'w') as f:
yaml.dump(outdata, stream=f)
def main():
for f in os.listdir('zuul-tests.d'):
if not f.endswith('.yaml'):
continue
if f == 'project.yaml':
continue
handle_file(os.path.join('zuul-tests.d', f))
if __name__ == "__main__":
main()