initial commit

This commit is contained in:
2023-02-18 07:39:08 +01:00
commit e63ab7b77e
63 changed files with 7122 additions and 0 deletions
+207
View File
@@ -0,0 +1,207 @@
import dataclasses
import logging
import os
import webbrowser
def force_import(module: str):
import importlib
import subprocess
import sys
try:
return importlib.import_module(module)
except ModuleNotFoundError:
subprocess.run([sys.executable, "-m", "pip", "install", module])
importlib.invalidate_caches()
return importlib.import_module(module)
try:
import httpx
except ImportError:
torf = force_import("httpx")
try:
import typer
except ImportError:
typer = force_import("typer")
try:
import rich
except ImportError:
rich = force_import("rich")
try:
import inquirer
except ImportError:
inquirer = force_import("inquirer")
from rich import print
import rich.table
JIRA_EMAIL = os.getenv('JIRA_EMAIL', 'abdussamet.kocak@akinon.com')
JIRA_TOKEN = os.getenv('JIRA_TOKEN', 'iAZhlJ1AdGwckbVllhlx48C4')
JIRA_URL = os.getenv('JIRA_URL', 'https://omniplatform.atlassian.net/')
if not JIRA_TOKEN:
logging.info('')
webbrowser.open('https://id.atlassian.com/manage-profile/security/api-tokens')
@dataclasses.dataclass
class Issue:
id: str
key: str
summary: str
@dataclasses.dataclass
class PullRequest:
id: str
name: str
repository: str
branch: str
class Jira:
def __init__(self, email: str, token: str):
self.client = httpx.Client(
base_url=JIRA_URL,
auth=httpx.BasicAuth(email, token),
)
def list_issues_for_release(self) -> list[Issue]:
mergeable_status = 'In Review'
res = self.client.post(
'/rest/api/2/search',
json={
'jql': f'project = COM AND status = "{mergeable_status}" AND "Team[Dropdown]" = Backend ORDER BY created DESC'
},
)
res.raise_for_status()
data = res.json()
development_type = ['Story', 'Bug', 'Task']
return [
Issue(id=it['id'], key=it['key'], summary=it['fields']['summary'])
for it in data['issues']
if it['fields']['issuetype']['name'] in development_type
]
def get_approved_prs(self, issue_id: str):
res = self.client.post(
f'/jsw/graphql',
params={'operation': 'DevDetailsDialog'},
json={
"operationName": "DevDetailsDialog",
"query": """
query DevDetailsDialog ($issueId: ID!) {
developmentInformation(issueId: $issueId){
details {
instanceTypes {
repository {
name
branches {
name
pullRequests {
name
status
lastUpdate
}
reviews {
state
id
}
}
pullRequests {
id
name
branchName
status
reviewers{
name
isApproved
}
}
}
danglingPullRequests {
id
name
branchName
status
reviewers{
name
isApproved
}
}
}
}
}
}
""",
"variables": {"issueId": issue_id},
},
)
res.raise_for_status()
data = res.json()['data']
if not data['developmentInformation']['details']['instanceTypes']:
return []
repo_name = data['developmentInformation']['details']['instanceTypes'][0]['repository'][0]['name']
prs = data['developmentInformation']['details']['instanceTypes'][0]['danglingPullRequests']
if not prs:
repo_name = data['developmentInformation']['details']['instanceTypes'][0]['repository'][0]['name']
prs = data['developmentInformation']['details']['instanceTypes'][0]['repository'][0]['pullRequests']
return [
PullRequest(
id=it['id'],
name=it['name'],
repository=repo_name,
branch=it['branchName'],
)
for it in prs
if it['status'] != 'MERGED'
]
console = rich.console.Console()
def render_issue(issue: Issue, prs: list[PullRequest]):
t = rich.table.Table(
title=f'{issue.key} -- {issue.summary}',
caption_justify='left',
)
t.add_column("Repository", no_wrap=True)
t.add_column("Branch", no_wrap=True)
t.add_column("Pull Request")
for it in prs:
t.add_row(it.repository, it.branch, it.name)
console.print(t)
def main():
logging.basicConfig(level=logging.INFO)
if not JIRA_EMAIL:
logging.error('JIRA_EMAIL is not set')
exit(1)
if not JIRA_TOKEN:
logging.error('JIRA_TOKEN is not set')
exit(1)
j = Jira(email=JIRA_EMAIL, token=JIRA_TOKEN)
logging.info('fetching issues in "ready to release" status')
issues = j.list_issues_for_release()
for it in issues:
logging.info(f'fetching pull requests for issue {it.key}')
prs = j.get_approved_prs(it.id)
if not prs:
logging.info(f'no non-merged pull requests found for issue {it.key}')
continue
render_issue(it, prs)
if __name__ == '__main__':
main()