1#!/usr/bin/env python 2"""Script to sync CF and Jenkins jobs.""" 3 4import json 5import os 6import re 7import sys 8import yaml 9 10import jenkins 11 12JENKINS_SERVER = ('localhost', 8080) 13 14JOB_TEMPLATES = [ 15 {'prefix': 'projects/', 'config': 'base_job.xml'}, 16 {'prefix': 'coverage/', 'config': 'coverage_job.xml'}, 17] 18 19SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 20OSSFUZZ_DIR = os.path.dirname(os.path.dirname(SCRIPT_DIR)) 21 22VALID_PROJECT_NAME = re.compile(r'^[a-zA-Z0-9_-]+$') 23 24 25def main(): 26 # Connect to jenkins server. 27 jenkins_login = get_jenkins_login() 28 server = jenkins.Jenkins( 29 'http://%s:%d' % JENKINS_SERVER, 30 username=jenkins_login[0], 31 password=jenkins_login[1]) 32 33 for project in get_projects(): 34 print 'syncing configs for', project 35 try: 36 # Create/update jenkins build job. 37 sync_jenkins_job(server, project) 38 39 except Exception as e: 40 print >> sys.stderr, 'Failed to setup job with exception', e 41 42 43def _has_dockerfile(project_dir): 44 """Whether or not the project has a Dockerfile.""" 45 if os.path.exists(os.path.join(project_dir, 'Dockerfile')): 46 return True 47 48 project_yaml_path = os.path.join(project_dir, 'project.yaml') 49 if not os.path.exists(project_yaml_path): 50 return False 51 52 with open(project_yaml_path) as f: 53 project_info = yaml.safe_load(f) 54 55 return 'dockerfile' in project_info 56 57 58def get_projects(): 59 """Return list of projects for oss-fuzz.""" 60 projects = [] 61 projects_dir = os.path.join(OSSFUZZ_DIR, 'projects') 62 for name in os.listdir(projects_dir): 63 full_path = os.path.join(projects_dir, name) 64 if not os.path.isdir(full_path) or not _has_dockerfile(full_path): 65 continue 66 67 if not VALID_PROJECT_NAME.match(name): 68 print >> sys.stderr, 'Invalid project name:', name 69 continue 70 71 projects.append(name) 72 73 if not projects: 74 print >> sys.stderr, 'No projects found.' 75 76 return projects 77 78 79def get_jenkins_login(): 80 """Returns (username, password) for jenkins.""" 81 username = os.getenv('JENKINS_USER') 82 password = os.getenv('JENKINS_PASS') 83 84 return username, password 85 86 87def sync_jenkins_job(server, project): 88 """Sync the config with jenkins.""" 89 project_yaml = os.path.join(OSSFUZZ_DIR, 'projects', project, 'project.yaml') 90 with open(project_yaml, 'r') as f: 91 project_json_string = json.dumps(json.dumps(yaml.safe_load(f))) 92 93 for job in JOB_TEMPLATES: 94 job_name = job['prefix'] + project 95 with open(os.path.join(SCRIPT_DIR, 'jenkins_config', job['config'])) as f: 96 job_config_xml = f.read() 97 98 if server.job_exists(job_name): 99 server.reconfig_job(job_name, job_config_xml) 100 else: 101 server.create_job(job_name, job_config_xml) 102 server.build_job(job_name) 103 104 105if __name__ == '__main__': 106 main() 107