mirror of
https://codeberg.org/readeck/readeck.git
synced 2025-12-22 05:07:08 +00:00
222 lines
5.8 KiB
Python
222 lines
5.8 KiB
Python
#!/usr/bin/python3
|
|
|
|
# SPDX-FileCopyrightText: © 2025 Olivier Meunier <olivier@neokraft.net>
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
import json
|
|
import os
|
|
from contextlib import chdir, contextmanager
|
|
from datetime import date
|
|
from subprocess import call, check_call, check_output
|
|
from tempfile import TemporaryDirectory
|
|
from urllib import parse, request
|
|
from urllib.error import HTTPError
|
|
|
|
SITE_CONFIG_REPO = "https://github.com/fivefilters/ftr-site-config"
|
|
LABELS = ["Chore"]
|
|
|
|
|
|
def versiontuple(v):
|
|
return tuple(map(int, (v.split("."))))
|
|
|
|
|
|
@contextmanager
|
|
def branch(base: str, name: str):
|
|
check_call(["git", "checkout", "-B", name])
|
|
yield name
|
|
check_call(["git", "checkout", base])
|
|
|
|
|
|
def commit_changes(files: list[str], message: str):
|
|
check_call(["git", "add"] + files)
|
|
rc = call(["git", "diff-index", "--quiet", "HEAD", "--"] + files)
|
|
if rc == 0:
|
|
return
|
|
|
|
# fmt:off
|
|
check_call(
|
|
[
|
|
"git", "commit",
|
|
"-m", message,
|
|
"--no-signoff", "--no-gpg-sign",
|
|
], env={
|
|
**os.environ,
|
|
"GIT_AUTHOR_NAME": "Readeck Bot",
|
|
"GIT_AUTHOR_EMAIL": "bot@readeck.com",
|
|
"GIT_COMMITTER_NAME": "Readeck Bot",
|
|
"GIT_COMMITTER_EMAIL": "bot@readeck.com",
|
|
},
|
|
)
|
|
# fmt:on
|
|
|
|
|
|
def push_changes(repository_url: str, base: str, branch_name: str):
|
|
rc = call(["git", "diff-index", "--quiet", base])
|
|
if rc == 0:
|
|
return
|
|
|
|
check_call(["git", "push", "--force", repository_url, branch_name])
|
|
|
|
|
|
def get_labels(api_url: str, api_token: str, org: str, *names: str):
|
|
r = request.Request(
|
|
f"{api_url}/orgs/{org}/labels",
|
|
headers={
|
|
"Authorization": f"token {api_token}",
|
|
},
|
|
)
|
|
with request.urlopen(r) as rsp:
|
|
data = json.load(rsp)
|
|
return [x for x in data if x["name"] in names]
|
|
|
|
|
|
def create_pr(
|
|
api_url: str,
|
|
api_token: str,
|
|
repository: str,
|
|
base: str,
|
|
branch_name: str,
|
|
):
|
|
labels = get_labels(api_url, api_token, repository.split("/")[0], *LABELS)
|
|
|
|
r = request.Request(
|
|
method="POST",
|
|
url=f"{api_url}/repos/{repository}/pulls",
|
|
headers={
|
|
"Content-Type": "application/json",
|
|
"Authorization": f"token {api_token}",
|
|
},
|
|
data=json.dumps(
|
|
{
|
|
"base": base,
|
|
"head": branch_name,
|
|
"title": f"Dependencies update [{date.today()}]",
|
|
"labels": [x["id"] for x in labels],
|
|
}
|
|
).encode("utf-8"),
|
|
)
|
|
try:
|
|
request.urlopen(r)
|
|
except HTTPError as e:
|
|
if e.status != 409:
|
|
raise
|
|
|
|
|
|
def update_go_version():
|
|
data = check_output(["go", "mod", "edit", "-json"])
|
|
current = json.loads(data)["Go"]
|
|
|
|
rsp = request.urlopen("https://go.dev/VERSION?m=text")
|
|
latest = rsp.readline().decode().strip().lstrip("go")
|
|
rsp.close()
|
|
|
|
cv = versiontuple(current)
|
|
lv = versiontuple(latest)
|
|
|
|
if lv > cv and lv[1] == cv[1]:
|
|
check_call(["go", "mod", "edit", f"-go={latest}"])
|
|
|
|
|
|
def update_go_dependencies():
|
|
check_call(["go", "get", "-t", "-u", "-v", "./..."])
|
|
check_call(["go", "mod", "tidy"])
|
|
|
|
|
|
def update_js_dependencies():
|
|
with chdir("web"):
|
|
# fmt:off
|
|
check_call(
|
|
[
|
|
"npm", "exec", "-y", "--",
|
|
"npm-check-updates",
|
|
"-t", "minor",
|
|
"--peer", "--upgrade",
|
|
"--install", "always",
|
|
]
|
|
)
|
|
# fmt: on
|
|
check_call(["npx", "-y", "update-browserslist-db@latest"])
|
|
|
|
|
|
def update_site_config_files():
|
|
with TemporaryDirectory() as folder:
|
|
# fmt: off
|
|
check_call(
|
|
[
|
|
"git", "clone", "--depth", "1",
|
|
SITE_CONFIG_REPO, "--single-branch",
|
|
"--branch", "master",
|
|
folder,
|
|
]
|
|
)
|
|
check_call(
|
|
[
|
|
"go", "run", "./tools/ftr",
|
|
folder,
|
|
"pkg/extract/contentscripts/assets/site-config",
|
|
], env={
|
|
**os.environ,
|
|
"GOWORK": "off",
|
|
},
|
|
)
|
|
# fmt: on
|
|
|
|
|
|
def main():
|
|
api_url = os.environ.get("GITHUB_API_URL")
|
|
api_user = os.environ.get("API_USER")
|
|
api_token = os.environ.get("API_TOKEN")
|
|
repository = os.environ.get("GITHUB_REPOSITORY")
|
|
repository_url = (
|
|
check_output(["git", "remote", "get-url", "origin"]).decode().strip()
|
|
)
|
|
|
|
url = parse.urlparse(repository_url)
|
|
if url.scheme == "https":
|
|
url = url._replace(netloc=f"{api_user}:{api_token}@{url.netloc}")
|
|
repository_url = url.geturl()
|
|
else:
|
|
repository_url = None
|
|
|
|
print(f"API_URL: {api_url}")
|
|
print(f"API USER: {api_user}")
|
|
print(f"REPOSITORY: {repository}")
|
|
|
|
base = check_output(["git", "branch", "--show-current"]).decode().strip()
|
|
|
|
with branch(base, "chore/updates") as branch_name:
|
|
update_go_version()
|
|
update_go_dependencies()
|
|
commit_changes(
|
|
["go.mod", "go.sum"],
|
|
"Updated Go dependencies",
|
|
)
|
|
|
|
update_js_dependencies()
|
|
commit_changes(
|
|
["web/package.json", "web/package-lock.json"],
|
|
"Updated JS dependencies",
|
|
)
|
|
|
|
update_site_config_files()
|
|
commit_changes(
|
|
["pkg/extract/contentscripts/assets/site-config"],
|
|
"Updated Site Config files",
|
|
)
|
|
|
|
rc = call(["git", "diff-index", "--quiet", base])
|
|
if rc == 0:
|
|
print("no new updates")
|
|
return
|
|
|
|
if repository_url:
|
|
push_changes(repository_url, base, branch_name)
|
|
|
|
if api_url and api_token and repository:
|
|
create_pr(api_url, api_token, repository, base, branch_name)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|