Skip to content

Commit 9fb8d33

Browse files
authored
Merge pull request #108 from sommersoft/issuepr_metrics
Add "Days Open" Metrics; Validate Issue Labels; CirPy.org AWS Transition; Misc Maintenance
2 parents de3bce8 + 671ce96 commit 9fb8d33

4 files changed

+75
-39
lines changed

adabot/circuitpython_libraries.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
if vals[0].startswith("validate")
100100
]
101101

102+
pr_sort_re = re.compile("(?<=\(Open\s)(.+)(?=\sdays)")
102103

103104
def run_library_checks(validators, bundle_submodules, latest_pylint, kw_args):
104105
"""runs the various library checking functions"""
@@ -204,7 +205,10 @@ def run_library_checks(validators, bundle_submodules, latest_pylint, kw_args):
204205
output_handler("Core")
205206
print_pr_overview(core_insights)
206207
output_handler("* {} open pull requests".format(len(core_insights["open_prs"])))
207-
for pr in core_insights["open_prs"]:
208+
sorted_prs = sorted(core_insights["open_prs"],
209+
key=lambda days: int(pr_sort_re.search(days).group(1)),
210+
reverse=True)
211+
for pr in sorted_prs:
208212
output_handler(" * {}".format(pr))
209213
print_issue_overview(core_insights)
210214
output_handler("* {} open issues".format(len(core_insights["open_issues"])))
@@ -223,7 +227,10 @@ def run_library_checks(validators, bundle_submodules, latest_pylint, kw_args):
223227
output_handler("Libraries")
224228
print_pr_overview(lib_insights)
225229
output_handler("* {} open pull requests".format(len(lib_insights["open_prs"])))
226-
for pr in lib_insights["open_prs"]:
230+
sorted_prs = sorted(lib_insights["open_prs"],
231+
key=lambda days: int(pr_sort_re.search(days).group(1)),
232+
reverse=True)
233+
for pr in sorted_prs:
227234
output_handler(" * {}".format(pr))
228235
print_issue_overview(lib_insights)
229236
output_handler("* {} open issues".format(len(lib_insights["open_issues"])))

adabot/lib/circuitpython_library_validators.py

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
ERROR_MISSING_EXAMPLE_FOLDER = "Missing examples folder"
5757
ERROR_EXAMPLE_MISSING_SENSORNAME = "Example file(s) missing sensor/library name"
5858
ERROR_MISSING_EXAMPLE_SIMPLETEST = "Missing simpletest example."
59+
ERROR_MISSING_STANDARD_LABELS = "Missing one or more standard issue labels (bug, documentation, enhancement, good first issue)."
5960
ERROR_MISSING_LIBRARIANS = "CircuitPythonLibrarians team missing or does not have write access"
6061
ERROR_MISSING_LICENSE = "Missing license."
6162
ERROR_MISSING_LINT = "Missing lint config"
@@ -133,6 +134,8 @@
133134
"Adafruit_CircuitPython_miniQR",
134135
]
135136

137+
STD_REPO_LABELS = ("bug", "documentation", "enhancement", "good first issue")
138+
136139
# Cache CircuitPython's subprojects on ReadTheDocs so its not fetched every repo check.
137140
rtd_subprojects = None
138141

@@ -439,14 +442,24 @@ def validate_contents(self, repo):
439442
return []
440443

441444
content_list = github.get("/repos/" + repo["full_name"] + "/contents/")
442-
# Empty repos return an object with a "message" that the repo is empty.
443-
if not content_list.ok or "message" in content_list.json():
444-
if not self.validate_contents_quiet:
445-
return [ERROR_UNABLE_PULL_REPO_CONTENTS]
446-
return []
445+
empty_repo = False
446+
if not content_list.ok:
447+
# Empty repos return:
448+
# - a 404 status code
449+
# - a "message" that the repo is empty.
450+
if "message" in content_list.json():
451+
if "empty" in content_list.json()["message"]:
452+
empty_repo = True
453+
if not empty_repo:
454+
if not self.validate_contents_quiet:
455+
return [ERROR_UNABLE_PULL_REPO_CONTENTS]
456+
return []
447457

448458
content_list = content_list.json()
449-
files = [x["name"] for x in content_list]
459+
files = []
460+
# an empty repo will return a 'message'
461+
if not empty_repo:
462+
files = [x["name"] for x in content_list]
450463

451464
# ignore new/in-work repos, which should have less than 8 files:
452465
# ___.py or folder, CoC, .travis.yml, .readthedocs.yml, docs/,
@@ -834,10 +847,17 @@ def gather_insights(self, repo, insights, since):
834847

835848
for issue in issues:
836849
created = datetime.datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ")
850+
days_open = datetime.datetime.today() - created
851+
if days_open.days < 0: # opened earlier today
852+
days_open += datetime.timedelta(days=(days_open.days * -1))
837853
if "pull_request" in issue:
838-
insights["open_prs"].append(issue["pull_request"]["html_url"])
854+
pr_link = "{0} (Open {1} days)".format(issue["pull_request"]["html_url"],
855+
days_open.days)
856+
insights["open_prs"].append(pr_link)
839857
else:
840-
insights["open_issues"].append(issue["html_url"])
858+
issue_link = "{0} (Open {1} days)".format(issue["html_url"],
859+
days_open.days)
860+
insights["open_issues"].append(issue_link)
841861

