diff --git a/Dockerfile b/Dockerfile index 6bed1af..1b64c0b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ WORKDIR /app COPY . . -RUN crontab autopkg.cron +RUN crontab docker/5autopkg RUN pip install --no-cache-dir -r requirements.txt CMD python main.py; crond -f diff --git a/autopkg.cron b/docker/5autopkg similarity index 100% rename from autopkg.cron rename to docker/5autopkg diff --git a/main.py b/main.py index 8d29186..b56aaf0 100644 --- a/main.py +++ b/main.py @@ -1,17 +1,21 @@ import os +import re import logging from configparser import ConfigParser import requests from logger import setup_log -from package import pkg +from package import Package ## Autopkg Apps apps = { - "bitcoinknots": "https://api.github.com/repos/bitcoinknots/bitcoin/releases/latest", - "electrs": "https://api.github.com/repos/romanz/electrs/releases/latest" + "bitcoinknots": { + "url": "https://api.github.com/repos/bitcoinknots/bitcoin/releases/latest", + "versioningScheme": r"^v(\d+)\.(\d+)\.(\d+)$" + }, + "electrs": {"url": "https://api.github.com/repos/romanz/electrs/releases/latest"} } @@ -24,17 +28,19 @@ class Autopkg: # Environment Setup target = os.getenv("APKG_TARGET") + os.environ["APKG_RUNTIME_DIR"] = os.path.dirname(os.path.abspath(__file__)) # Set runtime directory - if target == "prod": - self.datafile = "/etc/autopkg/data.ini" - elif target == "test" or target == "debug": - logging.warning("Running autopkg in testing mode!") + match target: + case "prod": + self.datafile = "/etc/autopkg/data.ini" + case "test" | "debug": + logging.warning("Running autopkg in testing mode!") - self.datafile = os.path.dirname(os.path.abspath(__file__)) + "/test/data.ini" + self.datafile = os.getenv("APKG_RUNTIME_DIR") + "/test/data.ini" - if os.path.exists(self.datafile): os.remove(self.datafile) - else: - raise ValueError("APKG_TARGET environment variable not setup correctly!") + if os.path.exists(self.datafile): os.remove(self.datafile) + case _: + raise ValueError("APKG_TARGET environment variable not setup correctly!") ## Config File Setup self.data = ConfigParser() @@ -57,24 +63,37 @@ class Autopkg: # Main Application def main(self): # Handle apps (get versions) - for app, url in apps.items(): - ini_version = self.data.getint("Versions", app, fallback=0) # Version previously packaged from data.ini + for app, info in apps.items(): + ini_version = self.data.get("Versions", app, fallback=None) # Version previously packaged from data.ini - response = requests.get(url) # Fetch data from API + response = requests.get(info["url"]) # Fetch data from API # Parse through JSON data if response.status_code == 200: json = response.json() - version = json["id"] # App version from API + tag = json["tag_name"] # App version from API + pre_release = json["prerelease"] # Package new versions if available - if version != ini_version: - logging.info(f"Found new version ({version}) for {app}, packaging..") + if tag != ini_version and not pre_release: + logging.info(f"Found new version ({tag}) for {app}, packaging..") - if pkg(app, version): - ini_version = str(version) + try: + if Package(app, tag).build(): + ini_version = str(tag) - self.write_data() + self.write_data() + except Exception as e: + logging.error(f"Error starting docker container for {app}") + + +def version_is_higher(tag: str, info: dict) -> (str, None): + regular_scheme = r"^v(\d+)\.(\d+)\.(\d+)$" + + try: + version = re.match(info["versioningScheme"], tag) + except: + version = re.match(regular_scheme) if __name__ == "__main__": diff --git a/package.py b/package.py index 1e18a3a..3fa3287 100644 --- a/package.py +++ b/package.py @@ -1,37 +1,32 @@ +import os import logging import docker -from docker import DockerClient from logger import setup_log # Container Management ## Build Image -def build(client: DockerClient, app: str): - with open(f"{app}/Dockerfile") as dockerfile: - image, _ = client.images.build(fileobj=dockerfile, tag=app) - return image +class Package: + def __init__(self, app: str, version: str): + # Logging Setup + setup_log() -## Run Image -def run(client: DockerClient, image, app: str): - container = client.containers.run(image, detach=True, name=f"autopkg-{app}") - return container + # Variable Setup + self.runtime_dir = os.getenv("APKG_RUNTIME_DIR") + self.client = docker.from_env() # Docker.sock connection + self.app = app + self.version = version + + # Main Packaging Function + def build(self): + with open(f"{self.runtime_dir}/{self.app}/Dockerfile") as dockerfile: + self.image, _ = self.client.images.build(fileobj=dockerfile, tag=f"{self.app}-{self.version}") + + # Run Container + self.run() -# Main Packaging Function -def pkg(app, version): - # Logging Setup - setup_log() - - client = docker.from_env() # Docker.sock connection - - try: - image = build(client, app) - - container = run(client, image, app) - - return True - except Exception as e: - logging.error(f"Error starting docker container for {app}") - - return False + def run(self, image): + container = self.client.containers.run(self.image, detach=True, name=f"autopkg-{self.app}") + return container diff --git a/versioning.py b/versioning.py new file mode 100644 index 0000000..435cf50 --- /dev/null +++ b/versioning.py @@ -0,0 +1,3 @@ +import re + +