github-overlord 0.6.9__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {github_overlord-0.6.9 → github_overlord-0.7.1}/PKG-INFO +4 -4
- {github_overlord-0.6.9 → github_overlord-0.7.1}/github_overlord/__init__.py +75 -17
- github_overlord-0.7.1/github_overlord/patch.py +14 -0
- {github_overlord-0.6.9 → github_overlord-0.7.1}/github_overlord/utils.py +16 -16
- {github_overlord-0.6.9 → github_overlord-0.7.1}/pyproject.toml +7 -7
- {github_overlord-0.6.9 → github_overlord-0.7.1}/LICENSE.md +0 -0
- {github_overlord-0.6.9 → github_overlord-0.7.1}/README.md +0 -0
- {github_overlord-0.6.9 → github_overlord-0.7.1}/github_overlord/stale_commenter.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: github-overlord
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: Automatically merge Dependabot PRs in public repositories
|
|
5
5
|
Home-page: https://github.com/iloveitaly/github-overlord
|
|
6
6
|
Keywords: github,dependabot,automation
|
|
@@ -12,11 +12,11 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Requires-Dist: apscheduler (>=3.10.4,<4.0.0)
|
|
14
14
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
15
|
-
Requires-Dist: funcy-pipe (>=0.11.
|
|
16
|
-
Requires-Dist: openai (>=1.
|
|
15
|
+
Requires-Dist: funcy-pipe (>=0.11.1,<0.12.0)
|
|
16
|
+
Requires-Dist: openai (>=1.41.1,<2.0.0)
|
|
17
17
|
Requires-Dist: pygithub (>=2.3.0,<3.0.0)
|
|
18
18
|
Requires-Dist: python-decouple-typed (>=3.11.0,<4.0.0)
|
|
19
|
-
Requires-Dist: structlog (>=24.
|
|
19
|
+
Requires-Dist: structlog (>=24.4.0,<25.0.0)
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
21
|
|
|
22
22
|
[](https://github.com/iloveitaly/github-overlord/releases) [](https://pepy.tech/project/github-overlord) [](https://pypi.org/project/github-overlord)  [](https://opensource.org/licenses/MIT)
|
|
@@ -10,12 +10,10 @@ from github.GithubObject import NotSet
|
|
|
10
10
|
from github.Notification import Notification
|
|
11
11
|
from github.PullRequest import PullRequest
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
)
|
|
18
|
-
from github_overlord.utils import log
|
|
13
|
+
import github_overlord.patch as _
|
|
14
|
+
|
|
15
|
+
from .stale_commenter import inspect_repo_for_stale_prs
|
|
16
|
+
from .utils import log
|
|
19
17
|
|
|
20
18
|
AUTOMATIC_MERGE_MESSAGE = "Automatically merged with [github-overlord](https://github.com/iloveitaly/github-overlord)"
|
|
21
19
|
|
|
@@ -244,26 +242,86 @@ def keep_alive_prs(token, dry_run, repo):
|
|
|
244
242
|
log.info("stale PR check complete")
|
|
245
243
|
|
|
246
244
|
|
|
247
|
-
|
|
245
|
+
@click.command()
|
|
246
|
+
@click.option(
|
|
247
|
+
"--token",
|
|
248
|
+
help="GitHub token, can also be set via GITHUB_TOKEN",
|
|
249
|
+
default=os.getenv("GITHUB_TOKEN"),
|
|
250
|
+
)
|
|
251
|
+
# TODO move this into the parent command
|
|
252
|
+
@click.option("--dry-run", is_flag=True, help="Run script without merging PRs")
|
|
253
|
+
@click.option(
|
|
254
|
+
"--only-unread", is_flag=True, help="Only process a single repository", default=True
|
|
255
|
+
)
|
|
256
|
+
def notifications(token, dry_run, only_unread):
|
|
248
257
|
"""
|
|
249
|
-
Look at notifications and mark them as read if they are
|
|
258
|
+
Look at notifications and mark them as read if they are:
|
|
259
|
+
|
|
260
|
+
* Dependabot notifications
|
|
261
|
+
* Releases on repos I own
|
|
262
|
+
* Closed (merged, closed) pull requests on repos I own
|
|
263
|
+
* Closed pull requests that I authored
|
|
264
|
+
|
|
265
|
+
Helpful if you work across a lot of repos and want to keep your notifications clean.
|
|
250
266
|
"""
|
|
251
267
|
|
|
252
|
-
|
|
253
|
-
user =
|
|
254
|
-
|
|
268
|
+
github = Github(token)
|
|
269
|
+
user = github.get_user()
|
|
270
|
+
login = user.login
|
|
271
|
+
|
|
272
|
+
# all includes read notifications AND done notifications :/
|
|
273
|
+
# there is no way to determine if a notification is marked as done
|
|
274
|
+
notifications = list(user.get_notifications(all=not only_unread))
|
|
275
|
+
|
|
276
|
+
# TODO fix funcy_pipe here
|
|
277
|
+
released_on_owned_repos = (
|
|
278
|
+
notifications
|
|
279
|
+
| fp.filter(
|
|
280
|
+
lambda n: n.subject.type == "Release"
|
|
281
|
+
and n.repository.owner.login == login
|
|
282
|
+
# TODO I think there is a way to convert the instance method to a standard method so it could be mapped
|
|
283
|
+
# patchy had some code for this
|
|
284
|
+
)
|
|
285
|
+
| fp.lmap(Notification.mark_as_done)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
log.info("marked releases as done", count=len(released_on_owned_repos))
|
|
255
289
|
|
|
256
|
-
def
|
|
257
|
-
|
|
290
|
+
def is_dependabot_notification(notification: Notification) -> bool:
|
|
291
|
+
return notification.get_pull_request().user.login == "dependabot[bot]"
|
|
292
|
+
|
|
293
|
+
def is_pull_request(notification: Notification) -> bool:
|
|
294
|
+
return notification.subject.type == "PullRequest"
|
|
295
|
+
|
|
296
|
+
def is_pull_request_open(notification: Notification) -> bool:
|
|
297
|
+
return notification.get_pull_request().state == "open"
|
|
298
|
+
|
|
299
|
+
# TODO github digest has some logic to detect bots, maybev we can use that
|
|
300
|
+
pull_requests_by_dependabot = (
|
|
301
|
+
notifications
|
|
302
|
+
| fp.filter(is_pull_request)
|
|
303
|
+
| fp.filter(is_dependabot_notification)
|
|
304
|
+
| fp.lmap(Notification.mark_as_done)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
log.info("marked dependabot PRs as done", count=len(pull_requests_by_dependabot))
|
|
308
|
+
|
|
309
|
+
# Closed (merged, closed) pull requests that I authored
|
|
310
|
+
owned_closed_pull_requests = (
|
|
311
|
+
notifications
|
|
312
|
+
# PRs that I did not author may still be interesting
|
|
313
|
+
| fp.where_attr(reason="author")
|
|
314
|
+
| fp.filter(is_pull_request)
|
|
315
|
+
| fp.filter(fp.complement(is_pull_request_open))
|
|
316
|
+
| fp.lmap(Notification.mark_as_done)
|
|
317
|
+
)
|
|
258
318
|
|
|
259
|
-
|
|
260
|
-
# print(f"Notification: {notification.subject['title']}, Reason: {notification.reason}")
|
|
261
|
-
# if not read_only:
|
|
262
|
-
# notification.mark_as_read()
|
|
319
|
+
log.info("marked owned closed PRs as done", count=len(owned_closed_pull_requests))
|
|
263
320
|
|
|
264
321
|
|
|
265
322
|
cli.add_command(dependabot)
|
|
266
323
|
cli.add_command(keep_alive_prs)
|
|
324
|
+
cli.add_command(notifications)
|
|
267
325
|
|
|
268
326
|
if __name__ == "__main__":
|
|
269
327
|
cli()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from github.Notification import Notification
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def mark_as_done(self) -> None:
|
|
5
|
+
"""
|
|
6
|
+
:calls: `PATCH /notifications/threads/{id} <https://docs.github.com/en/rest/activity/notifications?apiVersion=2022-11-28#mark-a-thread-as-done>`_
|
|
7
|
+
"""
|
|
8
|
+
headers, data = self._requester.requestJsonAndCheck(
|
|
9
|
+
"DELETE",
|
|
10
|
+
self.url,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
Notification.mark_as_done = mark_as_done
|
|
@@ -9,8 +9,23 @@ from pathlib import Path
|
|
|
9
9
|
import structlog
|
|
10
10
|
from decouple import config
|
|
11
11
|
|
|
12
|
+
root: Path
|
|
13
|
+
|
|
14
|
+
# must type manually, unfortunately :/
|
|
15
|
+
# https://www.structlog.org/en/21.3.0/types.html
|
|
16
|
+
log: structlog.stdlib.BoundLogger
|
|
17
|
+
|
|
12
18
|
|
|
13
19
|
def configure_logger():
|
|
20
|
+
global log
|
|
21
|
+
|
|
22
|
+
# context manager to auto-clear context
|
|
23
|
+
log.context = structlog.contextvars.bound_contextvars # type: ignore
|
|
24
|
+
# set thread-local context
|
|
25
|
+
log.local = structlog.contextvars.bind_contextvars # type: ignore
|
|
26
|
+
# clear thread-local context
|
|
27
|
+
log.clear = structlog.contextvars.clear_contextvars # type: ignore
|
|
28
|
+
|
|
14
29
|
logger_factory = structlog.PrintLoggerFactory()
|
|
15
30
|
|
|
16
31
|
# allow user to specify a log in case they want to do something meaningful with the stdout
|
|
@@ -38,30 +53,15 @@ def configure_logger():
|
|
|
38
53
|
)
|
|
39
54
|
|
|
40
55
|
|
|
41
|
-
# must type manually, unfortunately :/
|
|
42
|
-
# https://www.structlog.org/en/21.3.0/types.html
|
|
43
|
-
log: structlog.stdlib.BoundLogger
|
|
44
|
-
|
|
45
|
-
|
|
46
56
|
def setup():
|
|
47
57
|
if hasattr(setup, "complete") and setup.complete:
|
|
48
58
|
return
|
|
49
59
|
|
|
50
|
-
global root,
|
|
60
|
+
global root, log
|
|
51
61
|
|
|
52
62
|
root = Path(__file__).parent.parent
|
|
53
63
|
|
|
54
64
|
log = structlog.get_logger()
|
|
55
|
-
|
|
56
|
-
# context manager to auto-clear context
|
|
57
|
-
log.context = structlog.contextvars.bound_contextvars # type: ignore
|
|
58
|
-
# set thread-local context
|
|
59
|
-
log.local = structlog.contextvars.bind_contextvars # type: ignore
|
|
60
|
-
# clear thread-local context
|
|
61
|
-
log.clear = structlog.contextvars.clear_contextvars # type: ignore
|
|
62
|
-
|
|
63
|
-
logger = log
|
|
64
|
-
|
|
65
65
|
configure_logger()
|
|
66
66
|
|
|
67
67
|
log.debug("application setup")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "github-overlord"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.1"
|
|
4
4
|
description = "Automatically merge Dependabot PRs in public repositories"
|
|
5
5
|
authors = ["Michael Bianco <mike@mikebian.co>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -12,10 +12,10 @@ python = "^3.11"
|
|
|
12
12
|
pygithub = "^2.3.0"
|
|
13
13
|
click = "^8.1.7"
|
|
14
14
|
python-decouple-typed = "^3.11.0"
|
|
15
|
-
funcy-pipe = "^0.11.
|
|
16
|
-
structlog = "^24.
|
|
15
|
+
funcy-pipe = "^0.11.1"
|
|
16
|
+
structlog = "^24.4.0"
|
|
17
17
|
apscheduler = "^3.10.4"
|
|
18
|
-
openai = "^1.
|
|
18
|
+
openai = "^1.41.1"
|
|
19
19
|
|
|
20
20
|
[tool.poetry.scripts]
|
|
21
21
|
github-overlord = "github_overlord:cli"
|
|
@@ -28,9 +28,9 @@ float_to_top = true
|
|
|
28
28
|
|
|
29
29
|
[tool.poetry.group.dev.dependencies]
|
|
30
30
|
isort = "^5.13.2"
|
|
31
|
-
black = "^24.
|
|
32
|
-
pyright = "^1.1.
|
|
33
|
-
pylint = "^3.2.
|
|
31
|
+
black = "^24.8.0"
|
|
32
|
+
pyright = "^1.1.376"
|
|
33
|
+
pylint = "^3.2.6"
|
|
34
34
|
|
|
35
35
|
[build-system]
|
|
36
36
|
requires = ["poetry-core"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|