ftb-docker/build.py
2022-11-21 16:33:29 +01:00

110 lines
4.6 KiB
Python

#!/usr/bin/env python3
from argparse import ArgumentParser
from datetime import datetime
from re import search
from typing import Iterable
import docker
from ftbtypes import *
from jsongetcache import *
import jsongetcache
default_base_url = "https://api.modpacks.ch"
cache_path = Path("cache")
def get_entity(route: str, base_url: str = default_base_url):
slashes = '/\\'
cachefile = cache_path / f"{route.strip(slashes)}.json"
return jsongetcache.load_cached(base_url + route, cachefile)
def get_latest_release(versions: Iterable[ModPackVersion]):
return max((version for version in versions if version["type"].lower() == "release"), key=lambda version: version["updated"])
def get_modpack_route(modpack: ModPackManifest | int):
return f"/public/modpack/{modpack if isinstance(modpack, int) else modpack['id']}"
def get_modpack_manifest(modpack: ModPackManifest | int) -> ModPackManifest:
return get_entity(get_modpack_route(modpack))
def get_version_route(modpack: ModPackManifest | int, version: ModPackVersion | int):
return f"{get_modpack_route(modpack)}/{version if isinstance(version, int) else version['id']}"
def get_version_manifest(modpack: ModPackManifest | int, version: ModPackVersion | int) -> ModPackVersionManifest:
return get_entity(get_version_route(modpack, version))
def version_without_build(version: str):
print(version)
match = search(r"^(\d+(.\d+)*)\+(\d+)?$", version)
if match is None:
raise Exception(f"Invalid version string: {version}")
else:
return match.group(1)
def get_modpack_slug(modpack: ModPackManifest):
return '-'.join(filter(None, modpack["name"].lower().split(' ')))
def get_installer(modpack: ModPackManifest | int, version: ModPackVersion | int, architecture: docker.Platforms):
match architecture:
case "linux/arm64":
return f"{get_version_route(modpack, version)}/server/arm/linux", "83b9ef3f8b0f525da83c10fd8692c12a6a200c5ce79eba9da97ac29a414232fd"
case "linux/amd64":
return f"{get_version_route(modpack, version)}/server/linux", "9c5eed5e160e329bb6c393db549db356b9cc6a9711a5461aba35607b4124485a"
case _:
raise Exception(f"Invalid or unsupported architecture {architecture}!")
def parse_arguments():
parser = ArgumentParser("build.py", description="FTB Docker image build helper.")
parser.add_argument("modpack", type=int, help="Modpack ID")
parser.add_argument("--version", "-v", type=int, help="Specific Modpack Version ID, otherwise uses the latest")
return parser.parse_args()
if __name__ == "__main__":
args = parse_arguments()
modpack = get_modpack_manifest(args.modpack)
slug = get_modpack_slug(modpack)
print("Slug", slug)
if args.version is None:
args.version = get_latest_release(modpack["versions"])["id"]
version = get_version_manifest(modpack, args.version)
print(f"{modpack['name']} version {version['name']}: updated {datetime.fromtimestamp(version['updated'])}")
java_target = next((target for target in version["targets"] if target["type"] == "runtime" and target["name"] == "java"), None)
if java_target is None:
raise Exception(f"{modpack['name']} version {version['name']} has no java target: {' ,'.join(str(x) for x in version['targets'])}")
# java_version = version_without_build(java_target["version"])
java_version = java_target["version"].replace('+', '_')
print(f"Required java version is version {java_version}")
# base_image = f"azul/zulu-openjdk:{java_version}-jre"
base_image = f"eclipse-temurin:{java_version}-jre"
repo = f"hub.cnml.de/{slug}"
semver_version_tags = docker.semver_tags(version["name"])
platforms: list[docker.Platforms] = ["linux/arm64", "linux/amd64"]
for platform in platforms:
installer, checksum = get_installer(modpack, version, platform)
tags = list(f"{ver}-{platform[(platform.rfind('/')+1):]}" for ver in semver_version_tags)
print(tags)
print(installer, checksum)
docker.buildx(repo,
tags,
[platform],
build_args={
"INSTALLER_URL": default_base_url + installer,
"INSTALLER_CHECKSUM": checksum,
"MODPACK_ID": str(modpack["id"]),
"MODPACK_VERSION": str(version["id"]),
"BASE_IMAGE": base_image
},
write_command=True)
for version_tag in semver_version_tags:
tags = list(f"{version_tag}-{platform[(platform.rfind('/')+1):]}" for platform in platforms)
docker.create_manifest(repo, version_tag, tags, write_command=True)