Skip to content

Commit c9c9596

Browse files
Merge pull request #217 from shiftstack/jira-backport
Add a script to help with jira requirements for backports
2 parents 3cd1ce2 + d4b5208 commit c9c9596

File tree

3 files changed

+178
-0
lines changed

3 files changed

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