20after4 has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/390429 )

Change subject: Task Series scap plugin
......................................................................

Task Series scap plugin

Change-Id: If3d375d39c976788499737ab68fb281eb13dc2c5
---
A scap/plugins/task-series.py
1 file changed, 248 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/tools/release 
refs/changes/29/390429/1

diff --git a/scap/plugins/task-series.py b/scap/plugins/task-series.py
new file mode 100644
index 0000000..14bd75e
--- /dev/null
+++ b/scap/plugins/task-series.py
@@ -0,0 +1,248 @@
+# This Python file uses the following encoding: utf-8
+
+from __future__ import print_function, unicode_literals
+
+import argparse
+import calendar
+import datetime
+import re
+import os
+
+from string import Template
+
+from calendar import Calendar
+from phabricator import Phabricator
+from scap import cli, log
+from scap.utils import var_dump
+from datetime import timedelta
+
+
+ONEWEEK = timedelta(weeks=1)
+
+
+def trunc(len, string, ellipsis=" …"):
+    return string[0:len] + ellipsis
+
+
+def action_arg(*args, **kwargs):
+    kwargs['const'] = kwargs['action']
+    kwargs['dest'] = 'action'
+    kwargs['action'] = 'store_const'
+    kwargs['metavar'] = 'ACTION'
+    return cli.argument(*args, **kwargs)
+
+
+# function by jfs, see https://stackoverflow.com/a/8778548/1672995
+def totimestamp(dt, epoch=datetime.datetime(1970, 1, 1)):
+    td = dt - epoch
+    # return td.total_seconds()
+    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
+
+
+def find_mondays(year, month):
+    cal = Calendar()
+    mondays = list()
+    for week in cal.monthdays2calendar(year, month):
+        for day in week:
+            (monthday, weekday) = day
+            if (weekday == 1 and monthday > 0):
+                mondays.append(datetime.date(year=year,
+                                             month=month,
+                                             day=monthday))
+    return mondays
+
+
+phab = Phabricator(host='https://phabricator.wikimedia.org/api/')
+
+
+def phab_taskid(taskid):
+    if not taskid.startswith("T"):
+        raise Exception("Invalid task id: %s", taskid)
+    return taskid
+
+
+def mediawiki_version(ver):
+    """Validation our version number formats"""
+    try:
+        return re.match("(\d+\.\d+(\.\d+-)?wmf\.?\d+)", ver).group(0)
+    except:
+        raise argparse.ArgumentTypeError(
+            "Invalid wmf version '%s' expected: #.##.#-wmf.#" % ver)
+
+
+def date_str(datestr):
+    formats = ['%x', '%m-%d-%Y', '%Y%m%d', '%Y-%m-%d']
+    err = None
+    date = None
+    for format in formats:
+        try:
+            date = datetime.datetime.strptime(datestr, format)
+        except Exception as ex:
+            err = ex
+
+    if date is None and err is not None:
+        raise err
+
+    return date
+
+
+def map_transactions(obj):
+    trns = []
+
+    for key, val in obj.items():
+        trns.append({
+            "type": key,
+            "value": val
+        })
+    return trns
+
+
+@cli.command('task-series', subcommands=True)
+class ReleaseTagger(cli.Application):
+    """
+    Create a series of phabricator tasks with content generated from a template
+    """
+    action = None
+
+    def _setup_loggers(self):
+        """Setup logging."""
+        log.setup_loggers(self.config, self.arguments.loglevel + 10)
+
+    def _process_arguments(self, args, extra_args):
+        # print(args,extra_args)
+        return args, extra_args
+
+    @cli.argument('--count', help='Number of tasks to create, default=1',
+                  metavar='NUM', default=1, type=int)
+    @cli.argument('--date', help='Date of the first release,\
+                  default=today\'s date', metavar='START',
+                  type=date_str, default=datetime.datetime.utcnow())
+    @cli.argument('release', help='Create tasks beginning with VERSION',
+                  metavar='VERSION', type=mediawiki_version)
+    @cli.subcommand('blockers')
+    def blockers(self, *args):
+        '''
+        Create Release Blockers.
+
+        Command Usage:
+
+          $ scap task-series blockers --count 10 --date 2017-01-01 1.30.0-wmf.1
+
+        Creates 10 release-blocker tasks, beginning with version 1.30.0-wmf.1
+        on 2017-01-01.
+        '''
+        v = self.arguments.release.split('-')
+        wmfnum = int(v[-1].split('.')[-1])
+        week = self.arguments.date
+        weekday = week.weekday()
+        if weekday:
+            # ofset some days so that we always use monday of the given week:
+            week -= timedelta(days=weekday)
+
+        for n in range(wmfnum, wmfnum + self.arguments.count):
+            v[-1] = 'wmf.%d' % n
+            vs = "-".join(v)
+
+            ts = int(totimestamp(week))
+            trns = map_transactions({
+                'title': "%s deployment blockers" % vs,
+                'subtype': 'release',
+                'projects.add': ["PHID-PROJ-fmcvjrkfvvzz3gxavs3a",
+                                 "PHID-PROJ-pf35un2jsnsiriivnmeo"],
+                'custom.release.version': str(vs),
+                'custom.release.date': str(ts),
+            })
+            print("%s : %s, %s" % (vs, week, ts))
+            var_dump(phab.maniphest.edit(transactions=trns))
+            week += ONEWEEK
+
+    @cli.argument('--project', default='PHID-PROJ-fmcvjrkfvvzz3gxavs3a',
+                  dest='project', metavar='PHID',
+                  help='Hashtag or PHID for project (Optional)')
+    def list(selfm, *args):
+        project_name = self.arguments.project
+        query = {
+            'subtypes': ['release'],
+            'statuses': ['open'],
+            'projects': [project_name]
+        }
+        tasks = phab.maniphest.search(constraints=query,
+                                      # queryKey='hFre3CTnmGm2',
+                                      order='title')
+        titles = [task['fields']['name'] for task in tasks['data']]
+        taskmap = {task['phid']: task['fields']['name']
+                   for task in tasks['data']}
+        var_dump(titles)
+        var_dump(taskmap)
+
+    @cli.argument('--project', default='PHID-PROJ-fmcvjrkfvvzz3gxavs3a',
+                  dest='project', metavar='PROJECT',
+                  help='Create a tasks within PROJECT')
+    @cli.argument('--template', default='scap/templates/blockers.tmpl',
+                  help='template file')
+    @cli.argument('--mwversion', help='MediaWiki Version, e.g. 1.30.0')
+    @cli.argument('--previous', type=phab_taskid)
+    @cli.argument('-h', '--help', action='help')
+    @cli.subcommand("create")
+    def taskseries(self, *args):
+        ''' create a task series in phabricator '''
+        project_name = self.arguments.project
+        if project_name.startswith("PHID"):
+            parent_phid = project_name
+        else:
+            query = {
+                'name': project_name,
+            }
+            project = phab.maniphest.search(constraints=query)
+            parent_phid = project['data'][0]['phid']
+
+        template_path = self.arguments.template
+        if "/" not in template_path:
+            template_path = os.path.join("scap", "templates", template_path)
+
+        with file(template_path) as template_file:
+            template = Template("".join(template_file.readlines()))
+
+        tmpl_vars = {}
+        for key in vars(self.arguments).keys():
+            val = getattr(self.arguments, key)
+            while(isinstance(val, list)):
+                val = val[0]
+
+            if type(val) in (unicode, str):
+                tmpl_vars[key] = val
+
+        var_dump(tmpl_vars)
+        milestone_name = self.arguments.milestone[0]
+        description = template.safe_substitute(tmpl_vars)
+
+        print(description)
+
+        if self.arguments.hashtag is None:
+            hashtag = project_name + '-' + milestone_name
+        else:
+            hashtag = self.arguments.hashtag
+
+        trns = [
+            {
+                'type': 'milestone',
+                'value': parent_phid
+            },
+            {
+                'type': 'title',
+                'value': milestone_name
+            },
+            {
+                'type': 'slugs',
+                'value': [hashtag]
+            },
+            {
+                'type': 'description',
+                'value': description
+            }
+        ]
+
+        var_dump(trns)
+        result = phab.project.edit(transactions=trns)
+
+        var_dump(result)

-- 
To view, visit https://gerrit.wikimedia.org/r/390429
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If3d375d39c976788499737ab68fb281eb13dc2c5
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/tools/release
Gerrit-Branch: master
Gerrit-Owner: 20after4 <mmod...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to