aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--deployment/mgagit/files/git_multimail.py2
-rw-r--r--deployment/mgagit/manifests/init.pp2
-rwxr-xr-xdeployment/mgagit/templates/git-post-receive-hook198
3 files changed, 105 insertions, 97 deletions
diff --git a/deployment/mgagit/files/git_multimail.py b/deployment/mgagit/files/git_multimail.py
index 01acf6da..39aa1458 100644
--- a/deployment/mgagit/files/git_multimail.py
+++ b/deployment/mgagit/files/git_multimail.py
@@ -1,4 +1,4 @@
-#! /usr/bin/env python2
+#! /usr/bin/env python3
__version__ = '1.7.dev'
diff --git a/deployment/mgagit/manifests/init.pp b/deployment/mgagit/manifests/init.pp
index 2ad9cd64..8aa621ef 100644
--- a/deployment/mgagit/manifests/init.pp
+++ b/deployment/mgagit/manifests/init.pp
@@ -19,7 +19,7 @@ class mgagit(
$reposconf_dir = "${git_homedir}/repos-config"
$vhostdir = "${git_homedir}/www"
- package { ['mgagit', 'gitolite', 'python-bugz']:
+ package { ['mgagit', 'gitolite', 'python3-bugz']:
ensure => installed,
}
diff --git a/deployment/mgagit/templates/git-post-receive-hook b/deployment/mgagit/templates/git-post-receive-hook
index 087f9133..f8573dd4 100755
--- a/deployment/mgagit/templates/git-post-receive-hook
+++ b/deployment/mgagit/templates/git-post-receive-hook
@@ -1,18 +1,21 @@
-#!/usr/bin/python2
+#!/usr/bin/python3
+import configparser
import os
import re
import sys
+import urllib.error
+import urllib.parse
+import urllib.request
+import xmlrpc.client
+from dataclasses import dataclass
LIBDIR = '<%= @gitolite_commonhooksdir %>'
sys.path.insert(0, LIBDIR)
-import git_multimail
-
-import xmlrpclib
-from bugz.bugzilla import BugzillaProxy
+import bugz.settings
-import urllib2
+import git_multimail
# When editing this list, remember to edit the same list in
# modules/cgit/templates/filter.commit-links.sh
@@ -30,8 +33,17 @@ COMMIT_REPLACE = 'https://gitweb.mageia.org/%s/commit/?id=%s'
MAGEIA_BUGZILLA_URL = 'https://bugs.mageia.org/xmlrpc.cgi'
MAGEIA_BUGZILLA_PASSWORD_FILE = '.gitzilla-password'
-MAGEIA_BUGZILLA_AUTHTOKEN_FILE = '.gitzilla-authtoken'
+MAGEIA_BUGZILLA_APIKEY_FILE = '.gitzilla-apikey' # this holds a Bugzilla API key
+GITWEB_UPDATE_URL = 'https://gitweb.mageia.org:8000'
+
+# Bugzilla user
+USER_LOGIN = 'bot'
+
+# Recipient of i18n notifications
+I18N_MAIL = 'i18n-reports@ml.mageia.org'
+# Set to 1..3 for debug logging (WARNING: this will show passwords to git committers!)
+DEBUG = 0
git_multimail.FOOTER_TEMPLATE = """\
@@ -61,6 +73,14 @@ Auto-Submitted: auto-generated
REPO_NAME_RE = re.compile(r'^/git/(?P<name>.+?)(?:\.git)?$')
+
+
+# Log a debug message when logging is enabled
+def debug(s, *a):
+ if DEBUG > 0:
+ print(s % a)
+
+
def repo_shortname():
basename = os.path.abspath(git_multimail.get_git_dir())
m = REPO_NAME_RE.match(basename)
@@ -75,64 +95,55 @@ def repo_shortname():
class MageiaEnvironment(git_multimail.Environment):
def get_repo_shortname(self):
return repo_shortname()
+
+
git_multimail.Environment = MageiaEnvironment
# Override the Revision class to inject gitweb/cgit links and any referenced
# bug URLs
class MageiaLinksRevision(git_multimail.Revision):
- bz = None
- tokenfile = None
- token = None
+ def __init__(self, reference_change, rev, num, tot):
+ super().__init__(reference_change, rev, num, tot)
+ self.bz = None
def bugzilla_init(self):
- if self.bz is None:
- self.tokenfile = os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_AUTHTOKEN_FILE)
+ if not self.bz:
+ tokenfile = os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_APIKEY_FILE)
+ token = None
+ try:
+ token = open(tokenfile, 'r').readline().rstrip()
+ except IOError:
+ # Assume username/password will be used instead
+ pass
+
+ passwordfile = os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_PASSWORD_FILE)
+ pword = None
try:
- token = open(self.tokenfile, 'r').readline().rstrip()
- if token:
- self.token = token
+ pword = open(passwordfile, 'r').readline().rstrip()
except IOError:
+ print('Error: no Bugzilla credentials available; trying anyway')
+ # There's no real point in continuing, but why not
+
+ class ConfigSettings:
pass
- self.bz = BugzillaProxy(MAGEIA_BUGZILLA_URL)
- return self.bz
-
- def bugzilla_login(self):
- params = {
- 'login': 'bot',
- 'password': open(os.path.join(os.environ['HOME'], MAGEIA_BUGZILLA_PASSWORD_FILE), 'r').readline().rstrip(),
- 'remember': True
- }
- result = self.bz.User.login(params)
- if 'token' in result:
- self.token = result['token']
- if self.tokenfile is not None:
- fd = open(self.tokenfile, 'w')
- fd.write(self.token)
- fd.write('\n')
- fd.close()
- os.chmod(self.tokenfile, 0600)
- return True
- return False
-
- def bugzilla_call(self, method, *args):
- """Attempt to call method with args. Log in if authentication is required.
- """
- try:
- if self.token is not None:
- args[0]['token'] = self.token
- return method(*args)
- except xmlrpclib.Fault, fault:
- # Fault code 410 means login required
- if fault.faultCode == 410 and self.bugzilla_login():
- args[0]['token'] = self.token
- return method(*args)
- raise
+ cfg = ConfigSettings()
+ cfg.connection = 'Mageia'
+ if token:
+ # If an API key is found, that will be used instead of user/password
+ cfg.key = token
+ cfg.user = USER_LOGIN
+ cfg.password = pword
+ cfg.base = MAGEIA_BUGZILLA_URL
+ cfg.debug = DEBUG
+
+ cfile = configparser.ConfigParser()
+ cfile.add_section(cfg.connection)
+ self.bz = bugz.settings.Settings(cfg, cfile)
def generate_email_body(self, push):
"""Show this revision."""
-
output = git_multimail.read_git_lines(
['log'] + self.environment.commitlogopts + ['-1', self.rev.sha1],
keepends=True,
@@ -140,6 +151,9 @@ class MageiaLinksRevision(git_multimail.Revision):
bugs = {}
commit = None
idx = 0
+ # Modify the mail output on-the-fly to add links; this is sensitive to
+ # the mail format produced by git_multimail. Also, update Mageia
+ # Bugzilla if a bug reference is found.
for line in output:
idx += 1
if line == "---\n":
@@ -160,10 +174,10 @@ class MageiaLinksRevision(git_multimail.Revision):
output.insert(idx, "\n")
idx += 1
- # Attempt to modify bugzilla
+ # Attempt to modify Bugzilla
if "Mageia" in bugs:
try:
- bz = self.bugzilla_init()
+ self.bugzilla_init()
# Mask email address
comment = None
@@ -179,46 +193,38 @@ class MageiaLinksRevision(git_multimail.Revision):
params = {}
params['ids'] = bugs['Mageia']
params['comment'] = { 'body': comment }
- self.bugzilla_call(bz.Bug.update, params)
- print "Updated bugzilla bugs: %s" % ", ".join(bugs['Mageia'])
+ self.bz.call_bz(self.bz.bz.Bug.update, params)
+ print("Updated bugzilla bugs: %s" % ", ".join(bugs['Mageia']))
except:
- print "Unable to post to bugzilla bugs: %s :(" % ", ".join(bugs['Mageia'])
- print sys.exc_info()[1]
+ print("Unable to post to bugzilla bugs: %s :(" % ", ".join(bugs['Mageia']))
+ print(sys.exc_info()[1])
break
+
m = COMMIT_RE.search(line)
if m:
commit = m.group(1)
for tracker in BUG_REFS.keys():
foundbugs = BUG_REFS[tracker]['re'].findall(line)
- if len(foundbugs):
- if not tracker in bugs:
+ if foundbugs:
+ if tracker not in bugs:
bugs[tracker] = foundbugs
else:
bugs[tracker] = list(set(bugs[tracker] + foundbugs))
return output
+
# Override the Revision class to inject gitweb/cgit links and any referenced
# bug URLs
class MageiaI18NRevision(git_multimail.Revision):
"""A Change consisting of a single git commit."""
def __init__(self, reference_change, rev, num, tot):
- git_multimail.Change.__init__(self, reference_change.environment)
- self.reference_change = reference_change
- self.rev = rev
- self.change_type = self.reference_change.change_type
- self.refname = self.reference_change.refname
- self.num = num
- self.tot = tot
- self.author = git_multimail.read_git_output(['log', '--no-walk', '--format=%aN <%%aE>', self.rev.sha1])
- self.recipients = False
- self.output = []
-
- # -s is short for --no-patch, but -s works on older git's (e.g. 1.7)
- self.parents = git_multimail.read_git_lines(['show', '-s', '--format=%P', self.rev.sha1])[0].split()
+ super().__init__(reference_change, rev, num, tot)
+ # Don't send to any of the normal recipients
+ self.recipients = False
self.cc_recipients = ''
i18n_folders = []
@@ -228,14 +234,16 @@ class MageiaI18NRevision(git_multimail.Revision):
if name.endswith("/.tx"):
i18n_folders.append(os.path.dirname(name))
- if len(i18n_folders):
+ if i18n_folders:
self.output = git_multimail.read_git_lines(
['log', '-C', '--stat', '-p', '--no-walk', self.rev.sha1, '--'] + i18n_folders,
keepends=True,
)
- if len(self.output):
+ if self.output:
# We have some output so let's send the mail...
- self.recipients = 'i18n-reports@ml.mageia.org'
+ self.recipients = I18N_MAIL
+ print(f'Sending i8n notification to {self.recipients}')
+
def generate_email_body(self, push):
"""Show this revision."""
@@ -243,32 +251,29 @@ class MageiaI18NRevision(git_multimail.Revision):
return self.output
-
-if __name__ == '__main__':
+def main():
# Attempt to write a last-updated file for cgit cosmetics
+ git_dir = git_multimail.get_git_dir()
+ infowebdir = os.path.join(git_dir, 'info', 'web')
+ lastupdated = git_multimail.read_git_output(
+ ['for-each-ref', '--sort=-committerdate', "--format=%(committerdate:iso8601)", '--count=1', 'refs/heads'],
+ )
try:
- git_dir = git_multimail.get_git_dir()
- infowebdir = os.path.join(git_dir, 'info', 'web')
if not os.path.exists(infowebdir):
os.makedirs(infowebdir)
- lastupdated = git_multimail.read_git_output(
- ['for-each-ref', '--sort=-committerdate', "--format=%(committerdate:iso8601)", '--count=1', 'refs/heads'],
- )
- modfile = open(os.path.join(infowebdir, 'last-modified'), 'w')
- modfile.write(lastupdated)
- modfile.close()
+ with open(os.path.join(infowebdir, 'last-modified'), 'w') as modfile:
+ modfile.write(lastupdated)
except Exception:
- pass
+ debug('Warning: could not update git last-modified date: %s', sys.exc_info()[1])
+ # Contact the on-the-pull service on the gitweb server with the updated repo
try:
- req = urllib2.Request('https://gitweb.mageia.org:8000', repo_shortname() + '.git')
+ req = urllib.request.Request(GITWEB_UPDATE_URL, (repo_shortname() + '.git').encode('utf-8'))
req.add_header('Content-Type', 'x-git/repo')
- fp = urllib2.urlopen(req, timeout=5)
- if (fp):
- fp.close()
+ fp = urllib.request.urlopen(req, timeout=5)
+ fp.close()
except Exception:
- pass
-
+ debug('Warning: could not contact gitweb server: %s', sys.exc_info()[1])
config = git_multimail.Config('multimailhook')
@@ -278,7 +283,7 @@ if __name__ == '__main__':
)
mailer = git_multimail.choose_mailer(config, environment)
- # For testing...
+ # For testing...send mail to stdout only
#mailer = git_multimail.OutputMailer(sys.stdout)
changes = []
@@ -289,11 +294,10 @@ if __name__ == '__main__':
)
push = git_multimail.Push(environment, changes)
-
# First pass - regular commit mails
git_multimail.Revision = MageiaLinksRevision
push.send_emails(mailer, body_filter=environment.filter_body)
-
+
# Second pass - i18n commit mails
git_multimail.REVISION_HEADER_TEMPLATE = I18N_REVISION_HEADER_TEMPLATE
git_multimail.Revision = MageiaI18NRevision
@@ -302,5 +306,9 @@ if __name__ == '__main__':
change.recipients = False
push.send_emails(mailer, body_filter=environment.filter_body)
- except git_multimail.ConfigurationException, e:
+ except git_multimail.ConfigurationException as e:
sys.exit(str(e))
+
+
+if __name__ == '__main__':
+ main()