#!/usr/bin/env python3 # Copyright (C) Internet Systems Consortium, Inc. ("ISC") # # SPDX-License-Identifier: MPL-2.0 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, you can obtain one at https://mozilla.org/MPL/2.0/. # # See the COPYRIGHT file distributed with this work for additional # information regarding copyright ownership. import os import sys import time import gitlab def init_gitlab_project(): if os.getenv("CI_SERVER_URL", None) is not None: url = os.getenv("CI_SERVER_URL") job_token = os.environ["CI_JOB_TOKEN"] gl = gitlab.Gitlab(url, job_token=job_token) else: # running locally on dev machine gl = gitlab.Gitlab.from_config() return gl.projects.get("isc-projects/bind9-shotgun-ci") def parse_parent_pipeline_id(): if len(sys.argv) != 2: raise RuntimeError("usage: util/ci-wait-shotgun.py PIPELINE_ID") try: return int(sys.argv[1]) except ValueError as exc: raise RuntimeError("error: PIPELINE_ID must be a number") from exc def wait_until(callback, timeout=1800, retry=10): start = time.time() while time.time() - start < timeout: if callback(): return time.sleep(retry) raise RuntimeError(f"error: timed out after {timeout}s") def get_child_pipeline_id(project, pipeline_id): pipeline = project.pipelines.get(pipeline_id) def pipeline_finished(): pipeline.refresh() return pipeline.finished_at is not None wait_until(pipeline_finished, timeout=6600) bridges = pipeline.bridges.list() if len(bridges) != 1: raise RuntimeError("error: expected exactly one child pipeline") return bridges[0].downstream_pipeline["id"] def get_postproc_job(project, pipeline_id): pipeline = project.pipelines.get(pipeline_id) postproc_job = None def job_finished(): nonlocal postproc_job for job in pipeline.jobs.list(get_all=True): if job.name == "postproc": postproc_job = job if postproc_job is None: raise RuntimeError("error: failed to find 'postproc' job in child pipeline") return postproc_job.finished_at is not None wait_until(job_finished) return postproc_job def evaluate_postproc_job(job): print(f"postproc job URL: {job.web_url}") index_url = ( "https://isc-projects.gitlab-pages.isc.org/-/" f"bind9-shotgun-ci/-/jobs/{job.id}/artifacts/index.html" ) if job.status in ["success", "failed"]: print(f"result for manual inspection: {index_url}") if job.status != "success": raise RuntimeError("error: 'postproc' job didn't succeed") def main(): project = init_gitlab_project() parent_pipeline_id = parse_parent_pipeline_id() child_pipeline_id = get_child_pipeline_id(project, parent_pipeline_id) postproc_job = get_postproc_job(project, child_pipeline_id) evaluate_postproc_job(postproc_job) if __name__ == "__main__": try: main() except RuntimeError as err: print(err) sys.exit(1)