Пример #1
0
def send_to_stage(push):
    assert push.state in ('accepting', 'onstage')

    checkedin_requests = query.push_requests(push, state='checkedin')
    if checkedin_requests:
        if push.state != 'onstage':
            push.state = 'onstage'

            push.put()

        for request in checkedin_requests:
            request.state = 'onstage'
            if request.no_testing:
                set_request_tested(request, bust_caches=False)
            else:
                owner_email = request.owner.email()

                send_mail(
                    to=[owner_email, config.mail_to],
                    subject='Re: ' + request.subject,
                    body='Please check your changes on stage.\n' + config.url(push.uri))

                im_fields = dict(
                    pushmaster_email=html_escape(push.owner.email()),
                    pushmaster_name=html_escape(push.owner.nickname()),
                    request_subject=html_escape(request.subject),
                    uri=html_escape(config.url(push.uri)),
                    )
                send_im(owner_email, '<a href="mailto:%(pushmaster_email)s">%(pushmaster_name)s</a> requests that you check your changes on stage for <a href="%(uri)s">%(request_subject)s</a>.' % im_fields)
                request.put()

        push.bust_requests_cache()

    return push
Пример #2
0
    def get(self, push_id):
        push = None

        if push_id == 'current':
            push = query.current_push()
            self.redirect(push.uri if push else '/pushes')
            return

        try:
            push = model.Push.get(push_id)
        except BadKeyError:
            raise HTTPStatusCode(httplib.NOT_FOUND)

        current_user = users.get_current_user()
        pending_requests = query.pending_requests(not_after=util.tznow().date()) if current_user == push.owner else []

        if 'application/json' in self.get_request_header_list('Accept', default='*/*'):
            requests = query.push_requests(push)
            push_div = self.render_push_div(current_user, push, requests, pending_requests)
            response = {'push': dict(key=unicode(push.key()), state=push.state), 'html': unicode(push_div)}
            self.response.headers['Vary'] = 'Accept'
            self.response.headers['Content-Type'] = 'application/json'
            self.response.headers['Cache-Control'] = 'no-store'
            self.response.out.write(json.dumps(response))

        else:
            doc = self.render_doc(current_user, push, pending_requests)
            self.response.out.write(unicode(doc))
Пример #3
0
    def get(self, push_id):
        push = None

        if push_id == 'current':
            push = query.current_push()
            self.redirect(push.api_uri if push else '/pushes')
            return

        try:
            push = model.Push.get(push_id)
        except BadKeyError:
            raise HTTPStatusCode(httplib.NOT_FOUND)

        current_user = users.get_current_user()
        pending_requests = query.pending_requests(not_after=util.tznow().date()) if current_user == push.owner else []

        requests = query.push_requests(push)

        push_info = self.render_push_info(push, requests)
        request_info = self.render_request_info(pending_requests)

        response = {'push': push_info, 'pending_requests': request_info}

        self.response.headers['Vary'] = 'Accept'
        self.response.headers['Content-Type'] = 'application/json'
        self.response.headers['Cache-Control'] = 'no-store'

        self.response.out.write(json.dumps(response))
Пример #4
0
    def receive(self, mail_message):
        sender = mail_message.sender
        logging.debug('got mail from %s', sender)

        text_bodies = [body for content_type, body in mail_message.bodies('text/plain')]
        if not text_bodies:
            return
        text_body = text_bodies[0] # TODO: support multiple bodies

        to = mail_message.to
        match = self.push_key_address_re.match(to)
        if match is None:
            logging.warning('failed to match push address: %s', to)
            return

        try:
            push_key = match.group(1)
            push = model.Push.get(push_key)
            requester_emails = list(set([request.owner.email() for request in query.push_requests(push)]))
            kw = dict(sender=sender, to=requester_emails, subject=mail_message.subject, body=text_body, reply_to=sender)
            logging.info('sending push mail: %r', kw)
            util.send_mail(**kw)
            
        except BadKeyError:
            logging.warning('failed to find push %s', push_key)
Пример #5
0
    def get(self, datestr):
        from_date, to_date = report_date_range(datestr)

        doc = common.Document(title='pushmaster: reports')
        doc.body(T.h1('Report for ', from_date.strftime('%e %b %Y'), ' - ', to_date.strftime('%e %b %Y')))

        pushes = query.pushes_for_the_week_of(from_date)
        for push in pushes:
            pushdiv = T.div(class_='push')
            pushdiv(T.h2(
                    T.a(href=push.uri)(
                        push.ltime.replace(tzinfo=timezone.UTC()).astimezone(config.timezone).strftime('%a, %l:%M %p, %e %b %Y'),
                        T.span(' '),
                        push.name or '',
                        ), 
                    T.span(' by '),
                    common.display_user_email(push.owner),
                    ))
            reqlist = T.ol(class_='requests')
            for request in query.push_requests(push):
                reqlist(common.request_item(request))
            pushdiv(reqlist)
            doc.body(pushdiv)

        doc.body(common.jquery_js, common.jquery_ui_js, common.pushmaster_js)

        doc.serialize(self.response.out)
