asahi-kiwi-descriptions/builder.py

268 lines
6.3 KiB
Python
Raw Normal View History

#!/usr/bin/python3
import time
import os
import subprocess
import boto3
2023-07-19 23:16:04 +00:00
import io
import json
import click
import sys
import requests
from datetime import date
import shutil
2023-07-14 19:55:24 +00:00
import xml.etree.ElementTree as ET
def fail(message):
click.echo(message, err=True)
sys.exit(1)
2023-07-14 19:55:24 +00:00
tree = ET.parse("config.xml")
for e in tree.getroot().iter("release-version"):
RELEASE = e.text
break
if not RELEASE:
2023-07-14 19:55:24 +00:00
fail("Could not parse release from config.xml")
if os.path.exists("buildver"):
with open("buildver", "r") as f:
BUILDVER = f.read().strip()
else:
BUILDVER = date.today().strftime("%Y%m%d%H%m")
with open("buildver", "w") as f:
f.write(BUILDVER)
# TODO: should be a class using abc
TARGETS = {
"kde": {
"profile": "Workstation-KDE",
"name": f"Fedora Linux {RELEASE.capitalize()} with KDE Plasma ({BUILDVER})",
"os_name": "Fedora Linux with KDE Plasma",
"id": "kde",
},
"gnome": {
"profile": "Workstation-GNOME",
"name": f"Fedora Linux {RELEASE.capitalize()} with GNOME ({BUILDVER})",
"os_name": "Fedora Linux with GNOME",
"id": "gnome",
},
"server": {
"profile": "Server",
"name": f"Fedora Linux {RELEASE.capitalize()} Server ({BUILDVER})",
"os_name": "Fedora Linux Server",
"id": "server",
},
"minimal": {
"profile": "Minimal",
"name": f"Fedora Linux {RELEASE.capitalize()} Minimal ({BUILDVER})",
"os_name": "Fedora Linux Minimal",
"id": "minimal",
},
}
2023-07-19 23:16:04 +00:00
MANIFEST = os.getenv("MANIFEST", "installer_data.json")
S3_BUCKET = os.getenv("S3_BUCKET")
def requireCommands(commands):
missing = []
for cmd in commands:
if shutil.which(cmd) is None:
missing.append(cmd)
if len(missing) > 0:
fail("Required commands not found: {}".format(" ".join(missing)))
def runCommand(cmd, shell=False):
p = subprocess.run(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
shell=shell,
)
if p.returncode != 0:
fail(p.stdout)
return p
def kiwiBuild(profile):
requireCommands(["kiwi-ng"])
# TODO: check current status first
# runCommand(
# [
# "sudo",
# "setenforce",
# "0",
# ]
# )
# TODO: use the API instead of shelling out
runCommand(
[
"sudo",
"kiwi-ng",
"--debug",
"--type=oem",
f"--profile={profile}",
"system",
"build",
"--description",
"./",
"--target-dir",
"./outdir",
]
)
# runCommand(
# [
# "sudo",
# "setenforce",
# "1",
# ]
# )
def packageBuild(target):
# TODO: rewrite in python instead of shelling out
runCommand(["./make-asahi-installer-package.sh"])
base = f"fedora-{RELEASE}-{target['id']}-{BUILDVER}"
os.rename(f"fedora-{RELEASE}-{BUILDVER}.zip", f"{base}.zip")
os.rename(f"fedora-{RELEASE}-{BUILDVER}.logs.zip", f"{base}.logs.zip")
os.rename(f"fedora-{RELEASE}-{BUILDVER}.raw.zst", f"{base}.raw.zst")
os.rename(f"fedora-{RELEASE}-{BUILDVER}.json", f"{base}.json")
2023-07-20 17:00:28 +00:00
with open(f"{base}.json", "r") as f:
data = json.load(f)
2023-07-20 17:00:28 +00:00
data["name"] = target["name"]
data["default_os_name"] = target["os_name"]
data["package"] = f"{base}.zip"
2023-07-20 17:00:28 +00:00
with open(f"{base}.json", "w") as f:
json.dump(data, f)
2023-07-20 17:00:28 +00:00
if os.path.exists("installer_data.json"):
with open("installer_data.json", "r") as f:
data = json.load(f)
data["os_list"][0]["name"] = target["name"]
data["os_list"][0]["default_os_name"] = target["os_name"]
data["os_list"][0]["package"] = f"{base}.zip"
with open("installer_data.json", "w") as f:
json.dump(data, f)
def uploadToS3(source, destination):
if S3_BUCKET is None:
fail("S3_BUCKET is not set")
s3 = boto3.client("s3")
s3.upload_file(source, S3_BUCKET, destination)
def packageUpload(target):
base = f"fedora-{RELEASE}-{target['id']}-{BUILDVER}"
package = f"{base}.zip"
2023-07-20 17:00:28 +00:00
logs_package = f"{base}.logs.zip"
image = f"{base}.raw.zst"
2023-07-20 15:31:18 +00:00
manifest = f"{base}.json"
uploadToS3(package, f"os/{package}")
uploadToS3(logs_package, f"os/{logs_package}")
uploadToS3(image, f"os/{image}")
2023-07-20 15:31:18 +00:00
uploadToS3(manifest, f"os/{manifest}")
def getManifest():
if S3_BUCKET is None:
fail("S3_BUCKET is not set")
2023-07-19 23:16:04 +00:00
s3 = boto3.resource("s3")
obj = s3.Object(S3_BUCKET, MANIFEST)
data = io.BytesIO()
obj.download_fileobj(data)
return json.loads(data.getvalue().decode("utf-8"))
def manifestUpdate():
old = getManifest()
with open("installer_data.json", "r") as f:
new = json.load(f)
old["os_list"].insert(0, new["os_list"][0])
with open("merged_installer_data.json", "w") as f:
json.dump(old, f)
@click.group()
def cli():
pass
@cli.command()
@click.argument("target")
def build(target):
if target not in TARGETS.keys():
fail(f"Unknown target: {target}")
target = TARGETS[target]
kiwiBuild(target["profile"])
@cli.command()
@click.argument("target")
def package(target):
if target not in TARGETS.keys():
fail(f"Unknown target: {target}")
target = TARGETS[target]
packageBuild(target)
@cli.command()
@click.option("--manifest/--no-manifest", default=True)
2023-07-20 17:00:28 +00:00
@click.argument("target")
def upload(manifest, target):
if target not in TARGETS.keys():
fail(f"Unknown target: {target}")
target = TARGETS[target]
packageUpload(target)
if manifest:
manifestUpdate()
uploadToS3("merged_installer_data.json", MANIFEST)
@cli.command()
@click.option("--update/--no-update", default=False)
@click.option("--upload/--no-upload", default=False)
2023-07-19 21:08:43 +00:00
def manifest(update, upload):
if update:
manifestUpdate()
manifest = "merged_installer_data.json"
if upload:
2023-07-19 23:54:18 +00:00
uploadToS3(manifest, MANIFEST)
else:
manifest = getManifest()
click.echo(json.dumps(manifest, indent=2))
@cli.command()
def clean():
runCommand(["sudo", "rm", "-rf", "outdir"])
runCommand(["rm", "-f", "installer_data.json", "merged_installer_data.json"])
if __name__ == "__main__":
cli()