2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00
bind/util/ci-wait-shotgun.py
Tom Krizek ff32421a64
util: script to get DNS Shotgun pipeline results
The shotgun performance tests are executed in a different repository, in
a couple of different pipelines. To hide away the complexity, this
script takes the pipeline ID of the triggered pipeline and then takes
care of the rest - waits for the pipeline to finish, locates the child
pipeline and the relevant results. The output from this script is a
convenient link to the charts with the results once they're available.

GitLab also has a mechanism which can wait for another pipeline.
However, it can't be utilized here, since there are variables which
need to be passed in when the pipeline is triggered (like protocol to be
tested, load, runtime etc.). This isn't currently supported by the
GitLab feature.
2023-11-01 09:47:20 +01:00

105 lines
3.0 KiB
Python
Executable File

#!/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=3000)
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):
if job.status != "success":
raise RuntimeError("error: 'postproc' job didn't succeed")
index_url = (
"https://isc-projects.gitlab-pages.isc.org/-/"
f"bind9-shotgun-ci/-/jobs/{job.id}/artifacts/index.html"
)
print(f"Result ready for manual inspection: {index_url}")
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)