1
0
Fork 0

cancel previous builds for the same revisions

using metadata tags set in  finds and cancels existing builds before
starting a new one.

One caveat is that no result is reported back to Phabricator for the
cancelled build. That should not be an issue in the normal usecase.

For 
This commit is contained in:
Mikhail Goncharov 2021-05-04 11:24:08 +02:00
parent 6b731dc4d5
commit 1c04f70eb9
3 changed files with 26 additions and 34 deletions

View file

@ -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:

View file

@ -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)

View file

@ -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'))