Completed
Push — master ( 40212d...576f4e )
by Gonzalo
59s
created

get_token()   A

Complexity

Conditions 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 3
c 1
b 0
f 1
dl 0
loc 10
rs 9.4285
1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Copyright (c) The Spyder Development Team
4
#
5
# Licensed under the terms of the MIT License
6
# (See LICENSE.txt for details)
7
# -----------------------------------------------------------------------------
8
"""Create github labels from a text file."""
9
10
from __future__ import print_function
11
12
# Standard library imports
13
import argparse
14
import getpass
15
import re
16
import sys
17
import time
18
19
# Third party imports
20
from jinja2 import Template
21
22
# Local imports
23
# yapf: disable
24
from loghub.repo import GitHubRepo
25
from loghub.templates import (CHANGELOG_GROUPS_TEMPLATE_PATH,
26
                              CHANGELOG_TEMPLATE_PATH,
27
                              RELEASE_GROUPS_TEMPLATE_PATH,
28
                              RELEASE_TEMPLATE_PATH)
29
30
# yapf: enable
31
32
PY2 = sys.version[0] == '2'
33
34
35
def main():
36
    """Main script."""
37
    parse_arguments(skip=False)
38
39
40 View Code Duplication
def parse_arguments(skip=False):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
41
    """Parse CLI arguments."""
42
    # Cli options
43
    parser = argparse.ArgumentParser(
44
        description='Script to print the list of issues and pull requests '
45
        'closed in a given milestone, tag including additional filtering '
46
        'options.')
47
    parser.add_argument(
48
        'repository',
49
        help="Repository name to generate the Changelog for, in the form "
50
        "user/repo or org/repo (e.g. spyder-ide/spyder)")
51
    parser.add_argument(
52
        '-m',
53
        '--milestone',
54
        action="store",
55
        dest="milestone",
56
        default='',
57
        help="Github milestone to get issues and pull requests for")
58
    parser.add_argument(
59
        '-ilg',
60
        '--issue-label-group',
61
        action="append",
62
        nargs='+',
63
        dest="issue_label_groups",
64
        help="Groups the generated issues by the specified label. This option"
65
        "Takes 1 or 2 arguments, where the first one is the label to "
66
        "match and the second one is the label to print on the final"
67
        "output")
68
    parser.add_argument(
69
        '-ilr',
70
        '--issue-label-regex',
71
        action="store",
72
        dest="issue_label_regex",
73
        default='',
74
        help="Label issue filter using a regular expression filter")
75
    parser.add_argument(
76
        '-plr',
77
        '--pr-label-regex',
78
        action="store",
79
        dest="pr_label_regex",
80
        default='',
81
        help="Label pull requets filter using a regular expression filter")
82
    parser.add_argument(
83
        '-st',
84
        '--since-tag',
85
        action="store",
86
        dest="since_tag",
87
        default='',
88
        help="Github issues and pull requests since tag")
89
    parser.add_argument(
90
        '-ut',
91
        '--until-tag',
92
        action="store",
93
        dest="until_tag",
94
        default='',
95
        help="Github issues and pull requests until tag")
96
    parser.add_argument(
97
        '-b',
98
        '--branch',
99
        action="store",
100
        dest="branch",
101
        default='',
102
        help="Github base branch for merged PRs")
103
    parser.add_argument(
104
        '-f',
105
        '--format',
106
        action="store",
107
        dest="output_format",
108
        default='changelog',
109
        help="Format for print, either 'changelog' (for "
110
        "Changelog.md file) or 'release' (for the Github "
111
        "Releases page). Default is 'changelog'. The "
112
        "'release' option doesn't generate Markdown "
113
        "hyperlinks.")
114
    parser.add_argument(
115
        '--template',
116
        action="store",
117
        dest="template",
118
        default='',
119
        help="Use a custom Jinja2 template file ")
120
    parser.add_argument(
121
        '-u',
122
        '--user',
123
        action="store",
124
        dest="user",
125
        default='',
126
        help="Github user name")
127
    parser.add_argument(
128
        '-p',
129
        '--password',
130
        action="store",
131
        dest="password",
132
        default='',
133
        help="Github user password")
