-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtask-bot.py
executable file
·123 lines (102 loc) · 3.62 KB
/
task-bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
import argparse
import os
from datetime import datetime
from math import floor
from typing import Optional
import requests
from github import Github
from github.Label import Label
from github.Milestone import Milestone
from github.Repository import Repository
def as_percentage(a: float, b: float) -> int:
if b == 0:
return 0
return floor((a / b) * 100)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument("repo", type=str)
return parser.parse_args()
def get_in_progress_label(repo: Repository) -> Optional[Label]:
for label in repo.get_labels():
if "in progress" in label.name.lower():
return label
return None
def get_blocked_label(repo: Repository) -> Optional[Label]:
for label in repo.get_labels():
if "blocked" in label.name.lower():
return label
return None
def process_milestone(
repo: Repository,
milestone: Milestone,
in_progress_label: Optional[Label],
blocked_label: Optional[Label],
) -> str:
now = datetime.now()
html_url = milestone._rawData["html_url"] # type: ignore
total_issues = milestone.open_issues + milestone.closed_issues
percentage_complete = as_percentage(milestone.closed_issues, total_issues)
detail_lines = []
status_line = f":white_check_mark: {percentage_complete}% completed"
if in_progress_label:
in_progress_issues = list(
repo.get_issues(
milestone=milestone, labels=[in_progress_label], state="open"
)
)
if in_progress_issues:
percentage_in_progress = as_percentage(
len(in_progress_issues), total_issues
)
status_line += (
f" - :hourglass_flowing_sand: {percentage_in_progress}% in progress"
)
if blocked_label:
blocked_issues = list(
repo.get_issues(milestone=milestone, labels=[blocked_label], state="open")
)
if blocked_issues:
percentage_blocked = as_percentage(len(blocked_issues), total_issues)
status_line += f" - :octagonal_sign: {percentage_blocked}% blocked"
detail_lines.append(status_line)
if milestone.due_on:
duration = milestone.due_on - milestone.created_at
remaining = milestone.due_on - now
time_used = 100 - as_percentage(remaining.days, duration.days)
detail_lines.append(
f":date: {milestone.due_on.date().isoformat()} - :alarm_clock: {time_used}% time used"
)
rendered_line = (
f"<{html_url}|{milestone.title}> - {milestone.closed_issues}/{total_issues}"
)
for line in detail_lines:
rendered_line += f"\n\t{line}"
return rendered_line
def main() -> None:
args = parse_args()
github = Github(os.environ.get("GITHUB_TOKEN"))
repo = github.get_repo(args.repo)
in_progress_label = get_in_progress_label(repo)
blocked_label = get_blocked_label(repo)
messages = [
process_milestone(repo, milestone, in_progress_label, blocked_label)
for milestone in repo.get_milestones(sort="due_on")
]
if not messages:
return
webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
title = f"*Task Status for <{repo.html_url}|{repo.full_name}>*"
if webhook_url:
response = requests.post(
webhook_url,
json={
"text": title,
"attachments": [{"text": message} for message in messages],
},
)
response.raise_for_status()
print(title)
print("\n".join(messages))
if __name__ == "__main__":
main()