Skip to content

Commit 095aa7c

Browse files
committed
split manifest and use asyncio
1 parent 49fd388 commit 095aa7c

File tree

157 files changed

+2241
-54
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+2241
-54
lines changed

.github/workflows/links.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
linkChecker:
1616
runs-on: ubuntu-latest
1717
steps:
18-
- uses: actions/checkout@v3
18+
- uses: actions/checkout@v4
1919

2020
- name: Link Checker
2121
id: lychee

.github/workflows/python-passed.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ jobs:
99
continue-on-error: true
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v2
12+
- uses: actions/checkout@v4
1313
name: Checkout Repository
1414
with:
1515
token: ${{ secrets.UPDATER }}
1616
# otherwise, you will failed to push refs to dest repo
1717
fetch-depth: 0
1818
- name: Set up Python 3.7
19-
uses: actions/setup-python@v1
19+
uses: actions/setup-python@v5
2020
with:
2121
python-version: 3.7
2222
- name: Run script

.github/workflows/test-python.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
outputs:
2525
plugins: ${{ steps.filter.outputs.plugins }}
2626
steps:
27-
- uses: actions/checkout@v2
27+
- uses: actions/checkout@v4
2828
- uses: dorny/paths-filter@v2
2929
id: filter
3030
with:
@@ -36,15 +36,15 @@ jobs:
3636
if: ${{ needs.skip_check_job.outputs.plugins == 'true' }}
3737
runs-on: windows-latest
3838
steps:
39-
- uses: actions/checkout@v2
39+
- uses: actions/checkout@v4
4040
- if: ${{ github.event_name == 'pull_request'}}
4141
name: "Set up Python 3.11 for pull request test"
42-
uses: actions/setup-python@v1
42+
uses: actions/setup-python@v5
4343
with:
4444
python-version: 3.11
4545
- if: ${{ github.event_name == 'workflow_dispatch'}}
4646
name: "Set up Python ${{ github.event.inputs.pyversion }} for manual test"
47-
uses: actions/setup-python@v1
47+
uses: actions/setup-python@v5
4848
with:
4949
python-version: ${{ github.event.inputs.pyversion }}
5050
- uses: actions/cache@v2

.github/workflows/updater.yaml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ jobs:
99
update:
1010
runs-on: ubuntu-latest
1111
steps:
12-
- uses: actions/checkout@v2
12+
- uses: actions/checkout@v4
1313
with:
1414
token: ${{ secrets.UPDATER }}
1515
# otherwise, you will failed to push refs to dest repo
1616
fetch-depth: 0
1717

18-
- uses: actions/setup-python@v2
18+
- uses: actions/setup-python@v5
1919
with:
2020
python-version: "3.x"
2121

@@ -29,6 +29,10 @@ jobs:
2929
run: |
3030
python ./ci/src/updater.py ${{ secrets.DISCORD_WEBHOOK }}
3131
32+
- name: Merge Manifest
33+
run: |
34+
python ./ci/src/merge-manifest.py
35+
3236
- name: Commit & Push changes
3337
uses: stefanzweifel/git-auto-commit-action@v4
3438
with:

.github/workflows/validator.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ jobs:
1919
if: ${{ needs.pre_job.outputs.should_skip != 'true' }}
2020
runs-on: ubuntu-latest
2121
steps:
22-
- uses: actions/checkout@v2
23-
- uses: actions/setup-python@v2
22+
- uses: actions/checkout@v4
23+
- uses: actions/setup-python@v5
2424
with:
2525
python-version: "3.x"
2626

ci/envs/requirements-updater.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
requests
1+
aiohttp
22
tqdm

ci/src/_utils.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
from pathlib import Path
44
from typing import Dict, List, TypeVar
55
import re
6+
import os
67

78
# path
89
utils_path = Path(__file__).resolve()
910

1011
src_dir = utils_path.parent
1112
ci_dir = src_dir.parent
1213
base_dir = ci_dir.parent
13-
plugin_file = base_dir / "plugins.json"
14+
plugin_dir = base_dir / "plugins/"
1415
etag_file = base_dir / "etags.json"
1516

1617
# constants
@@ -40,8 +41,16 @@
4041

4142

4243
def plugin_reader() -> P:
43-
with open(plugin_file, "r", encoding="utf-8") as f:
44-
return json.load(f)
44+
plugin_files = [os.path.join(plugin_dir, file) for file in os.listdir(plugin_dir)]
45+
46+
manifests = []
47+
48+
for plugin in plugin_files:
49+
with open(plugin, "r", encoding="utf-8") as f:
50+
manifest = json.load(f)
51+
manifests.append(manifest)
52+
53+
return manifests
4554

4655

4756
def etag_reader() -> ETagsType:
@@ -50,8 +59,9 @@ def etag_reader() -> ETagsType:
5059

5160

5261
def plugin_writer(content: P):
53-
with open(plugin_file, "w", encoding="utf-8") as f:
54-
json.dump(content, f, indent=4)
62+
for plugin in content:
63+
with open(plugin_dir / f"{plugin[plugin_name]}-{plugin[id_name]}.json", "w", encoding="utf-8") as f:
64+
json.dump(plugin, f, indent=4)
5565

5666
def etags_writer(content: ETagsType):
5767
with open(etag_file, "w", encoding="utf-8") as f:

ci/src/discord.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
import aiohttp
12
import requests
23

34
from _utils import *
45

56
MAX_BODY_LEN = 1024
67

78

8-
def update_hook(webhook_url: str, info: dict, latest_ver: str, release: dict) -> None:
9+
async def update_hook(webhook_url: str, info: dict, latest_ver: str, release: dict) -> None:
910
embed = {
1011
"content": None,
1112
"embeds": [
@@ -41,7 +42,8 @@ def update_hook(webhook_url: str, info: dict, latest_ver: str, release: dict) ->
4142
release_notes = release.get('body')
4243
if release_notes and release_notes.strip():
4344
embed['embeds'][0]['fields'].append({"name": "Release Notes", "value": truncate_release_notes(release['html_url'], release.get('body', ""))})
44-
requests.post(webhook_url, json=embed)
45+
async with aiohttp.ClientSession() as session:
46+
await session.post(webhook_url, json=embed)
4547

4648
def truncate_release_notes(url: str, release_notes: str, length: int = MAX_BODY_LEN) -> str:
4749
if len(release_notes) <= length:

ci/src/merge-manifest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import os
2+
from os import path
3+
import json
4+
5+
if __name__ == "__main__":
6+
plugins = [file for file in os.listdir("plugins") if path.isfile(file) and file.endswith("json")]
7+
8+
manifests = []
9+
10+
for plugin in plugins:
11+
with open(plugin, "r") as f:
12+
manifest = json.load(f)
13+
manifests.append(manifest)
14+
15+
with open("plugins.json", "w") as f:
16+
json.dump(manifests, f, indent=4)
17+

ci/src/updater.py

Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
# -*-coding: utf-8 -*-
2-
from http.client import responses
2+
import asyncio
3+
import aiohttp
34
from typing import List
45
from unicodedata import name
56
from os import getenv
67
from sys import argv
78
import traceback
89

910
import requests
10-
from tqdm import tqdm
11+
from tqdm.asyncio import tqdm
1112

1213
from _utils import *
1314
from discord import update_hook
1415

1516

16-
def batch_github_plugin_info(info: P, tags: ETagsType, webhook_url: str = None) -> P:
17+
async def batch_github_plugin_info(
18+
info: P, tags: ETagsType, github_token=None, webhook_url: str = None
19+
) -> P:
1720
try:
18-
headers = {"authorization": f"token {getenv('GITHUB_TOKEN','')}"}
21+
headers = {"authorization": f"token {github_token}"}
1922
if "github.com" not in info[url_download]:
2023
return info
2124

@@ -28,69 +31,91 @@ def batch_github_plugin_info(info: P, tags: ETagsType, webhook_url: str = None)
2831

2932
if release_date in info.keys():
3033
headers["If-None-Match"] = tag
31-
res = requests.get(
32-
url_release.format(repo=repo),
33-
headers=headers,
34-
)
35-
if res.status_code in (403, 304):
36-
return info
3734

38-
latest_rel = res.json()
39-
assets = latest_rel.get("assets")
40-
if info.get(release_date, '') != latest_rel.get('published_at'):
41-
info[release_date] = latest_rel.get('published_at')
42-
if assets:
43-
info[url_download] = assets[0]["browser_download_url"]
44-
send_notification(info, clean(
45-
latest_rel["tag_name"], "v"), latest_rel, webhook_url)
46-
info[version] = clean(latest_rel["tag_name"], "v")
35+
async with aiohttp.ClientSession() as session:
36+
res = await session.get(
37+
url_release.format(repo=repo),
38+
headers=headers,
39+
)
40+
if res.status in (403, 304):
41+
return info
4742

48-
tags[info[id_name]] = res.headers.get(etag, "")
43+
latest_rel = await res.json()
4944

50-
return info
45+
assets = latest_rel.get("assets")
46+
47+
if info.get(release_date, "") != latest_rel.get("published_at"):
48+
info[release_date] = latest_rel.get("published_at")
49+
if assets:
50+
info[url_download] = assets[0]["browser_download_url"]
51+
await send_notification(
52+
info, clean(latest_rel["tag_name"], "v"), latest_rel, webhook_url
53+
)
54+
info[version] = clean(latest_rel["tag_name"], "v")
55+
56+
tags[info[id_name]] = res.headers.get(etag, "")
57+
58+
return info
5159
except Exception as e:
5260
tb = traceback.format_exc()
5361
print(f"Error when processing plugin {info[plugin_name]}:\n{e} {tb}")
5462
return info
5563

5664

57-
def batch_plugin_infos(plugin_infos: Ps, tags: ETagsType, webhook_url: str = None) -> Ps:
58-
return [batch_github_plugin_info(info, tags, webhook_url) for info in tqdm(plugin_infos)]
65+
async def batch_plugin_infos(
66+
plugin_infos: Ps, tags: ETagsType, github_token, webhook_url: str = None
67+
) -> Ps:
68+
return await tqdm.gather(
69+
*[
70+
batch_github_plugin_info(info, tags, github_token, webhook_url)
71+
for info in tqdm(plugin_infos)
72+
]
73+
)
5974

6075

6176
def remove_unused_etags(plugin_infos: Ps, etags: ETagsType) -> ETagsType:
6277
etags_updated = {}
6378
plugin_ids = [info.get("ID") for info in plugin_infos]
64-
79+
6580
for id, tag in etags.items():
66-
81+
6782
if id not in plugin_ids:
68-
print(f"Plugin with ID {id} has been removed. The associated ETag will be also removed now.")
83+
print(
84+
f"Plugin with ID {id} has been removed. The associated ETag will be also removed now."
85+
)
6986
continue
70-
87+
7188
etags_updated[id] = tag
72-
89+
7390
return etags_updated
7491

7592

76-
def send_notification(info: P, latest_ver, release, webhook_url: str = None) -> None:
93+
async def send_notification(
94+
info: P, latest_ver, release, webhook_url: str = None
95+
) -> None:
7796
if version_tuple(info[version]) != version_tuple(latest_ver):
7897
tqdm.write(f"Update detected: {info[plugin_name]} {latest_ver}")
7998
try:
80-
update_hook(webhook_url, info, latest_ver, release)
99+
await update_hook(webhook_url, info, latest_ver, release)
81100
except Exception as e:
82-
tqdm.write(e)
101+
tqdm.write(str(e))
83102

84103

85-
if __name__ == "__main__":
104+
async def main():
86105
webhook_url = None
87106
if len(argv) > 1:
88107
webhook_url = argv[1]
89108
plugin_infos = plugin_reader()
90109
etags = etag_reader()
91-
92-
plugin_infos_new = batch_plugin_infos(plugin_infos, etags, webhook_url)
110+
111+
plugin_infos_new = await batch_plugin_infos(
112+
plugin_infos, etags, getenv("GITHUB_TOKEN"), webhook_url
113+
)
93114
plugin_writer(plugin_infos_new)
94-
115+
95116
etags_new = remove_unused_etags(plugin_infos_new, etags)
96117
etags_writer(etags_new)
118+
119+
120+
if __name__ == "__main__":
121+
asyncio.run(main())

0 commit comments

Comments
 (0)