diff --git a/manifest-integration.yml b/manifest-integration.yml index 53691afdd0079031b185dc9b0483d008be1be6c2..1fc1b1cb5b900ef956200063a0313fe0b6f2938c 100644 --- a/manifest-integration.yml +++ b/manifest-integration.yml @@ -115,6 +115,20 @@ check: fi; done <<< "$INTEGRATION" +cancel-previous-pipelines: + extends: + - .infrastructure + - .skip-for-gitlab-ci-integrations + stage: manifest-integration + allow_failure: true + script: + - .gitlab-ci/scripts/cancel_pipelines.py + --gitlab-url=${CI_SERVER_URL} + --token=${GITBOT_TOKEN} + --project=${CI_PROJECT_PATH} + --ref=${CI_MERGE_REQUEST_REF_PATH} + --below-pipeline-id=${CI_PIPELINE_ID} + yamllint: extends: .yamllint stage: manifest-integration diff --git a/scripts/cancel_pipelines.py b/scripts/cancel_pipelines.py new file mode 100755 index 0000000000000000000000000000000000000000..437dc8805f2032bfb0b84da97a025a0767524e63 --- /dev/null +++ b/scripts/cancel_pipelines.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 +import argparse +import sys + +from gitlab.client import Gitlab +from gitlab.v4.objects import Project, ProjectPipeline + +import common + + +def cancel_pipelines( + project: Project, + ref: str = "", + below_pipeline_id: int = sys.maxsize, +) -> list[ProjectPipeline]: + """Cancel currently running pipelines. + + Args: + project: GitLab project the pipeline belongs to + ref: Git ref (branch or tag) the pipeline is running on + below_pipeline_id: cancel only pipelines with ID below this + + Returns: + List of cancelled pipelines + """ + + pipelines = project.pipelines.list( + ref=ref, status="running", retry_transient_errors=True + ) + + cancelled_pipelines = [] + for pipeline in pipelines: + if pipeline.id < below_pipeline_id: + pipeline.cancel() + cancelled_pipelines.append(pipeline) + + return cancelled_pipelines + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--gitlab-url", + help="""URL to the GitLab instance""", + dest="gitlab_url", + default=common.GITLAB_URL, + ) + 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="""Git reference (branch or tag)""", + dest="ref", + default="", + ) + parser.add_argument( + "--below-pipeline-id", + help="""Cancel only pipelines with IDs lower than this""", + dest="below_pipeline_id", + type=int, + default=sys.maxsize, + ) + + args, _ = parser.parse_known_args() + + gitlab = Gitlab(args.gitlab_url, private_token=args.token) + project = common.get_project(gitlab, args.project) + + print( + "Searching for pipelines in project '%s' on ref '%s' with IDs below %d" + % (args.project, args.ref, args.below_pipeline_id) + ) + + cancelled_pipelines = cancel_pipelines(project, args.ref, args.below_pipeline_id) + + if not cancelled_pipelines: + print("No running pipelines found.") + sys.exit(0) + + print("Cancelled pipelines:") + for pipeline in cancelled_pipelines: + print(pipeline.web_url) + + +if __name__ == "__main__": + main()