diff --git a/scripts/buildkite_utils.py b/scripts/buildkite_utils.py index d4ff78f..b7b4a9c 100644 --- a/scripts/buildkite_utils.py +++ b/scripts/buildkite_utils.py @@ -78,6 +78,9 @@ class BuildkiteApi: # https://buildkite.com/docs/apis/rest-api/builds#get-a-build return benedict(self.get(f'https://api.buildkite.com/v2/organizations/{self.organization}/pipelines/{pipeline}/builds/{build_number}').json()) + def list_running_revision_builds(self, pipeline: str, rev: str): + return self.get(f'https://api.buildkite.com/v2/organizations/{self.organization}/pipelines/{pipeline}/builds?state[]=scheduled&state[]=running&meta_data[ph_buildable_revision]={rev}').json() + @backoff.on_exception(backoff.expo, Exception, max_tries=3, logger='', factor=3) def get(self, url: str): authorization = f'Bearer {self.token}' @@ -86,6 +89,15 @@ class BuildkiteApi: raise Exception(f'Buildkite responded with non-OK status: {response.status_code}') return response + # cancel a build. 'build' is a json object returned by API. + def cancel_build(self, build): + build = benedict(build) + url = f'https://api.buildkite.com/v2/organizations/{self.organization}/pipelines/{build.get("pipeline.slug")}/builds/{build.get("number")}/cancel' + authorization = f'Bearer {self.token}' + response = requests.put(url, headers={'Authorization': authorization}) + if response.status_code != 200: + raise Exception(f'Buildkite responded with non-OK status: {response.status_code}') + def format_url(url: str, name: Optional[str] = None): if name is None: diff --git a/scripts/cancel_previous_build.py b/scripts/cancel_previous_build.py deleted file mode 100755 index 940e908..0000000 --- a/scripts/cancel_previous_build.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2020 Google LLC -# -# Licensed under the the Apache License v2.0 with LLVM Exceptions (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://llvm.org/LICENSE.txt -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import requests - -def main(review_number, api_key): - buildkite = requests.Session() - buildkite.headers.update({'Authorization': 'Bearer {}'.format(api_key)}) - api = lambda query: 'https://api.buildkite.com/v2' + query - - builds = buildkite.get(api('/organizations/llvm-project/builds?state[]=scheduled&state[]=running')).json() - for build in builds: - if build['message'] == review_number: - pipeline = build['pipeline']['slug'] - buildkite.put(api('/organizations/llvm-project/pipelines/{}/builds/{}/cancel'.format(pipeline, build['number']))) - -if __name__ == '__main__': - review_number = 'D{}'.format(os.getenv('ph_buildable_revision')) - api_key = # TODO where do we get that? The agents on the service queue need to have the proper access (read_builds and write_builds) - main(review_number, api_key) diff --git a/scripts/pipeline_create_branch.py b/scripts/pipeline_create_branch.py index b04463e..a28c471 100755 --- a/scripts/pipeline_create_branch.py +++ b/scripts/pipeline_create_branch.py @@ -15,7 +15,9 @@ import os import yaml -from buildkite_utils import annotate, feedback_url, set_metadata +import logging +from buildkite_utils import set_metadata, BuildkiteApi + if __name__ == '__main__': diff_id = os.getenv("ph_buildable_diff") @@ -23,6 +25,17 @@ if __name__ == '__main__': base_commit = os.getenv('ph_base_commit', 'auto') run_build = os.getenv('ph_skip_build') is None trigger = os.getenv('ph_trigger_pipeline') + logging.basicConfig(level=log_level, format='%(levelname)-7s %(message)s') + + # Cancel any existing builds. + # Do this before setting own 'ph_buildable_revision'. + try: + bk = BuildkiteApi(os.getenv("BUILDKITE_API_TOKEN"), os.getenv("BUILDKITE_ORGANIZATION_SLUG")) + for b in bk.list_running_revision_builds(os.getenv("BUILDKITE_PIPELINE_SLUG"), os.getenv('ph_buildable_revision')): + logging.info(f'cancelling build {b.get("web_url")}') + bk.cancel_build(b) + except Exception as e: + logging.error(e) set_metadata('ph_buildable_diff', os.getenv("ph_buildable_diff")) set_metadata('ph_buildable_revision', os.getenv('ph_buildable_revision'))