Skip to content

Commit 99a1503

Browse files
committed
Add a script to help with jira requirements for backports
1 parent 3cd1ce2 commit 99a1503

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

jira-backport/README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Create jira bugs for backports from upstream
2+
3+
Create bugs for merging backports:
4+
- run script with the URL of the PR
5+
- check if there is an open bug for the component and release
6+
- create new bug with
7+
- component "Cloud Compute / OpenStack Provider" (for CAPO and CPO - we don't sync NFS to stable branches)
8+
- type bug
9+
- prio normal
10+
- Affects version: target branch
11+
- labels: Triaged
12+
- description
13+
- create a dependent bug if none already
14+
- search for open bugs with upper version
15+
- tag PR with the new bug
16+
17+
## Usage
18+
19+
Install dependencies:
20+
```
21+
❯ pip install -r requirements.txt
22+
```
23+
24+
Export both the `JIRA_TOKEN` and `GITHUB_TOKEN` environment variables with valid personal access tokens for [Jira](https://issues.redhat.com/secure/ViewProfile.jspa?selectedTab=com.atlassian.pats.pats-plugin:jira-user-personal-access-tokens) and [Github](https://github.com/settings/tokens).
25+
26+
Then run the script and pass it the URL of a pull request:
27+
28+
```
29+
❯ python ./jira-backport.py https://github.com/openshift/cluster-api-provider-openstack/pull/346
30+
no existing issue... will create one
31+
created issue: OCPBUGS-58028
32+
Retitling PR to: OCPBUGS-58028: Merge https://github.com/kubernetes-sigs/cluster-api-provider-openstack:release-0.10 into release-4.16
33+
```

jira-backport/jira-backport.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
from jira import JIRA
2+
from github import Github
3+
from github import Auth
4+
import os
5+
import re
6+
import sys
7+
8+
# TODO
9+
# - Set Target version to be the same as the affected version
10+
# - Set Release notes not required
11+
# - Set Assignee
12+
# - Create parent bug if needed
13+
# - Work on main/master and not just "release-xxx" branches
14+
15+
16+
def getUpstreamBranch(repo, branch):
17+
y_version = branch.split("release-4.")[1]
18+
# OCP follows kube release cycle, but with 13 y-versions difference
19+
kube_y_version = int(y_version) + 13
20+
if repo.name == "cluster-api-provider-openstack":
21+
if int(y_version) == 15:
22+
return "release-0.8"
23+
elif int(y_version) <= 17:
24+
return "release-0.10"
25+
elif int(y_version) <= 18:
26+
return "release-0.11"
27+
else:
28+
return "release-0.12"
29+
else:
30+
return "release-1.{}".format(kube_y_version)
31+
32+
33+
def getPR(url):
34+
m = re.match(r'.*github.com\/(?P<repo_name>[-_\w]+\/[-_\w]+)\/pull\/(?P<pr_number>\d+)', url)
35+
repo_name = m.group('repo_name')
36+
pr_number = int(m.group('pr_number'))
37+
38+
repo=github.get_repo(repo_name)
39+
pr = repo.get_pull(pr_number)
40+
41+
return pr
42+
43+
def findOrCreateJira(repo, branch):
44+
issue = findJira(repo, branch)
45+
46+
if issue:
47+
print("found existing issue: {}".format(issue))
48+
else:
49+
print("no existing issue... will create one")
50+
issue = createJira(repo, branch)
51+
print("created issue: {}".format(issue))
52+
return issue
53+
54+
55+
def findJira(repo, branch):
56+
version = branch.split("release-")[1]
57+
58+
if repo.name in ["cloud-provider-openstack", "cluster-api-provider-openstack"]:
59+
component = "Cloud Compute / OpenStack Provider"
60+
else:
61+
return
62+
query = 'summary ~ "Sync stable branch for {project}" and project = "OpenShift Bugs" and component = "{component}" and affectedVersion = {version}.z and status not in (Verified, Closed)'.format(
63+
project = repo.name,
64+
component = component,
65+
version = version,
66+
)
67+
issues = jira.search_issues(query, maxResults=1)
68+
for issue in issues:
69+
return issue
70+
71+
def createJira(repo, branch):
72+
upstream_branch = getUpstreamBranch(repo, branch)
73+
summary = 'Sync stable branch for {repo} {upstream_branch} into {branch}'.format(
74+
branch=branch,
75+
upstream_branch=upstream_branch,
76+
repo=repo.name,
77+
)
78+
description = """Description of problem:{{code:none}}
79+
{branch} of {repo} is missing some commits that were backported in upstream project into the {upstream_branch} branch.
80+
We should import them in our downstream fork.
81+
{{code}}""".format(branch=branch,
82+
upstream_branch=upstream_branch,
83+
repo=repo.full_name)
84+
version = branch.split("release-")[1]
85+
86+
# TODO(mandre) add test coverage and target version so that the but does
87+
# not remove the triage label
88+
# also assignee
89+
issue_dict = {
90+
'project': {'key': 'OCPBUGS'},
91+
'summary': summary,
92+
'description': description,
93+
'issuetype': {'name': 'Bug'},
94+
'priority': {'name': 'Normal'},
95+
'components': [{'name': 'Cloud Compute / OpenStack Provider'}],
96+
'labels': ['Triaged'],
97+
'versions': [{'name': "{}.z".format(version)}],
98+
}
99+
return jira.create_issue(fields=issue_dict)
100+
101+
def retitlePR(pr, issue_key):
102+
m = re.match(r'(OCPBUGS-\d+:\s*)?(?P<title>.+)', pr.title)
103+
new_title = "{}: {}".format(issue_key, m.group('title'))
104+
if pr.title != new_title:
105+
print("Retitling PR to: {}".format(new_title))
106+
pr.create_issue_comment("/retitle {}".format(new_title))
107+
108+
109+
if len(sys.argv) < 1:
110+
print("Pass the URL of a github PR from mergebot")
111+
exit()
112+
113+
# Get yours at
114+
# https://issues.redhat.com/secure/ViewProfile.jspa?selectedTab=com.atlassian.pats.pats-plugin:jira-user-personal-access-tokens
115+
jira_token = os.environ.get('JIRA_TOKEN', "")
116+
if jira_token == "":
117+
print("Missing or empty JIRA_TOKEN environment variable")
118+
exit()
119+
120+
# Get yours at https://github.com/settings/tokens
121+
gh_token = os.environ.get('GITHUB_TOKEN', "")
122+
if gh_token == "":
123+
print("Missing or empty GITHUB_TOKEN environment variable")
124+
exit()
125+
126+
jira = JIRA(server="https://issues.redhat.com", token_auth=jira_token)
127+
github = Github(auth=Auth.Token(gh_token))
128+
129+
url = sys.argv[1]
130+
pr = getPR(url)
131+
132+
issue = findOrCreateJira(pr.base.repo, pr.base.ref)
133+
134+
# Retitle github PR if needed
135+
if issue:
136+
retitlePR(pr, issue.key)

jira-backport/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
jira
2+
PyGithub

0 commit comments

Comments
 (0)