blob: 8264c20128e6f1059559e57828d7efb8ba5e483b [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Manage tree status."""
from __future__ import print_function
import json
import os
import urllib
from chromite.lib import constants
from chromite.lib import alerts
from chromite.lib import cros_logging as logging
_LUCI_MILO_BUILDBOT_URL = 'https://luci-milo.appspot.com/buildbot'
_LOGDOG_URL = ('https://luci-logdog.appspot.com/v/'
'?s=chromeos/buildbucket/cr-buildbucket.appspot.com/'
'%s/%%2B/steps/%s/0/stdout')
# Will redirect:
# https://ci.chromium.org/b/8914470887449121184
# to:
# https://ci.chromium.org/p/chromeos/builds/b8914470887449121184
_MILO_BUILD_URL = 'https://ci.chromium.org/b/%(buildbucket_id)s'
def GetGardenerEmailAddresses():
"""Get the email addresses of the gardeners.
Returns:
Gardener email addresses.
"""
try:
response = urllib.urlopen(constants.CHROME_GARDENER_URL)
if response.getcode() == 200:
return json.load(response)['emails']
except (IOError, ValueError, KeyError) as e:
logging.error('Could not get gardener emails: %r', e)
return None
def GetHealthAlertRecipients(builder_run):
"""Returns a list of email addresses of the health alert recipients."""
recipients = []
for entry in builder_run.config.health_alert_recipients:
if '@' in entry:
# If the entry is an email address, add it to the list.
recipients.append(entry)
elif entry == constants.CHROME_GARDENER:
# Add gardener email address.
recipients.extend(GetGardenerEmailAddresses())
return recipients
def SendHealthAlert(builder_run, subject, body, extra_fields=None):
"""Send a health alert.
Health alerts are only sent for regular buildbots and Pre-CQ buildbots.
Args:
builder_run: BuilderRun for the main cbuildbot run.
subject: The subject of the health alert email.
body: The body of the health alert email.
extra_fields: (optional) A dictionary of additional message header fields
to be added to the message. Custom field names should begin
with the prefix 'X-'.
"""
if builder_run.InEmailReportingEnvironment():
server = alerts.GmailServer(
token_cache_file=constants.GMAIL_TOKEN_CACHE_FILE,
token_json_file=constants.GMAIL_TOKEN_JSON_FILE)
alerts.SendEmail(subject,
GetHealthAlertRecipients(builder_run),
server=server,
message=body,
extra_fields=extra_fields)
def ConstructMiloBuildURL(buildbucket_id):
"""Return a Milo build URL.
Args:
buildbucket_id: Buildbucket id of the build to link.
Returns:
The fully formed URL.
"""
# Only local tryjobs will not have a buildbucket_id but they also do not have
# a web UI to point at. Generate a fake URL.
buildbucket_id = buildbucket_id or 'fake_bb_id'
return _MILO_BUILD_URL % {'buildbucket_id': buildbucket_id}
def ConstructDashboardURL(buildbot_master_name, builder_name, build_number):
"""Return the dashboard (luci-milo) URL for this run
Args:
buildbot_master_name: Name of buildbot master, e.g. chromeos
builder_name: Builder name on buildbot dashboard.
build_number: Build number for this validation attempt.
Returns:
The fully formed URL.
"""
url_suffix = '%s/%s' % (builder_name, str(build_number))
url_suffix = urllib.quote(url_suffix)
return os.path.join(
_LUCI_MILO_BUILDBOT_URL, buildbot_master_name, url_suffix)
def ConstructLogDogURL(build_number, stage):
return _LOGDOG_URL % (str(build_number), stage)
def ConstructViceroyBuildDetailsURL(build_id):
"""Return the dashboard (viceroy) URL for this run.
Args:
build_id: CIDB id for the master build.
Returns:
The fully formed URL.
"""
_link = ('https://viceroy.corp.google.com/'
'chromeos/build_details?build_id=%(build_id)s')
return _link % {'build_id': build_id}
def ConstructGoldenEyeSuiteDetailsURL(job_id=None, build_id=None):
"""Return the dashboard (goldeneye) URL of suite details for job or build.
Args:
job_id: AFE job id.
build_id: CIDB id for the master build.
Returns:
The fully formed URL.
"""
if job_id is None and build_id is None:
return None
_link = 'http://cros-goldeneye/healthmonitoring/suiteDetails?'
if job_id:
return _link + 'suiteId=%d' % int(job_id)
else:
return _link + 'cidbBuildId=%d' % int(build_id)
def ConstructGoldenEyeBuildDetailsURL(build_id):
"""Return the dashboard (goldeneye) URL for this run.
Args:
build_id: CIDB id for the build.
Returns:
The fully formed URL.
"""
_link = ('http://go/goldeneye/'
'chromeos/healthmonitoring/buildDetails?id=%(build_id)s')
return _link % {'build_id': build_id}
def ConstructAnnotatorURL(build_id):
"""Return the build annotator URL for this run.
Args:
build_id: CIDB id for the master build.
Returns:
The fully formed URL.
"""
_link = ('https://chromiumos-build-annotator.googleplex.com/'
'build_annotations/edit_annotations/master-paladin/%(build_id)s/?')
return _link % {'build_id': build_id}