summaryrefslogtreecommitdiffstats
path: root/packages/management/commands/signoff_report.py
blob: ddf930db5473e007eceb290f6e5db6c616698569 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# -*- coding: utf-8 -*-
"""
signoff_report command

Send an email summarizing the state of outstanding signoffs for the given
repository.

Usage: ./manage.py signoff_report <email> <repository>
"""

from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.core.management.base import BaseCommand, CommandError
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.db.models import Count
from django.template import loader, Context

from collections import namedtuple
from datetime import timedelta
import logging
from operator import attrgetter
import sys

from main.models import Repo
from main.utils import utc_now
from packages.models import Signoff
from packages.utils import get_signoff_groups

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s -> %(levelname)s: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
    stream=sys.stderr)
logger = logging.getLogger()

class Command(BaseCommand):
    args = "<email> <repository>"
    help = "Send a signoff report for the given repository."

    def handle(self, *args, **options):
        v = int(options.get('verbosity', None))
        if v == 0:
            logger.level = logging.ERROR
        elif v == 1:
            logger.level = logging.INFO
        elif v == 2:
            logger.level = logging.DEBUG

        if len(args) != 2:
            raise CommandError("email and repository must be provided")

        return generate_report(args[0], args[1])

def generate_report(email, repo_name):
    repo = Repo.objects.get(name__iexact=repo_name)
    # Collect all existing signoffs for these packages
    signoff_groups = sorted(get_signoff_groups([repo]),
            key=attrgetter('target_repo', 'arch', 'pkgbase'))
    disabled = []
    bad = []
    complete = []
    incomplete = []
    new = []
    old = []

    new_hours = 24
    old_days = 14
    now = utc_now()
    new_cutoff = now - timedelta(hours=new_hours)
    old_cutoff = now - timedelta(days=old_days)

    if len(signoff_groups) == 0:
        # no need to send an email at all
        return

    for group in signoff_groups:
        spec = group.specification
        if spec.known_bad:
            bad.append(group)
        elif not spec.enabled:
            disabled.append(group)
        elif group.approved():
            complete.append(group)
        else:
            incomplete.append(group)

        if group.package.last_update > new_cutoff:
            new.append(group)
        if group.package.last_update < old_cutoff:
            old.append(group)

    old.sort(key=attrgetter('last_update'))

    proto = 'https'
    domain = Site.objects.get_current().domain
    signoffs_url = '%s://%s%s' % (proto, domain, reverse('package-signoffs'))

    # and the fun bit
    Leader = namedtuple('Leader', ['user', 'count'])
    leaders = Signoff.objects.filter(created__gt=new_cutoff,
            revoked__isnull=True).values_list('user').annotate(
                    signoff_count=Count('pk')).order_by('-signoff_count')[:5]
    users = User.objects.in_bulk([l[0] for l in leaders])
    leaders = (Leader(users[l[0]], l[1]) for l in leaders)

    subject = 'Signoff report for [%s]' % repo.name.lower()
    t = loader.get_template('packages/signoff_report.txt')
    c = Context({
        'repo': repo,
        'signoffs_url': signoffs_url,
        'disabled': disabled,
        'bad': bad,
        'all': signoff_groups,
        'incomplete': incomplete,
        'complete': complete,
        'new': new,
        'new_hours': new_hours,
        'old': old,
        'old_days': old_days,
        'leaders': leaders,
    })
    from_addr = 'Arch Website Notification <nobody@archlinux.org>'
    send_mail(subject, t.render(c), from_addr, [email])

# vim: set ts=4 sw=4 et: