mirror of
https://codeberg.org/hyperreal/vauxite-build
synced 2024-11-25 12:23:42 +01:00
250 lines
6.9 KiB
Plaintext
250 lines
6.9 KiB
Plaintext
|
#!/usr/bin/env python3
|
||
|
|
||
|
import argparse
|
||
|
import datetime as dt
|
||
|
import os
|
||
|
import shlex
|
||
|
import shutil
|
||
|
import subprocess
|
||
|
import sys
|
||
|
from glob import glob
|
||
|
from pathlib import Path
|
||
|
|
||
|
if os.geteuid() != 0:
|
||
|
exit("Please run this script with sudo")
|
||
|
|
||
|
BASE_DIR = Path("/home/jas/vauxite")
|
||
|
OSTREE_FILES_DIR = BASE_DIR.joinpath("src")
|
||
|
CACHE_DIR = BASE_DIR.joinpath(".cache")
|
||
|
BUILD_REPO = BASE_DIR.joinpath(".build-repo")
|
||
|
SOURCE_REPO = BASE_DIR.joinpath(".source-repo")
|
||
|
DEPLOY_REPO = BASE_DIR.joinpath(".deploy-repo")
|
||
|
WK_DIR = BASE_DIR.joinpath(".tmp")
|
||
|
|
||
|
parser = argparse.ArgumentParser()
|
||
|
group = parser.add_mutually_exclusive_group()
|
||
|
group.add_argument(
|
||
|
"--nodeploy",
|
||
|
required=False,
|
||
|
action="store_true",
|
||
|
help="Do not deploy repo to web server root",
|
||
|
)
|
||
|
group.add_argument(
|
||
|
"--onlydeploy",
|
||
|
required=False,
|
||
|
action="store_true",
|
||
|
help="Skip the build steps and only deploy repo to web server root",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"--sourceurl",
|
||
|
required=False,
|
||
|
action="store",
|
||
|
default="https://pagure.io/workstation-ostree-config",
|
||
|
help="URL for source repo",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"--sourcebranch",
|
||
|
required=True,
|
||
|
action="store",
|
||
|
help="Branch of source repo",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"--treefile",
|
||
|
required=False,
|
||
|
action="store",
|
||
|
default="vauxite.yaml",
|
||
|
help="Treefile to use for rpm-ostree",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"--ostreebranch",
|
||
|
required=True,
|
||
|
action="store",
|
||
|
help="Name of ref branch",
|
||
|
)
|
||
|
parser.add_argument(
|
||
|
"--destrepo",
|
||
|
required=False,
|
||
|
action="store",
|
||
|
default="/srv/repo",
|
||
|
help="Destination for rsync-repos",
|
||
|
)
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
|
||
|
def print_log(msg: str):
|
||
|
if sys.stdout.isatty():
|
||
|
log_date = dt.datetime.now().isoformat(" ", "seconds")
|
||
|
print("%s: %s" % (log_date, msg))
|
||
|
else:
|
||
|
print(msg)
|
||
|
|
||
|
|
||
|
def handle_err():
|
||
|
print_log("ERROR:")
|
||
|
print("{}" % sys.exc_info()[0])
|
||
|
print("{}" % sys.exc_info()[1])
|
||
|
print("{}" % sys.exc_info()[2])
|
||
|
exit(1)
|
||
|
|
||
|
|
||
|
def clean_wk_dir():
|
||
|
try:
|
||
|
print_log("Clean working directory")
|
||
|
shutil.rmtree(CACHE_DIR)
|
||
|
shutil.rmtree(SOURCE_REPO)
|
||
|
shutil.rmtree(WK_DIR)
|
||
|
for dir in glob("/tmp/rpmostree*", recursive=True):
|
||
|
shutil.rmtree(dir)
|
||
|
except FileNotFoundError as ferr:
|
||
|
pass
|
||
|
except Exception:
|
||
|
handle_err()
|
||
|
|
||
|
|
||
|
def run_proc(cmd: str, capture_output=False) -> subprocess.CompletedProcess:
|
||
|
try:
|
||
|
if capture_output:
|
||
|
return subprocess.run(shlex.split(cmd), capture_output=True, text=True)
|
||
|
|
||
|
return subprocess.run(shlex.split(cmd), check=True, text=True)
|
||
|
except subprocess.CalledProcessError:
|
||
|
handle_err()
|
||
|
|
||
|
|
||
|
def prepare_build_env():
|
||
|
clean_wk_dir()
|
||
|
|
||
|
print_log("Ensure CACHE_DIR exists")
|
||
|
CACHE_DIR.mkdir(exist_ok=True)
|
||
|
|
||
|
print_log("Ensure WK_DIR exists")
|
||
|
WK_DIR.mkdir(exist_ok=True)
|
||
|
|
||
|
print_log("Remove previous BUILD_REPO if it exists")
|
||
|
shutil.rmtree(BUILD_REPO, ignore_errors=True)
|
||
|
|
||
|
print_log("Initialize ostree repo in bare-user mode")
|
||
|
run_proc(f"ostree --repo={BUILD_REPO} init --mode=bare-user")
|
||
|
|
||
|
if not DEPLOY_REPO.exists():
|
||
|
print_log("Deploy repo not found; initialize new deploy repo in archive mode")
|
||
|
run_proc(f"ostree --repo={BUILD_REPO} init --mode=archive")
|
||
|
else:
|
||
|
print_log("Pull existing deploy repo into local build repo")
|
||
|
run_proc(
|
||
|
f"ostree --repo={BUILD_REPO} pull-local --depth=2 {DEPLOY_REPO} {args.ostreebranch}"
|
||
|
)
|
||
|
|
||
|
if not SOURCE_REPO.exists():
|
||
|
print_log(
|
||
|
f"Clone branch {args.sourcebranch} of {args.sourceurl} into SOURCE_REPO"
|
||
|
)
|
||
|
run_proc(f"git clone -b {args.sourcebranch} {args.sourceurl} {SOURCE_REPO}")
|
||
|
|
||
|
print_log("Copy SOURCE_REPO contents into WK_DIR")
|
||
|
run_proc(f"rsync -aAX {SOURCE_REPO}/ {WK_DIR}")
|
||
|
|
||
|
print_log("Remove upstream xfce-desktop-pkgs.yaml from WK_DIR")
|
||
|
WK_DIR.joinpath("xfce-desktop-pkgs.yaml").unlink(missing_ok=True)
|
||
|
|
||
|
print_log("Copy OSTREE_FILES_DIR contents into WK_DIR")
|
||
|
run_proc(f"rsync -aAX {OSTREE_FILES_DIR}/ {WK_DIR}")
|
||
|
|
||
|
|
||
|
def compose_ostree():
|
||
|
print_log("Compose ostree")
|
||
|
time_fmt = dt.datetime.now(dt.timezone.utc).strftime("%Y-%m-%dT%H%M%S")
|
||
|
run_proc(
|
||
|
subprocess.list2cmdline(
|
||
|
[
|
||
|
"rpm-ostree",
|
||
|
"compose",
|
||
|
"tree",
|
||
|
"--unified-core",
|
||
|
f"--cachedir={CACHE_DIR}",
|
||
|
f"--repo={BUILD_REPO}",
|
||
|
f"--add-metadata-string=Build={time_fmt}",
|
||
|
WK_DIR.joinpath(args.treefile),
|
||
|
]
|
||
|
)
|
||
|
)
|
||
|
|
||
|
|
||
|
def prepare_deploy():
|
||
|
print_log("Prune refs older than 30 days")
|
||
|
run_proc(
|
||
|
f"ostree --repo={BUILD_REPO} prune --refs-only --keep-younger-than='30 days ago'"
|
||
|
)
|
||
|
|
||
|
print_log("Pull new ostree commit into DEPLOY_REPO")
|
||
|
run_proc(
|
||
|
f"ostree --repo={DEPLOY_REPO} pull-local --depth=1 {BUILD_REPO} {args.ostreebranch}"
|
||
|
)
|
||
|
|
||
|
print_log("Remove local build repo")
|
||
|
shutil.rmtree(BUILD_REPO, ignore_errors=True)
|
||
|
|
||
|
print_log("Check filesystem for errors")
|
||
|
run_proc(f"ostree --repo={DEPLOY_REPO} fsck {args.ostreebranch}")
|
||
|
|
||
|
|
||
|
def generate_deltas():
|
||
|
print_log("Check if main ref has parent")
|
||
|
check_parent = run_proc(
|
||
|
f"ostree --repo={DEPLOY_REPO} show {args.ostreebranch}", capture_output=True
|
||
|
)
|
||
|
|
||
|
if not check_parent.stderr:
|
||
|
print_log("Generate static delta from main ref's parent")
|
||
|
run_proc(
|
||
|
f"ostree --repo={DEPLOY_REPO} static-delta generate {args.ostreebranch}"
|
||
|
)
|
||
|
|
||
|
print_log("Check if main ref's parent has parent")
|
||
|
check_gparent = run_proc(
|
||
|
f"ostree --repo={DEPLOY_REPO} show {args.ostreebranch}^^",
|
||
|
capture_output=True,
|
||
|
)
|
||
|
|
||
|
if not check_gparent.stderr:
|
||
|
print_log("Generate static delta from parent of main ref's parent")
|
||
|
run_proc(
|
||
|
f"ostree --repo={DEPLOY_REPO} static-delta generate --from={args.ostreebranch}^^ --to={args.ostreebranch}"
|
||
|
)
|
||
|
else:
|
||
|
print_log("Main ref's parent has no parent. No deltas generated.")
|
||
|
else:
|
||
|
print_log("Main ref has no parent. No deltas generated.")
|
||
|
|
||
|
|
||
|
def update_summary():
|
||
|
print_log("Update summary file of DEPLOY_REPO")
|
||
|
run_proc(f"ostree --repo={DEPLOY_REPO} summary -u")
|
||
|
|
||
|
|
||
|
def deploy_repo():
|
||
|
print_log("Deploying repo to web server root")
|
||
|
if DEPLOY_REPO.exists():
|
||
|
run_proc(f"{BASE_DIR}/rsync-repos --src {DEPLOY_REPO} --dest {args.destrepo}")
|
||
|
else:
|
||
|
print_log("DEPLOY_REPO not found. Not deploying to web server")
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
if args.nodeploy:
|
||
|
prepare_build_env()
|
||
|
compose_ostree()
|
||
|
prepare_deploy()
|
||
|
generate_deltas()
|
||
|
update_summary()
|
||
|
elif args.onlydeploy:
|
||
|
deploy_repo()
|
||
|
else:
|
||
|
prepare_build_env()
|
||
|
compose_ostree()
|
||
|
prepare_deploy()
|
||
|
generate_deltas()
|
||
|
update_summary()
|
||
|
deploy_repo()
|