Commit fcfc8580 authored by Philipp Hörist's avatar Philipp Hörist
Browse files

Add CI deploy script

parent 204e4316
from typing import Any, Iterator
import os
import json
import functools
from shutil import make_archive
from ftplib import FTP_TLS
from pathlib import Path
import requests
from rich.console import Console
PackageT = tuple[dict[str, Any], Path]
ManifestT = dict[str, Any]
PackageIndexT = dict[str, Any]
FTP_URL = 'panoramix.gajim.org'
FTP_USER = os.environ['FTP_USER']
FTP_PASS = os.environ['FTP_PASS']
REPOSITORY_FOLDER = 'plugins/master'
PACKAGE_INDEX_URL = 'https://ftp.gajim.org/plugins/master/package_index.json'
REPO_ROOT = Path(__file__).parent.parent
BUILD_PATH = REPO_ROOT / 'build'
REQUIRED_KEYS = {
'authors',
'description',
'homepage',
'name',
'platforms',
'requirements',
'short_name',
'version'
}
console = Console()
def ftp_connection(func: Any) -> Any:
@functools.wraps(func)
def func_wrapper(*args: Any) -> None:
ftp = FTP_TLS(FTP_URL, FTP_USER, FTP_PASS)
console.print('Successfully connected to', FTP_URL)
func(ftp, *args)
ftp.quit()
console.print('Quit')
return
return func_wrapper
def is_manifest_valid(manifest: ManifestT) -> bool:
manifest_keys = set(manifest.keys())
return REQUIRED_KEYS.issubset(manifest_keys)
def download_package_index() -> ManifestT:
console.print('Download package index')
r = requests.get(PACKAGE_INDEX_URL)
r.raise_for_status()
index = r.json()
return index
def iter_manifests() -> Iterator[PackageT]:
for path in REPO_ROOT.rglob('manifest.json'):
with path.open() as f:
manifest = json.load(f)
yield manifest, path.parent
def find_plugins_to_publish(index: PackageIndexT) -> list[PackageT]:
packages_to_publish: list[PackageT] = []
for manifest, path in iter_manifests():
if not is_manifest_valid(manifest):
exit('Invalid manifest found')
short_name = manifest['short_name']
version = manifest['version']
try:
index['plugins'][short_name][version]
except KeyError:
packages_to_publish.append((manifest, path))
console.print('Found package to publish:', path.stem)
return packages_to_publish
def get_release_zip_name(manifest: ManifestT) -> str:
short_name = manifest['short_name']
version = manifest['version']
return f'{short_name}_{version}'
def get_dir_list(ftp: FTP_TLS) -> set[str]:
return {x[0] for x in ftp.mlsd()}
def upload_file(ftp: FTP_TLS,
filepath: Path) -> None:
name = filepath.name
console.print('Upload file', name)
with open(filepath, 'rb') as f:
ftp.storbinary('STOR ' + name, f)
def create_release_folder(ftp: FTP_TLS,
packages_to_publish: list[PackageT]) -> None:
folders = {manifest['short_name'] for manifest, _ in packages_to_publish}
dir_list = get_dir_list(ftp)
missing_folders = folders - dir_list
for folder in missing_folders:
ftp.mkd(folder)
@ftp_connection
def deploy(ftp: FTP_TLS, packages_to_publish: list[PackageT]) -> None:
ftp.cwd(REPOSITORY_FOLDER)
create_release_folder(ftp, packages_to_publish)
for manifest, path in packages_to_publish:
package_name = manifest['short_name']
zip_name = get_release_zip_name(manifest)
zip_path = BUILD_PATH / f'{zip_name}.zip'
image_path = path / f'{package_name}.png'
make_archive(str(BUILD_PATH / zip_name), 'zip', path)
ftp.cwd(package_name)
upload_file(ftp, zip_path)
upload_file(ftp, image_path)
ftp.cwd('..')
console.print('Deployed', package_name)
if __name__ == '__main__':
index = download_package_index()
packages_to_publish = find_plugins_to_publish(index)
if not packages_to_publish:
console.print('No new packages deployed')
else:
deploy(packages_to_publish)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment