Index: appengine/chromium_rietveld/codereview/buildbucket.py |
diff --git a/appengine/chromium_rietveld/codereview/buildbucket.py b/appengine/chromium_rietveld/codereview/buildbucket.py |
index 53d65c7068c58e10c6f1185c200125d194e66b42..cb841a34fea126a2e7cdcfeb99f4323b648f68bf 100644 |
--- a/appengine/chromium_rietveld/codereview/buildbucket.py |
+++ b/appengine/chromium_rietveld/codereview/buildbucket.py |
@@ -19,6 +19,7 @@ import json |
import logging |
import os |
import urllib |
+import uuid |
from google.appengine.api import app_identity |
from google.appengine.api import memcache |
@@ -160,19 +161,7 @@ def get_builds_for_patchset_async(project, issue_id, patchset_id): |
Returns: |
A list of buildbucket build dicts. |
""" |
- # See tag conventions http://cr-buildbucket.appspot.com/#docs/conventions . |
- hostname = common.get_preferred_domain(project, default_to_appid=False) |
- if not hostname: |
- logging.error( |
- 'Preferred domain name for this app is not set. ' |
- 'See PREFERRED_DOMAIN_NAMES in settings.py: %r', hostname) |
- raise ndb.Return([]) |
- |
- buildset_tag = BUILDSET_TAG_FORMAT.format( |
- hostname=hostname, |
- issue=issue_id, |
- patch=patchset_id, |
- ) |
+ buildset_tag = get_buildset_for(project, issue_id, patchset_id) |
params = { |
'max_builds': 500, |
'tag': 'buildset:%s' % buildset_tag, |
@@ -212,6 +201,75 @@ def get_try_job_results_for_patchset_async(project, issue_id, patchset_id): |
################################################################################ |
+## Scheduling builds. |
+ |
+ |
+def schedule(issue, patchset_id, builds): |
+ """Schedules builds on buildbucket. |
+ |
+ |builds| is a list of (master, builder) tuples, where master must not have |
+ '.master' prefix. |
+ """ |
+ account = models.Account.current_user_account |
+ assert account, 'User is not logged in; cannot schedule builds.' |
+ |
+ if not builds: |
+ return |
+ |
+ self_hostname = common.get_preferred_domain(issue.project) |
+ |
+ req = {'builds':[]} |
+ opid = uuid.uuid4() |
+ |
+ for i, (master, builder) in enumerate(builds): |
+ # Build definitions are similar to what CQ produces: |
+ # https://chrome-internal.googlesource.com/infra/infra_internal/+/c3092da98975c7a3e083093f21f0f4130c66a51c/commit_queue/buildbucket_util.py#171 |
+ req['builds'].append({ |
+ 'bucket': 'master.%s' % master, |
+ 'parameters_json': json.dumps({ |
+ 'builder_name': builder, |
+ 'changes': [{ |
+ 'author': {'email': issue.owner.email()}, |
+ 'url': 'https://%s/%s/%s/' % ( |
+ self_hostname, issue.key.id(), patchset_id) |
+ }], |
+ 'properties': { |
+ 'issue': issue.key.id(), |
+ 'master': master, |
+ 'patch_project': issue.project, |
+ 'patch_storage': 'rietveld', |
+ 'patchset': patchset_id, |
+ 'project': issue.project, |
+ 'rietveld': self_hostname, |
+ }, |
+ }), |
+ 'tags': [ |
+ 'builder:%s' % builder, |
+ 'buildset:%s' % get_buildset_for( |
+ issue.project, issue.key.id(), patchset_id), |
+ 'master:%s' % master, |
+ 'user_agent:rietveld', |
+ ], |
+ 'client_operation_id': '%s:%s' % (opid, i), |
+ }) |
+ |
+ logging.debug( |
+ 'Scheduling %d builds on behalf of %s', len(req['builds']), account.email) |
+ res = rpc_async('PUT', 'builds/batch', payload=req).get_result() |
+ for r in res['results']: |
+ error = r.get('error') |
+ if error: |
+ logging.error('Build scheduling failed. Response: %r', res) |
+ raise BuildBucketError('Could not schedule build(s): %r' % error) |
Vadim Sh.
2015/09/16 21:57:38
how is this displayed to the user?
nodir
2015/09/17 17:44:17
very rough: on any 500 the old UI shows an alert t
|
+ |
+ actual_builds = [r['build'] for r in res['results']] |
+ logging.info( |
+ 'Scheduled buildbucket builds: %r', |
+ ', '.join([str(b['id']) for b in actual_builds])) |
+ return actual_builds |
+ |
+ |
+################################################################################ |
## Buildbucket RPC. |
@@ -326,3 +384,19 @@ def timestamp_to_datetime(timestamp): |
if isinstance(timestamp, basestring): |
timestamp = int(timestamp) |
return EPOCH + datetime.timedelta(microseconds=timestamp) |
+ |
+ |
+def get_buildset_for(project, issue_id, patchset_id): |
+ # See tag conventions http://cr-buildbucket.appspot.com/#docs/conventions |
Vadim Sh.
2015/09/16 21:57:38
https://
nodir
2015/09/17 17:44:17
Updated all doc links to point to the newer MD doc
|
+ hostname = common.get_preferred_domain(project, default_to_appid=False) |
+ if not hostname: |
+ logging.error( |
+ 'Preferred domain name for this app is not set. ' |
+ 'See PREFERRED_DOMAIN_NAMES in settings.py: %r', hostname) |
+ raise ndb.Return([]) |
+ |
+ return BUILDSET_TAG_FORMAT.format( |
+ hostname=hostname, |
+ issue=issue_id, |
+ patch=patchset_id, |
+ ) |