Пример #6
0
 def render(self, push, current_user, pending_requests):
     requests = query.push_requests(push)
     push_div = self.render_push_div(current_user, push, requests, pending_requests)
     response = {'push': dict(key=unicode(push.key()), state=push.state), 'html': unicode(push_div)}
     self.response.headers['Vary'] = 'Accept'
     self.response.headers['Content-Type'] = 'application/json'
     self.response.headers['Cache-Control'] = 'no-store'
     json.dump(response, self.response.out)
Пример #7
0
    def render_doc(self, current_user, push, pending_requests):
        doc = common.Document(title='pushmaster: push: ' + logic.format_datetime(push.ptime))
        requests = query.push_requests(push)
        push_div = self.render_push_div(current_user, push, requests, pending_requests)
        doc.body(push_div)

        doc.body(common.jquery_js, common.jquery_ui_js, common.pushmaster_js, common.script('/js/push.js'))
        push_json = ScriptCData('this.push = %s;' % json.dumps(dict(key=str(push.key()), state=push.state)))
        doc.head(T.script(type='text/javascript')(push_json))

        return doc
Пример #8
0
def push_item(push):
    requests = query.push_requests(push)
    return T.li(class_='push')(
        T.div(
            common.display_datetime(push.ptime),
            T.a(href=push.uri)(push.name or 'push'),
            common.user_home_link(push.owner, logic.user_info(push.owner)),
            T.span(class_='state')(common.display_push_state(push)),
            class_='headline',
            ),
        T.ol(map(common.request_item, requests)) if requests else T.div('No requests.'),
    )
Пример #9
0
    def render_doc(self, push, current_user, pending_requests):
        doc = common.Document(title='pushmaster: push: %s %s' % (util.format_datetime(push.ptime), push.name))
        doc.funcbar(T.span('|', class_='sep'), common.push_email(push, 'Send Mail to Requesters'))

        requests = query.push_requests(push)
        push_div = self.render_push_div(current_user, push, requests, pending_requests)
        doc.body(push_div)

        doc.scripts(common.script('/js/push.js'))
        push_json = ScriptCData('this.push = %s;' % json.dumps(dict(key=str(push.key()), state=push.state)))
        doc.head(T.script(type='text/javascript')(push_json))

        return doc
Пример #10
0
def force_live(push):
    for request in query.push_requests(push):
        request.state = 'live'

        request.put()
    push.bust_requests_cache()

    push.state = 'live'
    push.ltime = push.mtime

    push.put()
    
    return push
Пример #11
0
def abandon_push(push):
    assert push.state in ('accepting', 'onstage')

    push.state = 'abandoned'
    for request in query.push_requests(push):
        request.state = 'requested'
        request.push = None
        request.put()

    push.put()
    query.bust_request_caches()
    push.bust_requests_cache()

    return push
Пример #12
0
    def get(self, datestr=None):
        if datestr:
            from_date, to_date = report_date_range(datestr)
        else:
            for_date = last_monday_datetime() - datetime.timedelta(days=7)
            return self.redirect('/lastweek/' + for_date.strftime('%Y%m%d'))

        pushes = query.pushes_for_the_week_of(from_date)
        requests = []
        for push in pushes:
            requests.extend(query.push_requests(push))
        requests = sorted(requests, key=lambda r: r.mtime)

        doc = common.Document(title='pushmaster: weekly report: ' + datestr)

        teams_list = T.ul(class_='teams')
        doc(teams_list)

        nothing_messages_list = None

        for team in config.report_users:
            team_item = T.li(class_='team')(T.h3(team['name']))
            teams_list(team_item)

            devs_list = T.ul(class_='devs')
            team_item(devs_list)
            for dev in sorted(team['dev']):
                dev_item = T.li(class_='dev')(T.h4(dev))
                devs_list(dev_item)
                dev_requests = filter(lambda r: r.owner.nickname() == dev, requests)
                if dev_requests:
                    requests_list = T.ol(class_='requests')(map(common.request_item, dev_requests))
                    dev_item(requests_list)
                else:
                    # lazy (re)initialize random messages
                    if not nothing_messages_list:
                        nothing_messages_list = list(config.nothing_messages)
                        import random
                        random.shuffle(nothing_messages_list)

                    dev_item(T.div(nothing_messages_list.pop(), class_='nothing'))


            if 'prod' in team:
                team_item(T.h4('PM: ' if len(team['prod']) == 1 else 'PMs: ', ', '.join(team['prod']), class_='pm'))
        
        doc.serialize(self.response.out)
Пример #13
0
def send_to_live(push):
    assert push.state == 'onstage'
    requests = query.push_requests(push)
    for request in requests:
        assert request.state in ('tested', 'live')

    for request in requests:
        request.state = 'live'
        request.put()

    push.state = 'live'
    push.ltime = datetime.datetime.utcnow()

    push.put()
    push.bust_requests_cache()

    return push
Пример #14
0
def set_request_tested(request, bust_caches=True):
    assert request.state == 'onstage'
    push = request.push
    assert push

    request.state = 'tested'
    request.put()

    if bust_caches:
        push.bust_requests_cache()
    
    push_owner_email = push.owner.email()
    
    send_mail(
        to=[push_owner_email, config.mail_to],
        subject='Re: ' + request.subject,
        body='Looks good to me.\n' + config.url(push.uri))

    if all(request.state == 'tested' for request in query.push_requests(push)):
        send_im(push_owner_email, 'All changes for <a href="%s">the push</a> are tested on stage.' % config.url(push.uri))

    return request