Skip to content

Instantly share code, notes, and snippets.

@skitazaki
Last active December 23, 2015 10:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skitazaki/6619967 to your computer and use it in GitHub Desktop.
Save skitazaki/6619967 to your computer and use it in GitHub Desktop.
Get updated issues of Redmine by each day.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Get updated issues of Redmine by each day.
Setup & Usage
-------------
Python 2.7, ``virtualenv``, and ``pip`` are required.
Prepare Python virtual environment for this script. ::
$ PYVENV_DIR=~/pyvenv/redmine-daily
$ virtualenv --distribute $PYVENV_DIR
$ source $PYVENV_DIR/bin/activate
Install dependant libraries::
$ cat <<EOF >requirements.txt
pyredmine
clitool
pyyaml
jinja2
python-dateutil==1.5 # "pyredmine" requires internally
EOF
$ pip install -r requirements.txt
Example configuration file is:
development:
url: "http://localhost:8080"
staging:
url: "http://test.example.com/redmine"
username: "skitazaki"
password: "secret"
production:
url: "http://ci.example.com/redmine"
username: "skitazaki"
password: "super-secret"
After saving above as ``config.yaml``, run as following.
::
$ ./redmine-daily.py -c config.yaml --environment test --project demo
If ``--project`` options is omitted, crawl all projects.
"""
import datetime
from functools import partial
from redmine import Redmine
from jinja2 import Template
from clitool.cli import parse_arguments, cliconfig
NOW = datetime.datetime.now()
TEMPLATE = Template(u'''
[{{ identifier }}] {{ name }}
------------------------------------------------------------------------------
{%- for r in rs %}
Updated on: {{ r.updated.strftime('%Y-%m-%d (%A)') }}
{% for issue in r.issues %}
#{{ issue.id }} {{ issue.subject }}
{{ issue.url }}
[{{ issue.status }}] by {{ issue.assigned_to }} until {{ issue.due_date }}
{% endfor %}
{%- endfor %}
'''.rstrip())
def ticket_url(baseurl, ticket_number):
return '{}/issues/{}'.format(baseurl, ticket_number)
def writer(output, encoding, text):
output.write(text.encode(encoding))
def main():
args = parse_arguments(
environment=dict(flags='--environment', required=True),
project=dict(flags='--project', help="commna separated value"),
term=dict(flags='--term', type=int, default=7))
cfg = cliconfig(args.config, args.environment)
if cfg is None:
raise SystemExit('Key is not found for "{}" in "{}"'.format(
args.environment, args.config.name))
redmine = Redmine(cfg['url'],
username=cfg.get('username'), password=cfg.get('password'))
# Collect specified projects or all projects if nothing specified
projects = {}
if args.project:
for p in args.project.split(','):
projects[p] = redmine.projects[p]
else:
for proj in redmine.projects:
projects[proj.name] = proj
url = partial(ticket_url, cfg['url'])
write = partial(writer, args.output, args.output_encoding)
for proj in projects.values():
rs = []
for i in range(args.term):
d = NOW - datetime.timedelta(days=i)
issues = []
for issue in proj.issues(updated_on=d.strftime('%Y-%m-%d')):
try:
assigned_to = 'User#{}'.format(issue.assigned_to.id)
except AttributeError:
assigned_to = 'NOT DETERMINED YET'
try:
due_date = issue.due_date
except AttributeError:
due_date = 'NOT DETERMINED YET'
issues.append({
'id': issue.id, 'subject': issue.subject,
'url': url(issue.id), 'status': issue.status,
'assigned_to': assigned_to, 'due_date': due_date})
if len(issues) > 0:
rs.append({'updated': d, 'issues': issues})
write(TEMPLATE.render(
identifier=proj.identifier, name=proj.name, rs=rs))
if __name__ == '__main__':
main()
# vim: set et ts=4 sw=4 cindent fileencoding=utf-8 :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment