Skip to content

Commit 931600d

Browse files
committed
create_ticket, Initial version
Signed-off-by: Or Shoval <[email protected]>
1 parent d27223f commit 931600d

File tree

10 files changed

+323
-130
lines changed

10 files changed

+323
-130
lines changed

.gitignore

Lines changed: 2 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -1,129 +1,2 @@
1-
# Byte-compiled / optimized / DLL files
2-
__pycache__/
3-
*.py[cod]
4-
*$py.class
5-
6-
# C extensions
7-
*.so
8-
9-
# Distribution / packaging
10-
.Python
11-
build/
12-
develop-eggs/
13-
dist/
14-
downloads/
15-
eggs/
16-
.eggs/
17-
lib/
18-
lib64/
19-
parts/
20-
sdist/
21-
var/
22-
wheels/
23-
pip-wheel-metadata/
24-
share/python-wheels/
25-
*.egg-info/
26-
.installed.cfg
27-
*.egg
28-
MANIFEST
29-
30-
# PyInstaller
31-
# Usually these files are written by a python script from a template
32-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33-
*.manifest
34-
*.spec
35-
36-
# Installer logs
37-
pip-log.txt
38-
pip-delete-this-directory.txt
39-
40-
# Unit test / coverage reports
41-
htmlcov/
42-
.tox/
43-
.nox/
44-
.coverage
45-
.coverage.*
46-
.cache
47-
nosetests.xml
48-
coverage.xml
49-
*.cover
50-
*.py,cover
51-
.hypothesis/
52-
.pytest_cache/
53-
54-
# Translations
55-
*.mo
56-
*.pot
57-
58-
# Django stuff:
59-
*.log
60-
local_settings.py
61-
db.sqlite3
62-
db.sqlite3-journal
63-
64-
# Flask stuff:
65-
instance/
66-
.webassets-cache
67-
68-
# Scrapy stuff:
69-
.scrapy
70-
71-
# Sphinx documentation
72-
docs/_build/
73-
74-
# PyBuilder
75-
target/
76-
77-
# Jupyter Notebook
78-
.ipynb_checkpoints
79-
80-
# IPython
81-
profile_default/
82-
ipython_config.py
83-
84-
# pyenv
85-
.python-version
86-
87-
# pipenv
88-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91-
# install all needed dependencies.
92-
#Pipfile.lock
93-
94-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95-
__pypackages__/
96-
97-
# Celery stuff
98-
celerybeat-schedule
99-
celerybeat.pid
100-
101-
# SageMath parsed files
102-
*.sage.py
103-
104-
# Environments
105-
.env
106-
.venv
107-
env/
108-
venv/
109-
ENV/
110-
env.bak/
111-
venv.bak/
112-
113-
# Spyder project settings
114-
.spyderproject
115-
.spyproject
116-
117-
# Rope project settings
118-
.ropeproject
119-
120-
# mkdocs documentation
121-
/site
122-
123-
# mypy
124-
.mypy_cache/
125-
.dmypy.json
126-
dmypy.json
127-
128-
# Pyre type checker
129-
.pyre/
1+
__pycache__
2+
secret.txt

Dockerfile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM fedora
2+
3+
# Install packages
4+
RUN dnf install -y python3 \
5+
git \
6+
pip
7+
8+
RUN pip install requests
9+
RUN pip install jira
10+
11+
CMD [“echo”, “Hello World!”]
12+

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@
186186
same "printed page" as the copyright notice for easier
187187
identification within third-party archives.
188188

189-
Copyright [yyyy] [name of copyright owner]
189+
Copyright [2021] [The KubeVirt Authors]
190190

191191
Licensed under the Apache License, Version 2.0 (the "License");
192192
you may not use this file except in compliance with the License.

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,43 @@
11
# github2jira
22
Scrap github issues and create Jira tickets
3+
4+
## One time configuration
5+
1. Create github token https://github.com/settings/tokens, refer it as `GITHUB_TOKEN`
6+
2. Make sure you have a Jira bot access (either a user:pass or user:token), refer as `JIRA_USERNAME`,`JIRA_TOKEN`
7+
3. Get your Jira project id, refer as `JIRA_PROJECT_ID`
8+
`curl -s -u JIRA_USERNAME:JIRA_TOKEN -X GET -H "Content-Type: application/json" <JIRA_SERVER>/rest/api/latest/project/<JIRA_PROJECT> | jq .id`
9+
10+
## Running manually
11+
12+
1. export the following envvars:
13+
```
14+
export JIRA_SERVER=<..> # for example https://nmstate.atlassian.net
15+
export JIRA_PROJECT=<..> # name of the Jira project (ticket names are JIRA_PROJECT-#)
16+
export JIRA_PROJECT_ID=<..> # see "One time configuration" section
17+
export JIRA_COMPONENT=<..> # which component to set in the created tickets
18+
export GITHUB_OWNER=<..> # the x of https://github.com/x/y
19+
export GITHUB_REPO=<..> # the y of https://github.com/x/y
20+
export GITHUB_LABEL=<..> # which label to filter
21+
22+
export JIRA_USERNAME=<..> # see "One time configuration" section
23+
export JIRA_TOKEN=<..> # see "One time configuration" section
24+
export GITHUB_TOKEN=<..> # see "One time configuration" section
25+
```
26+
27+
2. Run `./create_ticket.py` in order to fetch github issues and create a ticket for them
28+
29+
## Running as k8s payload
30+
31+
### One time configuration: Build docker image for the script
32+
33+
1. Run `docker build -f Dockerfile -t <image> .`
34+
once its done, push it to your image repository, or rename and push to a local registry.
35+
36+
### Deploy as k8s payload
37+
38+
1. Create secret.txt with the exports from the section above (include the export command).
39+
40+
2. Create a configmap for the txt file
41+
`kubectl create configmap git-token --from-file=secret.txt`
42+
43+
3. Deploy either a pod or a CronJob (see manifests folder).