134
    parser.add_argument(
135
        '-t',
136
        '--token',
137
        action="store",
138
        dest="token",
139
        default='',
140
        help="Github access token")
141
    options = parser.parse_args()
142
143
    username = options.user
144
    password = options.password
145
    milestone = options.milestone
146
    issue_label_groups = options.issue_label_groups
147
148
    if username and not password:
149
        password = getpass.getpass()
150
151
    # Check if repo given
152
    if not options.repository:
153
        print('LOGHUB: Please define a repository name to this script. '
154
              'See its help')
155
        sys.exit(1)
156
157
    # Check if milestone or tag given
158
    if not milestone and not options.since_tag:
159
        print('\nLOGHUB: Querying all issues\n')
160
    elif milestone:
161
        print('\nLOGHUB: Querying issues for milestone {0}'
162
              '\n'.format(milestone))
163
164
    new_issue_label_groups = []
165
    if issue_label_groups:
166
        for item in issue_label_groups:
167
            dic = {}
168
            if len(item) == 1:
169
                dic['label'] = item[0]
170
                dic['name'] = item[0]
171
            elif len(item) == 2:
172
                dic['label'] = item[0]
173
                dic['name'] = item[1]
174
            else:
175
                print('LOGHUB: Issue label group takes 1 or 2 arguments\n')
176
                sys.exit(1)
177
            new_issue_label_groups.append(dic)
178
179
    if not skip:
180
        create_changelog(
181
            repo=options.repository,
182
            username=username,
183
            password=password,
184
            token=options.token,
185
            milestone=milestone,
186
            since_tag=options.since_tag,
187
            until_tag=options.until_tag,
188
            branch=options.branch,
189
            issue_label_regex=options.issue_label_regex,
190
            pr_label_regex=options.pr_label_regex,
191
            output_format=options.output_format,
192
            template_file=options.template,
193
            issue_label_groups=new_issue_label_groups)
194
195
    return options
196
197
198
def get_token():
199
    r"""
200
    Get the API token to use for talking to GitHub
201
    """
202
    try:
203
        with open('token', 'rt') as token_file:
204
            return token_file.readline()[:-1]
205
    except IOError:
206
        import os
207
        return os.environ['GITHUB_TOKEN']
208
209
210
if __name__ == '__main__':
211
    import argparse
212
213
    # Get command-line arguments
214
    parser = argparse.ArgumentParser()
215
    parser.add_argument('repository', help='Repository', type=str)
216
    parser.add_argument('-o', '--org', help='Organization', type=str, default='Unidata')
217
    parser.add_argument('action', help='Action to take', type=str, choices=['get', 'update'],
218
                        default='get', nargs='?')
219
    parser.add_argument('-f', '--filename', help='File for storing labels', type=str,
220
                        default='labels.txt')
221
    args = parser.parse_args()
222
223
    # Get the github API entry
224
    token = get_token()
225
    g = github.Github(token)
226
227
    # Get the organization
228
    org = g.get_organization(args.org)
229
230
    # Get the object for this repository
231
    repo = org.get_repo(args.repository)
232
233
    #
234
    if args.action == 'get':
235
        print('Getting labels from {0}'.format(args.repository))
236
        with open(args.filename, 'wt') as outfile:
237
            labels = sorted((l.name, l.color) for l in repo.get_labels())
238
            outfile.write(''.join('{0}|{1}\n'.format(*l) for l in labels))
239
    elif args.action == 'update':
240
        if token is None:
241
            raise RuntimeError('Updating labels requires a personal access token!')
242
        print('Updating labels on {0}'.format(args.repository))
243
        with open(args.filename, 'rt') as infile:
244
            for line in infile:
245
                parts = line.strip().split('|')
246
                if len(parts) == 3:
247
                    old_name, new_name, color = parts
248
                else:
249
                    new_name, color = parts
250
                    old_name = new_name
251
252
                try:
253
                    label = repo.get_label(old_name)
254
                    label.edit(new_name, color)
255
                    print('Updated label: {0.name}->{1} (#{2})'.format(label, new_name, color))
256
                except github.GithubException:
257
                    label = repo.create_label(new_name, color)
258
                    print('Created label: {0.name} (#{0.color})'.format(label))
259
260
                    
261
if __name__ == '__main__':  # yapf: disable
262
    main()
263