diff --git a/rrs/tools/rrs_upstream_email.py b/rrs/tools/rrs_upstream_email.py new file mode 100755 index 0000000..a3a7f72 --- /dev/null +++ b/rrs/tools/rrs_upstream_email.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Send email to maintainers about the current status of the recipes. +# +# Copyright (C) 2015 Intel Corporation +# Author: Aníbal Limón +# +# Licensed under the MIT license, see COPYING.MIT for details + +import sys +import os.path +import optparse +import logging +from tabulate import tabulate + +sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__)))) +from common import common_setup, update_repo, get_pv_type +common_setup() +from layerindex import utils + +utils.setup_django() +from django.core.mail import EmailMessage +import settings + +from layerindex.models import LayerItem, LayerBranch, Recipe +from rrs.models import Maintainer, RecipeMaintainerHistory, RecipeMaintainer, \ + RecipeUpstream, RecipeUpstreamHistory + +logger = utils.logger_create('RrsUpstreamEmail') + +LAYERBRANCH_NAME = "master" + +""" + Send email with Recipes that need update. +""" +def send_email(recipes, repodir, options): + header = """This mail was sent out by Recipe reporting system. + +This message list those recipes which need to be upgraded. If maintainers +believe some of them needn't to upgrade this time, they can fill in +RECIPE_NO_UPDATE_REASON_pn-"xxx" in upstream_tracking files to ignore this +recipe remainder until newer upstream version was detected. + +Example: +RECIPE_NO_UPDATE_REASON_pn-"xxx" = "Not upgrade to 2.0 is unstable" + +You can check the detail information at: + +http://packages.yoctoproject.org/ + +""" + + upgradable_count = 0 + no_upgradable_count = 0 + maintainers = Maintainer.objects.all().order_by("name") + + table_headers = ['Package', 'Version', 'Upstream version', + 'Maintainer', 'NoUpgradeReason'] + table = [] + for m in maintainers: + for recipe in recipes.keys(): + recipe_maintainer = recipes[recipe]['maintainer'] + recipe_upstream = recipes[recipe]['upstream'] + + if m.id == recipe_maintainer.maintainer.id: + pn_max_len = 20 + pv_max_len = 20 + name_max_len = 20 + reason_max_len = 30 + + pn = recipe.pn + if len(pn) > pn_max_len: + pn = pn[0:pn_max_len - 3] + "..." + + pv = recipe.pv + if len(pv) > pv_max_len: + pv = pv[0:pv_max_len - 3] + "..." + + pv_up = recipe_upstream.version + if len(pv_up) > pv_max_len: + pv_up = pv_up[0:pv_max_len - 3] + "..." + + name = m.name + if len(name) > name_max_len: + name = name[0:name_max_len - 3] + "..." + + reason = recipe_upstream.no_update_reason + if len(reason) > reason_max_len: + reason = reason[0:reason_max_len - 3] + "..." + + table.append([pn, pv, pv_up, name, reason]) + + upgradable_count = upgradable_count + 1 + if recipe_upstream.no_update_reason: + no_upgradable_count = no_upgradable_count + 1 + + body = tabulate(table, table_headers, tablefmt="simple") + + footer = """ +\nUpgradable count: %d\nUpgradable total count: %d\n +The based commit is: + +%s +Any problem, please contact Anibal Limon +""" % ((upgradable_count - no_upgradable_count), upgradable_count, + utils.runcmd("git log -1", repodir)) + + # + subject = options.subject + from_email = options._from + to_email_list = options.to.split(';') + text_content = header + body + footer + + msg = EmailMessage(subject, text_content, from_email, to_email_list) + msg.send() + +def main(): + parser = optparse.OptionParser( + usage = """ + %prog [options]""") + + parser.add_option("-l", "--layername", + action="store", dest="layername", default=settings.CORE_LAYER_NAME) + parser.add_option("-s", "--subject", + action="store", dest="subject", default=settings.RRS_EMAIL_SUBJECT) + parser.add_option("-f", "--from", + action="store", dest="_from", default=settings.RRS_EMAIL_FROM) + parser.add_option("-t", "--to", + action="store", dest="to", default=settings.RRS_EMAIL_TO) + parser.add_option("-d", "--debug", + help = "Enable debug output", + action="store_const", const=logging.DEBUG, dest="loglevel", default=logging.INFO) + parser.add_option("-q", "--quiet", + help = "Hide all output except error messages", + action="store_const", const=logging.ERROR, dest="loglevel") + + options, args = parser.parse_args(sys.argv) + + recipes = {} + layer = LayerItem.objects.filter(name = options.layername)[0] + + # get recipes for send email + layerbranch = layer.get_layerbranch(LAYERBRANCH_NAME) + recipe_upstream_history = RecipeUpstreamHistory.get_last() + if recipe_upstream_history is None: + logger.warn('I don\'t have Upstream information yet, run update.py script') + sys.exit(1) + + recipe_maintainer_history = RecipeMaintainerHistory.get_last() + if recipe_maintainer_history is None: + logger.warn('I don\'t have Maintainership information yet,' + + ' run rrs_maintainer_history.py script') + sys.exit(1) + + for recipe in Recipe.objects.filter(layerbranch = layerbranch): + recipe_upstream_query = RecipeUpstream.objects.filter(recipe = + recipe, history = recipe_upstream_history) + if recipe_upstream_query and recipe_upstream_query[0].status == 'N': + recipes[recipe] = {} + + recipe_maintainer = RecipeMaintainer.objects.filter(recipe = + recipe, history = recipe_maintainer_history)[0] + recipes[recipe]['maintainer'] = recipe_maintainer + recipes[recipe]['upstream'] = recipe_upstream_query[0] + + repodir = os.path.join(settings.LAYER_FETCH_DIR, layer.get_fetch_dir()) + + send_email(recipes, repodir, options) + +if __name__ == "__main__": + main()