blob: 1405175581125c2ed862ff47341938904500bd98 [file]
#
# 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.
#
import os
import re
import sys
try:
import jira.client
JIRA_IMPORTED = True
except ImportError:
JIRA_IMPORTED = False
# ASF JIRA access token
JIRA_ACCESS_TOKEN = os.environ.get("JIRA_ACCESS_TOKEN")
JIRA_API_BASE = "https://issues.apache.org/jira"
# Default JIRA component for Apache Spark Docker issues
DEFAULT_COMPONENT = "Spark Docker"
def fail(msg):
print(msg)
sys.exit(-1)
def get_jira_client():
"""Create and return a JIRA client, or exit with a helpful message."""
errors = []
if not JIRA_IMPORTED:
errors.append("jira-python library not installed, run 'pip install jira'")
if not JIRA_ACCESS_TOKEN:
errors.append("JIRA_ACCESS_TOKEN env-var not set")
if errors:
fail(
"Cannot create JIRA ticket automatically (%s). "
"Please create the ticket manually at %s" % ("; ".join(errors), JIRA_API_BASE)
)
return jira.client.JIRA(
{"server": JIRA_API_BASE}, token_auth=JIRA_ACCESS_TOKEN, timeout=(3.05, 30)
)
def detect_affected_version(asf_jira):
"""Return the latest unreleased x.y.z version, or exit."""
versions = asf_jira.project_versions("SPARK")
versions = [
x
for x in versions
if not x.raw["released"] and not x.raw["archived"] and re.match(r"\d+\.\d+\.\d+", x.name)
]
versions = sorted(versions, key=lambda x: x.name, reverse=True)
if not versions:
fail(
"Cannot detect affected version. "
"Please create the ticket manually at %s" % JIRA_API_BASE
)
return versions[0].name
def list_components(asf_jira):
"""Print all non-archived Spark JIRA components."""
components = asf_jira.project_components("SPARK")
components = [c for c in components if not c.raw.get("archived", False)]
for c in sorted(components, key=lambda x: x.name):
print(c.name)
def create_jira_issue(asf_jira, title, component, parent=None, issue_type=None, version=None):
"""Create a JIRA issue and return the issue key (e.g. SPARK-12345)."""
affected_version = version if version else detect_affected_version(asf_jira)
issue_dict = {
"project": {"key": "SPARK"},
"summary": title,
"description": "",
"versions": [{"name": affected_version}],
"components": [{"name": component}],
}
if parent:
issue_dict["issuetype"] = {"name": "Sub-task"}
issue_dict["parent"] = {"key": parent}
else:
issue_dict["issuetype"] = {"name": issue_type if issue_type else "Improvement"}
try:
new_issue = asf_jira.create_issue(fields=issue_dict)
return new_issue.key
except Exception as e:
fail("Failed to create JIRA issue: %s" % e)