common.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import sys
5+
6+
def get_envvar(name, default_value=None):
7+
value = os.getenv(name, default_value)
8+
if value == None:
9+
print(f"Error: cant find {name}, exiting")
10+
sys.exit(1)
11+
return value
12+
13+
def main():
14+
print("common self test")
15+
get_envvar('JIRA_TOKEN')
16+
17+
if __name__ == '__main__':
18+
main()

create_ticket.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import json
5+
import sys
6+
import argparse
7+
8+
from common import get_envvar
9+
from jiralib import Jira
10+
from githublib import Github
11+
12+
# max github pages to process
13+
GITHUB_MAX_PAGES = 20
14+
# process upto x weeks back
15+
max_delta_weeks = 4
16+
# how many tickets can be opened on each cycle
17+
flood_protection_limit = 3
18+
19+
def process_issue(jira, github, issue, dryrun):
20+
html_url = issue["html_url"]
21+
22+
if "pull" in html_url:
23+
return False
24+
25+
if github.check_labels(issue) == False:
26+
return False
27+
28+
issue_id = issue["number"]
29+
if jira.issue_exists(github.repo, issue_id) == False:
30+
if github.check_time(issue, max_delta_weeks) == False:
31+
return False
32+
33+
if dryrun == False:
34+
created_issue = jira.create_issue(github.repo, issue_id, issue["title"], html_url)
35+
print(f'Created issue {jira.server}/browse/{created_issue} for {html_url}')
36+
else:
37+
print(f'Dry Run Created issue for {html_url}')
38+
return True
39+
else:
40+
print("Issue for", html_url, "already exists")
41+
42+
return False
43+
44+
def loop(jira, github, dryrun):
45+
issues_created = 0
46+
47+
for page in range(1, GITHUB_MAX_PAGES):
48+
issues = github.get_issues(page)
49+
if len(issues) == 0:
50+
break
51+
52+
for issue in issues:
53+
res = process_issue(jira, github, issue, dryrun)
54+
if res == True:
55+
issues_created += 1
56+
if issues_created == flood_protection_limit:
57+
print("Flood protection limit reached, exiting")
58+
sys.exit(0)
59+
60+
def main():
61+
server = get_envvar('JIRA_SERVER')
62+
username = get_envvar('JIRA_USERNAME')
63+
token = get_envvar('JIRA_TOKEN')
64+
project = get_envvar('JIRA_PROJECT')
65+
project_id = get_envvar('JIRA_PROJECT_ID')
66+
jira_component = get_envvar('JIRA_COMPONENT')
67+
68+
github_token = get_envvar('GITHUB_TOKEN')
69+
github_owner = get_envvar('GITHUB_OWNER')
70+
github_repo = get_envvar('GITHUB_REPO')
71+
github_label = get_envvar('GITHUB_LABEL')
72+
73+
parser = argparse.ArgumentParser()
74+
parser.add_argument('--dryrun', default=False, action='store_true')
75+
args = parser.parse_args()
76+
77+
if args.dryrun:
78+
print("INFO: dryrun mode enabled")
79+
80+
github = Github(github_token, github_owner, github_repo, github_label)
81+
jira = Jira(server, username, token, project, project_id, jira_component)
82+
83+
loop(jira, github, args.dryrun)
84+
85+
if __name__ == '__main__':
86+
main()

githublib.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
import sys
5+
import requests
6+
import json
7+
import time
8+
from datetime import datetime
9+
10+
from common import get_envvar
11+
12+
SECONDS_PER_WEEK = 604800
13+
14+
class Github:
15+
def __init__(self, token, owner, repo, expected_label):
16+
self.owner = owner
17+
self.repo = repo
18+
self.expected_label = expected_label
19+
self.query_url = f"https://github.com/api/repos/{owner}/{repo}/issues"
20+
self.headers = {'Authorization': f'token {token}'}
21+
22+
def get_issues(self, page):
23+
params = {
24+
"state": "open", "page" : page, "per_page": "100"
25+
}
26+
27+
r = requests.get(self.query_url, headers=self.headers, params=params)
28+
data = r.json()
29+
return data
30+
31+
def check_labels(self, issue):
32+
if self.expected_label == "":
33+
return True
34+
for label in issue["labels"]:
35+
if label["name"] == self.expected_label:
36+
return True
37+
return False
38+
39+
def check_time(self, issue, max_delta):
40+
epoch_time_now = int(time.time())
41+
epoch = int(datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ").timestamp())
42+
return (epoch_time_now - epoch) < (max_delta * SECONDS_PER_WEEK)
43+
44+
def main():
45+
print("githublib self test")
46+
47+
github_token = get_envvar('GITHUB_TOKEN')
48+
github_owner = get_envvar('GITHUB_OWNER')
49+
github_repo = get_envvar('GITHUB_REPO')
50+
51+
github = Github(github_token, github_owner, github_repo, "")
52+
data = github.get_issues(1)
53+
print(json.dumps(data[0], sort_keys=True, indent=4))
54+
55+
if __name__ == '__main__':
56+
main()

0 commit comments

Comments
 (0)