blob: c525b95e5f79dbd4db504cf535206bb7210b7c4c [file] [log] [blame]
#!/usr/bin/env python
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
import argparse
import datetime
import time
import email
import email.mime.text
import json
import os
import subprocess
import sh
import smtplib
import sys
def get_daily_query(status, project):
return 'project:%s branch:master status:%s -age:%dh' % (project, status, args['age'])
def get_digest(query):
digest = ''
freshers = ''
do_module = []
about = ''
# we want first time contributors on new changes for core
do_fresh = (query.split(':')[1].split(' ')[0] == 'core' and
query.split(':')[3].split(' ')[0] == 'open' and
query.split(':')[3].split(' ')[1] == '-age' )
if do_fresh:
all_users = init_freshers()
do_module = ['--files', '--patch-sets']
for line in subprocess.check_output(['ssh', args['gerrit'], 'gerrit', 'query'] + do_module +
['--format=JSON','--', "'" + query +"'"]).strip().splitlines():
change = json.loads(line)
if 'url' in change.keys():
if do_fresh: # we are in new changes
fpaths = (set([fileobj['file'] for fileobj in change['patchSets'][-1]['files']]))
fpaths.remove('/COMMIT_MSG')
# we assume gerrit replies with no leading slash
# if no subfolder, module is "build"
about = '\n about module ' + ', '.join(sorted(set([p.split('/')[0]
if '/' in p else 'build' for p in fpaths])))
if do_fresh and change['owner']['name'].encode('utf8') not in all_users:
freshers += '+ %s\n in %s from %s%s\n' % (change['subject'][:73],
change['url'], change['owner']['name'], about)
else:
digest += '+ %s\n in %s from %s%s\n' % (change['subject'][:73],
change['url'], change['owner']['name'], about)
if freshers != '':
digest = ('~~~~ First time contributors doing great things! ~~~~\n' + freshers +
"~~~~ End of freshness ~~~~\n\n" + digest )
if digest == '':
digest = 'None'
return digest
def init_freshers():
repo_dir='/var/tmp/core.git'
if not os.path.exists(repo_dir):os.makedirs(repo_dir)
os.chdir(repo_dir)
if not os.path.exists(os.path.join(repo_dir,'config')):
subprocess.call(['git','clone','--bare','https://git.libreoffice.org/core',repo_dir])
else:
subprocess.call(['git','fetch','origin','master:master'])
return subprocess.check_output(['git','shortlog','-s','master'])
def get_project_body(project):
none = True
body = ('* Open changes on master for project %s changed in the last %d hours:\n\n'
% (project, args['age']))
dig = get_digest(get_daily_query('open', project))
if dig != 'None': none = False
body += dig
body += ('\n\n* Merged changes on master for project %s changed in the last %d hours:\n\n'
% (project, args['age']))
dig = get_digest(get_daily_query('merged', project))
if dig != 'None': none = False
body += dig
body += ('\n\n* Abandoned changes on master for project %s changed in the last %d hours:\n\n'
% (project, args['age']))
dig = get_digest(get_daily_query('abandoned', project))
if dig != 'None': none = False
body += dig
body += '\n\n* Open changes needing tweaks, but being untouched for more than a week:\n\n'
dig = get_digest('project:%s branch:master status:open (label:Code-Review<=-1 OR label:Verified<=-1) age:1w' % project)
if dig != 'None': none = False
body += dig
if none: return ""
else: return body
def send_message_for_project(project):
now = datetime.datetime.now()
nothing = 'Nothing moved in the project for the last %d hours' % args['age']
body = 'Moin!\n\n'
if project == 'submodules':
dict = get_project_body('dictionaries')
tran = get_project_body('translations')
help = get_project_body('help')
if dict + tran + help == "": return 'Nothing'
body += '\n\n~~~~~~ Project dictionaries ~~~~~~\n\n'
body += dict if bool(dict) else nothing
body += '\n\n~~~~~~ Project translations ~~~~~~\n\n'
body += tran if bool(tran) else nothing
body += '\n\n~~~~~~ Project help ~~~~~~\n\n'
body += help if bool(help) else nothing
else:
proj = get_project_body(project)
if proj == "": return 'Nothing'
body += proj
body += '''
Best,
Your friendly LibreOffice Gerrit Digest Mailer
Note: The bot generating this message can be found and improved here:
https://git.libreoffice.org/dev-tools/tree/master/gerritbot/send-daily-digest'''
msg = email.mime.text.MIMEText(body, 'plain', 'UTF-8')
msg['From'] = msg_from
msg['To'] = msg_to[0]
msg['Cc'] = ', '.join(msg_to[1:]) # Works only if at least 2 items in tuple
msg['Date'] = email.utils.formatdate(time.mktime((now.timetuple())))
msg['Subject'] = 'LibreOffice Gerrit News for %s on %s' % (project, now.date().isoformat())
msg['Reply-To'] = msg_to[0]
msg['X-Mailer'] = 'LibreOfficeGerritDigestMailer 1.1'
server.sendmail(msg_from, msg_to, str(msg))
return project
if __name__ == '__main__':
parser = argparse.ArgumentParser('gerrit daily digest generator')
parser.add_argument('-g', '--gerrit', help='(i. e. logerrit or gerrit.libreoffice.org, use the alias in your ~/.ssh(config with your public key)', required=True)
parser.add_argument('-r', '--repo', help='(A single project from gerrit (core, ...) or "submodules" (... of core) or "all" (core + dev-tools + submodules)', required=False, default='all')
parser.add_argument('-a', '--age', help='(A number expressed in hours.)', required=False, default=25)
args=vars(parser.parse_args())
msg_from = 'gerrit@libreoffice.org'
msg_to = ['libreoffice@lists.freedesktop.org', 'qa@fr.libreoffice.org']
server = smtplib.SMTP('localhost')
if args['repo'] == 'all':
send_message_for_project('core')
send_message_for_project('submodules')
send_message_for_project('dev-tools')
else:
send_message_for_project(args['repo'])
server.quit()
# vim: set et sw=4 ts=4: