diff --git a/get_pipelines.py b/get_pipelines.py new file mode 100755 index 0000000000000000000000000000000000000000..b3c2012a9e1f9b6394ea30f145b77bb2fa19b8e8 --- /dev/null +++ b/get_pipelines.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +import common + +import argparse +import sys +from gitlab import Gitlab +from gitlab.v4.objects import Project + + +def get_pipelines(project: Project, commit, ref: str): + """ + Get all pipelines for a given commit and ref. + The ref can be negated with a preceding '^', e.g. '^master' finds pipelines on any + ref different from 'master'. + """ + + # Find pipelines for commit + pipelines = project.pipelines.list(sha=commit, retry_transient_errors=True) + + # Remove pipelines not matching the ref condition + if ref: + for p in pipelines[:]: + if ( + ref.startswith("^") + and p.ref == ref[1:] + or not ref.startswith("^") + and p.ref != ref + ): + pipelines.remove(p) + + if not pipelines: + raise LookupError( + "No pipeline for commit '%s'%s found" + % (commit, " on ref '%s'" % ref if ref else "") + ) + + return pipelines + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--gitlab-url", + help="""URL to the GitLab instance""", + dest="gitlab_url", + required=True, + ) + parser.add_argument( + "--token", + help="""GitLab REST API private access token""", + dest="token", + required=True, + ) + parser.add_argument( + "--project", + help="""name of the GitLab project""", + dest="project", + required=True, + ) + parser.add_argument( + "--commit", + help="""sha of the project commit to check""", + dest="commit", + required=True, + ) + parser.add_argument( + "--ref", + help="""ref the pipeline ran on (can be negated with preceding '^')""", + dest="ref", + default="", + required=False, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + project = common.get_project(gitlab, args.project) + + try: + pipelines = get_pipelines(project, args.commit, args.ref) + except LookupError as e: + sys.exit(e) + + for p in pipelines: + print(p.id) + + sys.exit(0) + + +if __name__ == "__main__": + main() diff --git a/check_pipeline_status.py b/mirror_pipeline_result.py similarity index 62% rename from check_pipeline_status.py rename to mirror_pipeline_result.py index fa3b8175c102c807860eafd8a4c48a285537d6e4..c2973691108ecff7cbdc24e92855fe000fd26e66 100755 --- a/check_pipeline_status.py +++ b/mirror_pipeline_result.py @@ -9,31 +9,14 @@ from gitlab import Gitlab, GitlabGetError from gitlab.v4.objects import Project -def check_pipeline_status(project: Project, commit, ref: str): +def mirror_pipeline_result(project: Project, pipeline_id, job=None): """ Get latest pipeline status for a given commit and ref. The ref can be negated with a preceding '^', e.g. '^master' finds a pipeline on any ref different from 'master'. """ - # Find pipeline for commit - pipelines = project.pipelines.list(sha=commit, retry_transient_errors=True) - - # Remove pipelines not matching the ref condition - if ref: - for p in pipelines[:]: - if ( - ref.startswith("^") - and p.ref == ref[1:] - or not ref.startswith("^") - and p.ref != ref - ): - pipelines.remove(p) - - if not pipelines: - print("ERROR: no pipeline for commit '%s' with ref '%s' found" % (commit, ref)) - sys.exit(1) - pipeline = pipelines[0] + pipeline = project.pipelines.get(pipeline_id, retry_transient_errors=True) # Wait for pipeline termination print("Waiting for pipeline %s" % pipeline.web_url) @@ -45,6 +28,13 @@ def check_pipeline_status(project: Project, commit, ref: str): print("") print("Result: %s" % pipeline.status, flush=True) + # If we are running in a job environment and the upstream status is canceled, + # explicitly cancel this job as well + if job and pipeline.status == "canceled": + time.sleep(5) + job.cancel() + + # Else just reflect job status in return value return pipeline.status @@ -69,43 +59,31 @@ def main(): required=True, ) parser.add_argument( - "--commit", - help="""sha of the project commit to check""", - dest="commit", + "--pipeline", + help="""id of the pipeline to mirror the result of""", + dest="pipeline", required=True, ) - parser.add_argument( - "--ref", - help="""ref the pipeline ran on (can be negated with preceding '^')""", - dest="ref", - default="", - required=False, - ) args, _ = parser.parse_known_args() gitlab = Gitlab(args.gitlab_url, private_token=args.token) project = common.get_project(gitlab, args.project) - status = check_pipeline_status(project, args.commit, args.ref) - - # If we are running in a job environment and the upstream status is canceled, - # explicitly cancel this job as well + # Check if we are running in a GitLab job context job_project_path = os.environ.get("CI_PROJECT_PATH") job_id = os.environ.get("CI_JOB_ID") - if job_project_path and job_id and status == "canceled": + if job_project_path and job_id: try: job_project = common.get_project(gitlab, job_project_path) job = job_project.jobs.get(id=job_id, retry_transient_errors=True) - # Wait some time until Gitlab has flushed the job log, otherwise it will be - # truncated before all lines are visible - time.sleep(5) - job.cancel() except GitlabGetError: print("WARNING: job %s not found in project %s" % (args.job, args.project)) + job = None - # Else just reflect job status in return value - elif status != "success": + status = mirror_pipeline_result(project, args.pipeline, job) + + if status != "success": sys.exit(1) sys.exit(0) diff --git a/trigger_pipeline.py b/trigger_pipeline.py new file mode 100755 index 0000000000000000000000000000000000000000..c0d0bada90119c59e3ba4ca91f2f06c9f345d0aa --- /dev/null +++ b/trigger_pipeline.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +import common + +import argparse +import sys +from gitlab import Gitlab, GitlabCreateError + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--gitlab-url", + help="""URL to the GitLab instance""", + dest="gitlab_url", + required=True, + ) + parser.add_argument( + "--token", + help="""GitLab REST API private access token""", + dest="token", + required=True, + ) + parser.add_argument( + "--project", + help="""name of the GitLab project""", + dest="project", + required=True, + ) + parser.add_argument( + "--ref", + help="""branch or tag ref to trigger the pipeline for""", + dest="ref", + required=True, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + project = common.get_project(gitlab, args.project) + + try: + pipeline = project.pipelines.create({"ref": args.ref}) + except GitlabCreateError as e: + sys.exit("ERROR: %s" % e) + + print("Created new pipeline:") + print(pipeline.web_url) + + sys.exit(0) + + +if __name__ == "__main__": + main()