diff options
Diffstat (limited to 'deployment/mgagit/templates')
| -rwxr-xr-x | deployment/mgagit/templates/git-post-receive-hook | 314 | ||||
| -rw-r--r-- | deployment/mgagit/templates/git-post-update-hook | 12 | ||||
| -rw-r--r-- | deployment/mgagit/templates/gitolite.rc | 161 | ||||
| -rw-r--r-- | deployment/mgagit/templates/group_owned_repo.gl | 36 | ||||
| -rw-r--r-- | deployment/mgagit/templates/mgagit.conf | 57 | ||||
| -rw-r--r-- | deployment/mgagit/templates/repodef_repo.gl | 8 |
6 files changed, 588 insertions, 0 deletions
diff --git a/deployment/mgagit/templates/git-post-receive-hook b/deployment/mgagit/templates/git-post-receive-hook new file mode 100755 index 00000000..68da3200 --- /dev/null +++ b/deployment/mgagit/templates/git-post-receive-hook @@ -0,0 +1,314 @@ +#!/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 bugz.settings + +import git_multimail + +# When editing this list, remember to edit the same list in +# modules/cgit/templates/filter.commit-links.sh +BUG_REFS = { + 'Mageia': { 're': re.compile('mga#([0-9]+)'), 'replace': 'https://bugs.mageia.org/%s' }, + 'Red Hat': { 're': re.compile('rhbz#([0-9]+)'), 'replace': 'https://bugzilla.redhat.com/show_bug.cgi?id=%s' }, + 'Free Desktop': { 're': re.compile('fdo#([0-9]+)'), 'replace': 'https://bugs.freedesktop.org/show_bug.cgi?id=%s' }, + 'KDE': { 're': re.compile('(?:bko|kde)#([0-9]+)'), 'replace': 'https://bugs.kde.org/show_bug.cgi?id=%s' }, + 'GNOME': { 're': re.compile('(?:bgo|gnome)#([0-9]+)'), 'replace': 'https://bugzilla.gnome.org/show_bug.cgi?id=%s' }, + 'Launchpad': { 're': re.compile('lp#([0-9]+)'), 'replace': 'https://launchpad.net/bugs/%s' }, +} + +COMMIT_RE = re.compile('^commit ([a-f0-9]{40})') +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_APIKEY_FILE = '.gitzilla-apikey' # this holds a Bugzilla API key +GITWEB_UPDATE_URL = 'http://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 = """\ + +-- \n\ +Mageia Git Monkeys. +""" +git_multimail.REVISION_FOOTER_TEMPLATE = git_multimail.FOOTER_TEMPLATE + +I18N_REVISION_HEADER_TEMPLATE = """\ +Date: %(send_date)s +To: %(recipients)s +Subject: %(emailprefix)s%(oneline)s +MIME-Version: 1.0 +Content-Type: text/plain; charset=%(charset)s +Content-Transfer-Encoding: 8bit +From: %(fromaddr)s +Reply-To: %(reply_to)s +In-Reply-To: %(reply_to_msgid)s +References: %(reply_to_msgid)s +X-Git-Host: %(fqdn)s +X-Git-Repo: %(repo_shortname)s +X-Git-Refname: %(refname)s +X-Git-Reftype: %(refname_type)s +X-Git-Rev: %(rev)s +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) + if m: + return m.group('name') + else: + return basename + + +# Override the Environment class to generate an appropriate short name which is +# used in git links and as an email prefix +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): + def __init__(self, reference_change, rev, num, tot): + super().__init__(reference_change, rev, num, tot) + self.bz = None + + def bugzilla_init(self): + 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: + 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 + + 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, + ) + 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": + if commit and COMMIT_REPLACE: + output.insert(idx, "\n") + output.insert(idx, " %s\n" % (COMMIT_REPLACE % (self.environment.get_repo_shortname(), commit))) + output.insert(idx, " Commit Link:\n") + idx += 3 + if bugs: + output.insert(idx, " Bug links:\n") + idx += 1 + for tracker, bugnos in bugs.items(): + output.insert(idx, " %s\n" % tracker) + idx += 1 + for bugno in bugnos: + output.insert(idx, " %s\n" % (BUG_REFS[tracker]['replace'] % bugno)) + idx += 1 + output.insert(idx, "\n") + idx += 1 + + # Attempt to modify Bugzilla + if "Mageia" in bugs: + try: + self.bugzilla_init() + + # Mask email address + comment = None + # Suppress the "Bug links:" section if only one bug + # is referenced + if len(bugs) == 1 and len(bugs['Mageia']) == 1: + comment = output[0:idx-4] + else: + comment = output[0:idx] + comment[1] = re.sub(r'^(Author: [^@]*)@.*(>)?', r'\1@...>', comment[1]) + comment = "".join(comment) + + params = {} + params['ids'] = bugs['Mageia'] + params['comment'] = { 'body': comment } + 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]) + + 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 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): + super().__init__(reference_change, rev, num, tot) + + # Don't send to any of the normal recipients + self.recipients = False + self.cc_recipients = '' + + i18n_folders = [] + # Check files and find i18n folders + for line in git_multimail.read_git_lines(['ls-tree', '-rd', self.rev.sha1]): + (modetypesha1, name) = line.split("\t", 1) + if name.endswith("/.tx"): + i18n_folders.append(os.path.dirname(name)) + + if i18n_folders: + self.output = git_multimail.read_git_lines( + ['log', '-C', '--stat', '-p', '--no-walk', self.rev.sha1, '--'] + i18n_folders, + keepends=True, + ) + if self.output: + # We have some output so let's send the mail... + self.recipients = I18N_MAIL + print(f'Sending i8n notification to {self.recipients}') + + + def generate_email_body(self, push): + """Show this revision.""" + + return self.output + + +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: + if not os.path.exists(infowebdir): + os.makedirs(infowebdir) + with open(os.path.join(infowebdir, 'last-modified'), 'w') as modfile: + modfile.write(lastupdated) + except Exception: + 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 = urllib.request.Request(GITWEB_UPDATE_URL, (repo_shortname() + '.git').encode('utf-8')) + req.add_header('Content-Type', 'x-git/repo') + fp = urllib.request.urlopen(req, timeout=5) + fp.close() + except Exception: + debug('Warning: could not contact gitweb server: %s', sys.exc_info()[1]) + + config = git_multimail.Config('multimailhook') + + try: + environment = git_multimail.choose_environment( + config, osenv=os.environ, + ) + + mailer = git_multimail.choose_mailer(config, environment) + # For testing...send mail to stdout only + #mailer = git_multimail.OutputMailer(sys.stdout) + + changes = [] + for line in sys.stdin: + (oldrev, newrev, refname) = line.strip().split(' ', 2) + changes.append( + git_multimail.ReferenceChange.create(environment, oldrev, newrev, refname) + ) + 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 + # Don't send the summary email, so nuke the change recipients + for change in push.changes: + change.recipients = False + push.send_emails(mailer, body_filter=environment.filter_body) + + except git_multimail.ConfigurationException as e: + sys.exit(str(e)) + + +if __name__ == '__main__': + main() diff --git a/deployment/mgagit/templates/git-post-update-hook b/deployment/mgagit/templates/git-post-update-hook new file mode 100644 index 00000000..a2550ad3 --- /dev/null +++ b/deployment/mgagit/templates/git-post-update-hook @@ -0,0 +1,12 @@ +#!/bin/bash + +if [ "${GL_REPO:0:28}" == "infrastructure/repositories/" ]; then + OK=no + (unset GIT_DIR && mgagit glconf && mgagit glrun) >/dev/null 2>&1 && OK=yes + if [ "$OK" == "yes" ]; then + echo + echo " *** Repository definitions updated" + echo + fi +fi +exit 0
\ No newline at end of file diff --git a/deployment/mgagit/templates/gitolite.rc b/deployment/mgagit/templates/gitolite.rc new file mode 100644 index 00000000..c4c925e6 --- /dev/null +++ b/deployment/mgagit/templates/gitolite.rc @@ -0,0 +1,161 @@ +# configuration variables for gitolite + +# This file is in perl syntax. But you do NOT need to know perl to edit it -- +# just mind the commas, use single quotes unless you know what you're doing, +# and make sure the brackets and braces stay matched up! + +# (Tip: perl allows a comma after the last item in a list also!) + +# HELP for commands can be had by running the command with "-h". + +# HELP for all the other FEATURES can be found in the documentation (look for +# "list of non-core programs shipped with gitolite" in the master index) or +# directly in the corresponding source file. + +%RC = ( + + # ------------------------------------------------------------------ + + # default umask gives you perms of '0700'; see the rc file docs for + # how/why you might change this + UMASK => 0022, + + # look for "git-config" in the documentation + GIT_CONFIG_KEYS => 'gitweb\.description gitweb\.owner multimailhook\.mailingList multimailhook\.emailDomain multimailhook\.envelopeSender', + + # comment out if you don't need all the extra detail in the logfile + LOG_EXTRA => 1, + + # roles. add more roles (like MANAGER, TESTER, ...) here. + # WARNING: if you make changes to this hash, you MUST run 'gitolite + # compile' afterward, and possibly also 'gitolite trigger POST_COMPILE' + ROLES => { + READERS => 1, + WRITERS => 1, + }, + + # ------------------------------------------------------------------ + + # rc variables used by various features + + # the 'info' command prints this as additional info, if it is set + # SITE_INFO => 'Please see http://blahblah/gitolite for more help', + + # the 'desc' command uses this + # WRITER_CAN_UPDATE_DESC => 1, + + # the CpuTime feature uses these + # display user, system, and elapsed times to user after each git operation + # DISPLAY_CPU_TIME => 1, + # display a warning if total CPU times (u, s, cu, cs) crosses this limit + # CPU_TIME_WARN_LIMIT => 0.1, + + # the Mirroring feature needs this + # HOSTNAME => "foo", + + # if you enabled 'Shell', you need this + # SHELL_USERS_LIST => "$ENV{HOME}/.gitolite.shell-users", + + # ------------------------------------------------------------------ + + # List of commands and features to enable + + ENABLE => [ + + # COMMANDS + + # These are the commands enabled by default + 'help', + 'desc', + 'info', + 'perms', + 'writable', + + # Uncomment or add new commands here. + # 'create', + # 'fork', + # 'mirror', + # 'sskm', + # 'D', + + # These FEATURES are enabled by default. + + # essential (unless you're using smart-http mode) + 'ssh-authkeys', + + # creates git-config entities from gitolite.conf file entries like 'config foo.bar = baz' + 'git-config', + + # creates git-daemon-export-ok files; if you don't use git-daemon, comment this out + 'daemon', + + # creates projects.list file; if you don't use gitweb, comment this out + 'gitweb', + + # These FEATURES are disabled by default; uncomment to enable. If you + # need to add new ones, ask on the mailing list :-) + + # user-visible behaviour + + # prevent wild repos auto-create on fetch/clone + # 'no-create-on-read', + # no auto-create at all (don't forget to enable the 'create' command!) + # 'no-auto-create', + + # access a repo by another (possibly legacy) name + # 'Alias', + + # give some users direct shell access + # 'Shell', + + # set default roles from lines like 'option default.roles-1 = ...', etc. + # 'set-default-roles', + + # system admin stuff + + # enable mirroring (don't forget to set the HOSTNAME too!) + # 'Mirroring', + + # allow people to submit pub files with more than one key in them + # 'ssh-authkeys-split', + + # selective read control hack + # 'partial-copy', + + # manage local, gitolite-controlled, copies of read-only upstream repos + # 'upstream', + + # updates 'description' file instead of 'gitweb.description' config item + 'cgit', + + # performance, logging, monitoring... + + # be nice + # 'renice 10', + + # log CPU times (user, system, cumulative user, cumulative system) + # 'CpuTime', + + # syntactic_sugar for gitolite.conf and included files + + # allow backslash-escaped continuation lines in gitolite.conf + # 'continuation-lines', + + # create implicit user groups from directory names in keydir/ + # 'keysubdirs-as-groups', + + # allow simple line-oriented macros + # 'macros', + + ], + +); + +# ------------------------------------------------------------------------------ +# per perl rules, this should be the last line in such a file: +1; + +# Local variables: +# mode: perl +# End: +# vim: set syn=perl: diff --git a/deployment/mgagit/templates/group_owned_repo.gl b/deployment/mgagit/templates/group_owned_repo.gl new file mode 100644 index 00000000..14431d6c --- /dev/null +++ b/deployment/mgagit/templates/group_owned_repo.gl @@ -0,0 +1,36 @@ +[% SET maintainer = r.repos.$repo.maintainer %] +repo [% repo %] + RW+ master$ = [% maintainer %] + RW+ distro/ = [% maintainer %] + RW+ topic/ = [% maintainer %] + RW+ refs/tags/ = [% maintainer %] +[% IF r.repos.$repo.lockdown != 'yes' -%] + RW master$ = @mga-<%= @group %> + RW distro/ = @mga-<%= @group %> + RW+ topic/ = @mga-<%= @group %> + RW refs/tags/ = @mga-<%= @group %> + RW master$ = @mga-i18n-committers + RW distro/ = @mga-i18n-committers + RW topic/ = @mga-i18n-committers +[% END -%] + RW+ master$ = @mga-sysadmin + RW+ distro/ = @mga-sysadmin + RW+ topic/ = @mga-sysadmin + RW+ refs/tags/ = @mga-sysadmin + RW+ user/USER/ = @all + R = @all +[% IF r.repos.$repo.noemail -%] + config multimailhook.mailingList = "" +[% ELSE -%] +[% IF r.repos.$repo.mailingList -%] + config multimailhook.mailingList = "[% r.repos.$repo.mailingList %]" +[% ELSE -%] + config multimailhook.mailingList = "<%= @ml %>-commits@ml.mageia.org" +[% END -%] +[% END -%] + config multimailhook.emailDomain = "mageia.org" + config multimailhook.envelopeSender = "root@mageia.org" + config gitweb.description = "[% r.repos.$repo.description %]" +[% IF r.users.$maintainer -%] + config gitweb.owner = "[% r.users.$maintainer.cn.0 %] [[% maintainer %]]" +[% END -%] diff --git a/deployment/mgagit/templates/mgagit.conf b/deployment/mgagit/templates/mgagit.conf new file mode 100644 index 00000000..82b1d66a --- /dev/null +++ b/deployment/mgagit/templates/mgagit.conf @@ -0,0 +1,57 @@ +--- +use_ldap: yes +ldapserver: <%= @ldap_server %> +binddn: <%= @binddn %> +bindpwfile: <%= @bindpwfile %> +pubkey_dir: <%= @gitolite_keydir %> +tmpl_dir: <%= @gitolite_tmpldir %> +gitolite_config: <%= @gitolite_conf %> +run_gitolite: yes +repodef_dir: <%= @reposconf_dir %> +repos_config: + - prefix: infrastructure/repositories + gl_template: repodef_repo + repos: + - name: artwork + maintainer: '@mga-sysadmin' + description: Artwork repository definitions + - name: doc + maintainer: '@mga-sysadmin' + description: Documentation repository definitions + - name: infrastructure + maintainer: '@mga-sysadmin' + description: Infrastructure repository definitions + - name: org + maintainer: '@mga-sysadmin' + description: Organization repository definitions + - name: qa + maintainer: '@mga-sysadmin' + description: QA repository definitions + - name: software + maintainer: '@mga-sysadmin' + description: Software repository definitions + - name: web + maintainer: '@mga-sysadmin' + description: Website repository definitions + - prefix: artwork + gl_template: artwork_repo + git_url: file:///git/infrastructure/repositories/artwork.git + - prefix: doc + gl_template: doc_repo + git_url: file:///git/infrastructure/repositories/doc.git + - prefix: infrastructure + gl_template: infrastructure_repo + git_url: file:///git/infrastructure/repositories/infrastructure.git + - prefix: org + gl_template: org_repo + git_url: file:///git/infrastructure/repositories/org.git + - prefix: qa + gl_template: qa_repo + git_url: file:///git/infrastructure/repositories/qa.git + - prefix: software + gl_template: soft_repo + git_url: file:///git/infrastructure/repositories/software.git + - prefix: web + gl_template: web_repo + git_url: file:///git/infrastructure/repositories/web.git +www_dir: <%= @vhostdir %> diff --git a/deployment/mgagit/templates/repodef_repo.gl b/deployment/mgagit/templates/repodef_repo.gl new file mode 100644 index 00000000..12c946f5 --- /dev/null +++ b/deployment/mgagit/templates/repodef_repo.gl @@ -0,0 +1,8 @@ +repo [% repo %] + RW master$ = [% r.repos.$repo.maintainer %] + RW+ user/USER/ = @all + R = @all + config multimailhook.mailingList = "sysadmin-commits@ml.mageia.org" + config multimailhook.emailDomain = "mageia.org" + config multimailhook.envelopeSender = "root@mageia.org" + config gitweb.description = "[% r.repos.$repo.description %]" |
