| #!/usr/bin/env python |
| |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| # Utility for updating fix version for Jiras. |
| # |
| # usage: ./gobblin-jira-version (see config env vars below) |
| # |
| |
| from __future__ import print_function |
| import json |
| import os |
| import re |
| import subprocess |
| import sys |
| import textwrap |
| |
| # Python 3 compatibility |
| try: |
| import urllib2 as urllib |
| except ImportError: |
| import urllib.request as urllib |
| if sys.version_info[0] == 3: |
| raw_input = input |
| |
| try: |
| import click |
| except ImportError: |
| print("Could not find the click library. Run 'sudo pip install click' to install.") |
| sys.exit(-1) |
| |
| try: |
| import keyring |
| except ImportError: |
| print("Could not find the keyring library. Run 'sudo pip install keyring' to install.") |
| sys.exit(-1) |
| |
| try: |
| import jira.client |
| except ImportError: |
| print("Could not find jira-python library; exiting. Run 'sudo pip install jira' to install.") |
| sys.exit(-1) |
| |
| JIRA_BASE = "https://issues.apache.org/jira/browse" |
| JIRA_API_BASE = "https://issues.apache.org/jira" |
| |
| TMP_CREDENTIALS = {} |
| |
| def register(username, password): |
| """ Use this function to register a JIRA account in your OS' keyring """ |
| keyring.set_password('gobblin-pr', username, password) |
| |
| def validate_jira_id(jira_id): |
| if not jira_id: |
| return |
| elif isinstance(jira_id, int): |
| return 'GOBBLIN-{}'.format(abs(jira_id)) |
| |
| # first look for GOBBLIN-X |
| ids = re.findall("GOBBLIN-[0-9]{1,6}", jira_id) |
| if len(ids) > 1: |
| raise click.UsageError('Found multiple issue ids: {}'.format(ids)) |
| elif len(ids) == 1: |
| jira_id = ids[0] |
| elif not ids: |
| # if we don't find GOBBLIN-X, see if jira_id is an int |
| try: |
| jira_id = 'GOBBLIN-{}'.format(abs(int(jira_id))) |
| except ValueError: |
| raise click.UsageError( |
| 'JIRA id must be an integer or have the form GOBBLIN-X') |
| |
| return jira_id |
| |
| def update_jira_issue(fix_version): |
| """ |
| Update JIRA issue |
| |
| fix_version: the version to assign to the Gobblin JIRAs. |
| """ |
| |
| # ASF JIRA username |
| JIRA_USERNAME = os.environ.get("JIRA_USERNAME", '') |
| if not JIRA_USERNAME: |
| JIRA_USERNAME = TMP_CREDENTIALS.get('JIRA_USERNAME', '') |
| # ASF JIRA password |
| JIRA_PASSWORD = os.environ.get("JIRA_PASSWORD", '') |
| if not JIRA_PASSWORD: |
| JIRA_PASSWORD = TMP_CREDENTIALS.get('JIRA_PASSWORD', '') |
| |
| if not JIRA_USERNAME: |
| JIRA_USERNAME = click.prompt( |
| click.style('Username for Gobblin JIRA', fg='blue', bold=True), |
| type=str) |
| click.echo( |
| 'Set a JIRA_USERNAME env var to avoid this prompt in the future.') |
| TMP_CREDENTIALS['JIRA_USERNAME'] = JIRA_USERNAME |
| if JIRA_USERNAME and not JIRA_PASSWORD: |
| JIRA_PASSWORD = keyring.get_password("gobblin-pr", JIRA_USERNAME) |
| if JIRA_PASSWORD: |
| click.echo("Obtained password from keyring. To reset remove it there.") |
| if not JIRA_PASSWORD: |
| JIRA_PASSWORD = click.prompt( |
| click.style('Password for Gobblin JIRA', fg='blue', bold=True), |
| type=str, |
| hide_input=True) |
| if JIRA_USERNAME and JIRA_PASSWORD: |
| if click.confirm(click.style("Would you like to store your password " |
| "in your keyring?", fg='blue', bold=True)): |
| register(JIRA_USERNAME, JIRA_PASSWORD) |
| TMP_CREDENTIALS['JIRA_PASSWORD'] = JIRA_PASSWORD |
| |
| try: |
| asf_jira = jira.client.JIRA( |
| {'server': JIRA_API_BASE}, |
| basic_auth=(JIRA_USERNAME, JIRA_PASSWORD)) |
| except: |
| raise ValueError('Could not log in to JIRA!') |
| |
| for jira_obj in asf_jira.search_issues('filter=12342798', startAt=0, maxResults=2000): |
| jira_id = jira_obj.key |
| click.echo("Processing JIRA: %s" % jira_id) |
| |
| try: |
| issue = asf_jira.issue(jira_id) |
| fixVersions = [] |
| for version in issue.fields.fixVersions: |
| fixVersions.append({'name': version.name}) |
| fixVersions.append({'name': fix_version}) |
| issue.update(fields={'fixVersions': fixVersions}) |
| except Exception as e: |
| raise ValueError( |
| "ASF JIRA could not find issue {}\n{}".format(jira_id, e)) |
| |
| def update_jira_issues(): |
| fix_version = click.prompt( |
| click.style( |
| "Enter fix version", fg='blue', bold=True), |
| default=None) |
| |
| if fix_version is None: |
| raise click.UsageError('No fix version specified') |
| |
| update_jira_issue( |
| fix_version=fix_version) |
| |
| |
| if __name__ == "__main__": |
| try: |
| update_jira_issues() |
| except: |
| raise |