Skip to content

Commit

Permalink
Merge 315d8a3 into c575487
Browse files Browse the repository at this point in the history
  • Loading branch information
armenzg committed Jul 31, 2015
2 parents c575487 + 315d8a3 commit 4e16251
Show file tree
Hide file tree
Showing 11 changed files with 190 additions and 23 deletions.
6 changes: 3 additions & 3 deletions mozci/mozci.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@

import logging

from mozci.platforms import determine_upstream_builder, is_downstream, filter_buildernames,\
build_talos_buildernames_for_repo
from mozci.platforms import determine_upstream_builder, is_downstream, \
filter_buildernames, build_talos_buildernames_for_repo
from mozci.sources import allthethings, buildapi, buildjson, pushlog
from mozci.query_jobs import PENDING, RUNNING, SUCCESS, UNKNOWN,\
from mozci.query_jobs import PENDING, RUNNING, SUCCESS, UNKNOWN, \
COALESCED, BuildApi, TreeherderApi
from mozci.utils.misc import _all_urls_reachable
from mozci.utils.transfer import path_to_file, clean_directory
Expand Down
28 changes: 28 additions & 0 deletions mozci/scheduling.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
This module allow us to interact with the various scheduling systems
in a very generic manner.
Defined in here:
* BaseSchedulingClient
* TaskclusterSchedulingClient
"""
from __future__ import absolute_import
from abc import ABCMeta, abstractmethod

from mozci.sources import taskcluster_


class BaseSchedulingClient:
""" Base class for common scheduling methods. """

__metaclass__ = ABCMeta

@abstractmethod
def retrigger(self, uuid, **kwargs):
pass


class TaskclusterSchedulingClient(BaseSchedulingClient):

def retrigger(self, uuid, **kwargs):
taskcluster_.retrigger_task(task_id=uuid, **kwargs)
5 changes: 2 additions & 3 deletions mozci/scripts/alltalos.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,9 @@ def main():
options = parse_args()

if options.debug:
LOG = setup_logging(logging.DEBUG)
LOG.info("Setting DEBUG level")
setup_logging(logging.DEBUG)
else:
LOG = setup_logging(logging.INFO)
setup_logging()

pgo = False
if options.repo_name in PGO_ONLY_BRANCHES or options.pgo:
Expand Down
20 changes: 9 additions & 11 deletions mozci/scripts/generate_triggercli.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,30 @@
3) Remove the --dry-run parameter and actually trigger intermittents via trigger.py script.
"""
import bugsy
import logging
import os

from argparse import ArgumentParser

import bugsy

from mozci.mozci import query_repo_name_from_buildername
from mozci.utils.misc import setup_logging

bugzilla = bugsy.Bugsy()
logging.basicConfig(format='%(asctime)s %(levelname)s:\t %(message)s',
datefmt='%m/%d/%Y %I:%M:%S')
LOG = logging.getLogger()
LOG.setLevel(logging.INFO)
LOG = setup_logging()


def main():
global LOG

options = parse_args()
bugs = []
assert options.bug_no or options.test_name, \
"Either call this with --bug-no or with --test-name"

if options.debug:
LOG.setLevel(logging.DEBUG)
logging.getLogger("requests").setLevel(logging.DEBUG)
LOG.info("Setting DEBUG level")
else:
LOG.setLevel(logging.INFO)
# requests is too noisy and adds no value
LOG = setup_logging(logging.DEBUG)

if options.bug_no:
bugs.append(options.bug_no)
Expand Down
49 changes: 49 additions & 0 deletions mozci/scripts/misc/taskcluster_retrigger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'''
taskcluster_retrigger.py allows you to retrigger a task from TaskCluster
past its deadline.
'''
import logging

from argparse import ArgumentParser

from mozci.scheduling import TaskclusterSchedulingClient
from mozci.utils.misc import setup_logging


def main():
parser = ArgumentParser()
parser.add_argument('-r',
action="store_true",
dest="retrigger",
help="It retriggers a TaskCluster task.")

parser.add_argument("--debug",
action="store_true",
dest="debug",
help="set debug for logging.")

parser.add_argument("--dry-run",
action="store_true",
dest="dry_run",
help="Dry run. No real actions are taken.")

parser.add_argument('task_ids',
metavar='task_id',
type=str,
nargs='+',
help='Task IDs to work with.')

options = parser.parse_args()

if options.debug:
setup_logging(logging.DEBUG)
else:
setup_logging()

if options.retrigger:
sch = TaskclusterSchedulingClient()
for t_id in options.task_ids:
sch.retrigger(uuid=t_id, dry_run=options.dry_run)

if __name__ == "__main__":
main()
1 change: 0 additions & 1 deletion mozci/scripts/trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ def main():

if options.debug:
LOG = setup_logging(logging.DEBUG)
LOG.info("Setting DEBUG level")
else:
LOG = setup_logging(logging.INFO)

Expand Down
1 change: 0 additions & 1 deletion mozci/scripts/triggerbyfilters.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def main():

if options.debug:
LOG = setup_logging(logging.DEBUG)
LOG.info("Setting DEBUG level")
else:
LOG = setup_logging(logging.INFO)