842862
# get milestones for core repo
843863
if repo["name"] == "circuitpython":
@@ -864,3 +884,22 @@ def validate_in_pypi(self, repo):
864884
if not common_funcs.repo_is_on_pypi(repo):
865885
return [ERROR_NOT_ON_PYPI]
866886
return []
887+
888+
def validate_labels(self, repo):
889+
"""ensures the repo has the standard labels available"""
890+
response = github.get("/repos/" + repo["full_name"] + "/labels")
891+
if not response.ok:
892+
# replace 'output_handler' with ERROR_OUTPUT_HANDLER
893+
self.output_file_data.append("Labels request failed: {}".format(repo["full_name"]))
894+
return [ERROR_OUTPUT_HANDLER]
895+
896+
repo_labels = [label["name"] for label in response.json()]
897+
has_all_labels = True
898+
for label in STD_REPO_LABELS:
899+
if not label in repo_labels:
900+
has_all_labels = False
901+
902+
if not has_all_labels:
903+
return [ERROR_MISSING_STANDARD_LABELS]
904+
else:
905+
return []

adabot/lib/common_funcs.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,8 @@ def is_new_or_updated(repo):
234234
new_releases = 0
235235
releases = result.json()
236236
for release in releases:
237+
if not release["published_at"]:
238+
continue
237239
release_date = datetime.datetime.strptime(
238240
release["published_at"],
239241
"%Y-%m-%dT%H:%M:%SZ"

adabot/update_cp_org_libraries.py

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import inspect
2727
import json
2828
import os
29+
import re
2930
import sh
3031
from sh.contrib import git
3132
import sys
@@ -46,6 +47,8 @@
4647
dest="output_file"
4748
)
4849

50+
sort_re = re.compile("(?<=\(Open\s)(.+)(?=\sdays)")
51+
4952
def get_open_issues_and_prs(repo):
5053
""" Retreive all of the open issues (minus pull requests) for the repo.
5154
"""
@@ -59,10 +62,17 @@ def get_open_issues_and_prs(repo):
5962

6063
issues = result.json()
6164
for issue in issues:
65+
created = datetime.datetime.strptime(issue["created_at"], "%Y-%m-%dT%H:%M:%SZ")
66+
days_open = datetime.datetime.today() - created
67+
if days_open.days < 0: # opened earlier today
68+
days_open += datetime.timedelta(days=(days_open.days * -1))
69+
70+
issue_title = "{0} (Open {1} days)".format(issue["title"],
71+
days_open.days)
6272
if "pull_request" not in issue: # ignore pull requests
63-
open_issues.append({issue["html_url"]: issue["title"]})
73+
open_issues.append({issue["html_url"]: issue_title})
6474
else:
65-
open_pull_requests.append({issue["html_url"]: issue["title"]})
75+
open_pull_requests.append({issue["html_url"]: issue_title})
6676

6777
return open_issues, open_pull_requests
6878

@@ -180,25 +190,6 @@ def update_json_file(json_string):
180190
print("Running circuitpython.org/libraries updater...")
181191

182192
run_time = datetime.datetime.now()
183-
# Travis CI weekly cron jobs do not allow or guarantee that they will be run
184-
# on a specific day of the week. So, we set the cron to run daily, and then
185-
# check for the day we want this to run.
186-
if "TRAVIS" in os.environ:
187-
should_run = int(os.environ["CP_ORG_UPDATER_RUN_DAY"])
188-
if run_time.isoweekday() != should_run:
189-
delta_days = should_run - run_time.isoweekday()
190-
run_delta = datetime.timedelta(days=delta_days)
191-
should_run_date = run_time + run_delta
192-
msg = [
193-
"Aborting...",
194-
" - Today is not {}.".format(should_run_date.strftime("%A")),
195-
" - Next scheduled run is: {}".format(should_run_date.strftime("%Y-%m-%d")),
196-
" - To run the updater on a different day, change the",
197-
" 'CP_ORG_UPDATER_RUN_DAY' environment variable in Travis.",
198-
" - Day is a number between 1 & 7, with 1 being Monday."
199-
]
200-
print("\n".join(msg))
201-
sys.exit()
202193

203194
working_directory = os.path.abspath(os.getcwd())
204195
#cp_org_dir = os.path.join(working_directory, ".cp_org")
@@ -319,11 +310,8 @@ def update_json_file(json_string):
319310
}
320311
json_obj = json.dumps(build_json, indent=2)
321312

322-
if "TRAVIS" in os.environ:
323-
update_json_file(json_obj)
324-
else:
325-
#update_json_file(json_obj)
326-
if local_file_output:
327-
with open(output_filename, "w") as json_file:
328-
json.dump(build_json, json_file, indent=2)
329-
print(json_obj)
313+
#update_json_file(json_obj)
314+
if local_file_output:
315+
with open(output_filename, "w") as json_file:
316+
json.dump(build_json, json_file, indent=2)
317+
print(json_obj)

0 commit comments

Comments
 (0)