Update update_unstable.py
- Port to Python 3.8 syntax - Use type annotations - Add a matrix notification using matrix-commander
This commit is contained in:
parent
1a35e5637c
commit
86fe82e6cd
1 changed files with 59 additions and 19 deletions
|
@ -3,43 +3,56 @@
|
||||||
# SPDX-License-Identifier: BSD-3-clause
|
# SPDX-License-Identifier: BSD-3-clause
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
from datetime import date
|
||||||
|
from collections import defaultdict
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Union, Dict, Any
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
import git
|
import git
|
||||||
import requests
|
import requests
|
||||||
|
import sarge
|
||||||
|
|
||||||
|
|
||||||
API_URL = "https://invent.kde.org/api/v4/projects/"
|
API_URL = "https://invent.kde.org/api/v4/projects/"
|
||||||
OBS_URL = "https://api.opensuse.org/trigger/runservice"
|
OBS_URL = "https://api.opensuse.org/trigger/runservice"
|
||||||
|
|
||||||
|
MESSAGE_TEMPLATE = f"""
|
||||||
|
### OBS package update complete
|
||||||
|
|
||||||
|
Stats for {date.today().strftime('%Y-%m-%d')}:
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class GitHashCache:
|
class GitHashCache:
|
||||||
|
|
||||||
def __init__(self, cache_file):
|
def __init__(self, cache_file: str) -> None:
|
||||||
self.cache = cache_file
|
self.cache = cache_file
|
||||||
self._data = dict()
|
self._data: Dict[str, Dict[str, str]] = dict()
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key: str) -> Dict[str, str]:
|
||||||
|
|
||||||
if key not in self._data:
|
if key not in self._data:
|
||||||
return ""
|
raise KeyError
|
||||||
|
|
||||||
return self._data[key]
|
return self._data[key]
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key: str, value: Dict[str, str]) -> None:
|
||||||
self._data[key] = value
|
self._data[key] = value
|
||||||
|
|
||||||
def get(self, key, *args, **kwargs):
|
def get(self, key: str,
|
||||||
|
*args: Any, **kwargs: Any) -> Union[None, str, Dict[str, str]]:
|
||||||
return self._data.get(key, *args, **kwargs)
|
return self._data.get(key, *args, **kwargs)
|
||||||
|
|
||||||
def save(self):
|
def save(self) -> None:
|
||||||
logging.debug("Saving pickled data")
|
logging.debug("Saving pickled data")
|
||||||
with open(self.cache, "w") as handle:
|
with open(self.cache, "w") as handle:
|
||||||
json.dump(self._data, handle, indent=4)
|
json.dump(self._data, handle, indent=4)
|
||||||
|
|
||||||
def load(self):
|
def load(self) -> None:
|
||||||
|
|
||||||
if not Path(self.cache).exists():
|
if not Path(self.cache).exists():
|
||||||
logging.debug("File cache not found, not loading")
|
logging.debug("File cache not found, not loading")
|
||||||
|
@ -49,7 +62,7 @@ class GitHashCache:
|
||||||
self._data = json.load(handle)
|
self._data = json.load(handle)
|
||||||
|
|
||||||
|
|
||||||
def project_exists(project):
|
def project_exists(project: str) -> bool:
|
||||||
# We want / to get quoted, so put safe to ""
|
# We want / to get quoted, so put safe to ""
|
||||||
project_name = quote(project, safe="")
|
project_name = quote(project, safe="")
|
||||||
request = requests.get(API_URL + project_name)
|
request = requests.get(API_URL + project_name)
|
||||||
|
@ -60,7 +73,7 @@ def project_exists(project):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def lsremote(url):
|
def lsremote(url: str) -> Dict[str, str]:
|
||||||
|
|
||||||
remote_refs = {}
|
remote_refs = {}
|
||||||
gitcmd = git.cmd.Git()
|
gitcmd = git.cmd.Git()
|
||||||
|
@ -71,12 +84,13 @@ def lsremote(url):
|
||||||
return remote_refs
|
return remote_refs
|
||||||
|
|
||||||
|
|
||||||
def get_remote_hash(url, branch="master"):
|
def get_remote_hash(url: str, branch: str = "master") -> str:
|
||||||
refs = "refs/heads/{}".format(branch)
|
refs = "refs/heads/{}".format(branch)
|
||||||
return lsremote(url)[refs]
|
return lsremote(url)[refs]
|
||||||
|
|
||||||
|
|
||||||
def trigger_update(repository, package_name, token):
|
def trigger_update(repository: str, package_name: str,
|
||||||
|
token: str) -> Union[requests.Response, bool]:
|
||||||
|
|
||||||
header = {"Authorization": f"Token {token}"}
|
header = {"Authorization": f"Token {token}"}
|
||||||
parameters = {"project": repository, "package": package_name}
|
parameters = {"project": repository, "package": package_name}
|
||||||
|
@ -94,9 +108,11 @@ def trigger_update(repository, package_name, token):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def update_package(hash_data, package_name,
|
def update_package(hash_data: GitHashCache, package_name: str,
|
||||||
remote_name, obs_repository,
|
remote_name: str, obs_repository: str,
|
||||||
branch, token):
|
branch: str,
|
||||||
|
token: str,
|
||||||
|
stats: Dict[str, int]) -> None:
|
||||||
|
|
||||||
repo_name = "https://invent.kde.org/{}".format(remote_name)
|
repo_name = "https://invent.kde.org/{}".format(remote_name)
|
||||||
|
|
||||||
|
@ -119,19 +135,26 @@ def update_package(hash_data, package_name,
|
||||||
logging.debug("Hash doesn't match, updating")
|
logging.debug("Hash doesn't match, updating")
|
||||||
if trigger_update(obs_repository, package_name, token):
|
if trigger_update(obs_repository, package_name, token):
|
||||||
hash_data[obs_repository][remote_name] = remote_hash
|
hash_data[obs_repository][remote_name] = remote_hash
|
||||||
|
stats["updated"] += 1
|
||||||
hash_data.save()
|
hash_data.save()
|
||||||
|
else:
|
||||||
|
stats["errors"] += 1
|
||||||
|
|
||||||
|
|
||||||
def update_packages(cache_file, repo_mapping_file, token):
|
def update_packages(cache_file: str,
|
||||||
|
repo_mapping_file: str, token: str) -> None:
|
||||||
|
|
||||||
hash_data = GitHashCache(cache_file)
|
hash_data = GitHashCache(cache_file)
|
||||||
hash_data.load()
|
hash_data.load()
|
||||||
|
|
||||||
|
stats = dict()
|
||||||
|
|
||||||
with open(repo_mapping_file, "r") as mapping:
|
with open(repo_mapping_file, "r") as mapping:
|
||||||
|
|
||||||
repo_data = json.load(mapping)
|
repo_data = json.load(mapping)
|
||||||
|
|
||||||
for obs_repository, branch_data in repo_data.items():
|
for obs_repository, branch_data in repo_data.items():
|
||||||
|
repo_stats: Dict[str, int] = defaultdict(int)
|
||||||
|
|
||||||
logging.info("Updating packages for %s", obs_repository)
|
logging.info("Updating packages for %s", obs_repository)
|
||||||
|
|
||||||
|
@ -144,13 +167,30 @@ def update_packages(cache_file, repo_mapping_file, token):
|
||||||
package_name, obs_name)
|
package_name, obs_name)
|
||||||
logging.debug("Using branch %s", branch)
|
logging.debug("Using branch %s", branch)
|
||||||
update_package(hash_data, obs_name, kde_name, obs_repository,
|
update_package(hash_data, obs_name, kde_name, obs_repository,
|
||||||
branch, token)
|
branch, token, repo_stats)
|
||||||
|
stats[obs_repository] = repo_stats
|
||||||
|
|
||||||
logging.debug("Saving data")
|
logging.debug("Saving data")
|
||||||
hash_data.save()
|
hash_data.save()
|
||||||
|
notify_matrix(stats)
|
||||||
|
|
||||||
|
|
||||||
def commit_changes(cache_file, repo_home):
|
def notify_matrix(stats: Dict[str, Dict[str, int]]) -> None:
|
||||||
|
|
||||||
|
structure = [MESSAGE_TEMPLATE]
|
||||||
|
for key, value in stats.items():
|
||||||
|
row = (f"* {key}: {stats['updated']} updated packages,"
|
||||||
|
f" {stats['errors']} errors")
|
||||||
|
structure.append(row)
|
||||||
|
|
||||||
|
message = "\n".join(structure)
|
||||||
|
|
||||||
|
cmd = ["matrix_commander.py", "--markdown", "-m", message]
|
||||||
|
logging.debug("Sending Matrix notification")
|
||||||
|
sarge.run(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def commit_changes(cache_file: str, repo_home: str) -> None:
|
||||||
|
|
||||||
repo = git.Repo(repo_home)
|
repo = git.Repo(repo_home)
|
||||||
repo.index.add([cache_file])
|
repo.index.add([cache_file])
|
||||||
|
@ -160,7 +200,7 @@ def commit_changes(cache_file, repo_home):
|
||||||
origin.push()
|
origin.push()
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
|
|
Loading…
Add table
Reference in a new issue