Expand Down
3 changes: 2 additions & 1 deletion mozci/sources/buildapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

import requests

from mozci.utils.authentication import get_credentials, remove_credentials, AuthenticationError
from mozci.utils.authentication import get_credentials, remove_credentials, \
AuthenticationError
from mozci.utils.transfer import path_to_file

LOG = logging.getLogger('mozci')
Expand Down
86 changes: 86 additions & 0 deletions mozci/sources/taskcluster_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
"""
This module allow us to interact with taskcluster through the taskcluster
client.
"""
import datetime
import json
import logging
import traceback

import taskcluster as taskcluster_client

LOG = logging.getLogger('mozci')
TASKCLUSTER_TOOLS_HOST = 'https://tools.taskcluster.net'


def retrigger_task(task_id, dry_run=False):
""" Given a task id (our uuid) we query it and build
a new task based on the old one which we schedule on TaskCluster.
We don't call the rerun API since we can't rerun a task past
its deadline, instead we create a new task with a new taskGroupId,
expiration, creation and deadline values.
task_id (int) - ID that identifies a task on Taskcluster
dry_run (bool) - Default to False. If True, it won't trigger
a task.
returns - None for dry_run case, -1 for any failure a new task id (int)
in a succesful retrigger.
http://docs.taskcluster.net/queue/api-docs/#createTask
"""
one_year = 365
new_task_id = None

try:
queue = taskcluster_client.Queue()
task = queue.task(task_id)

LOG.debug("Original task: (Limit 1024 char)")
LOG.debug(str(json.dumps(task))[:1024])
new_task_id = taskcluster_client.slugId()

artifacts = task['payload'].get('artifacts', {})
for artifact, definition in artifacts.iteritems():
definition['expires'] = taskcluster_client.fromNow('%s days' % one_year)

# The task group will be identified by the ID of the only
# task in the group
task['taskGroupId'] = new_task_id
# TC workers create public logs which are 365 days; if the task expiration
# date is the same or less than that we won't have logs for the task
task['expires'] = taskcluster_client.fromNow('%s days' % (one_year + 1))
task['created'] = taskcluster_client.stringDate(datetime.datetime.utcnow())
task['deadline'] = taskcluster_client.fromNow('24 hours')

LOG.debug("Contents of new task: (Limit 1024 char)")
LOG.debug(str(task)[:1024])

if not dry_run:
LOG.info("Attempting to schedule new task with task_id: {}".format(new_task_id))
result = queue.createTask(new_task_id, task)
LOG.debug(result)
LOG.info("{}/task-inspector/#{}".format(TASKCLUSTER_TOOLS_HOST, new_task_id))
else:
LOG.info("Dry-run mode: Nothing was retriggered.")

except taskcluster_client.exceptions.TaskclusterRestFailure as e:
traceback.print_exc()
new_task_id = -1

except taskcluster_client.exceptions.TaskclusterAuthFailure as e:
# Hack until we fix it in the issue
if str(e) == "Authorization Failed":
LOG.error("The taskclaster client that you specified is lacking "
"the right set of scopes.")
LOG.error("Run this same command with --debug and you will see "
"the missing scopes (the output comes from the "
"taskcluster python client)")
elif str(e) == "Authentication Error":
LOG.error("Make sure that you create permanent credentials and you "
"set these environment variables: TASKCLUSTER_CLIENT_ID & "
"TASKCLUSTER_ACCESS_TOKEN")
new_task_id = -1

return new_task_id
13 changes: 10 additions & 3 deletions mozci/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def _all_urls_reachable(urls):
return True


def setup_logging(level):
def setup_logging(level=logging.INFO):
"""
Save every message (including debug ones) to ~/.mozilla/mozci/mozci-debug.log.
Expand All @@ -53,23 +53,30 @@ def setup_logging(level):
As seen in:
https://docs.python.org/2/howto/logging-cookbook.html#logging-to-multiple-destinations
"""
LOG = logging.getLogger('mozci')
LOG = logging.getLogger()

# Handler 1 - Store all debug messages in a specific file
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(levelname)s:\t %(message)s',
datefmt='%m/%d/%Y %I:%M:%S',
filename=path_to_file('mozci-debug.log'),
filemode='w')

# Handler 2 - Console output
console = logging.StreamHandler()
console.setLevel(level)
# console does not use the same formatter specified in basicConfig
# we have to set it again
formatter = logging.Formatter('%(asctime)s %(levelname)s:\t %(message)s',
formatter = logging.Formatter('%(asctime)s %(name)s %(levelname)s:\t %(message)s',
datefmt='%m/%d/%Y %I:%M:%S')
console.setFormatter(formatter)
LOG.addHandler(console)

if level != logging.DEBUG:
# requests is too noisy and adds no value
logging.getLogger("requests").setLevel(logging.WARNING)

if level == logging.DEBUG:
LOG.info("Setting DEBUG level")

return LOG
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
'progressbar>=2.3',
'requests>=2.5.1',
'keyring>=5.3',
'taskcluster>=0.0.22',
'treeherder-client>=1.4'
],

Expand Down

0 comments on commit 4e16251

Please sign in to comment.