mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
Replaced hardcoded base_images/app_images lists with dynamic parsing: - Base images scanned from base-images/Dockerfile.* filenames - App images parsed from docker-compose.stack.yml build services Also fixed run() shadowing bug (same issue as nexus_populate). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
114 lines
3.6 KiB
Python
114 lines
3.6 KiB
Python
"""Push locally-built images to local Nexus registry for act CI runner."""
|
|
|
|
import argparse
|
|
import pathlib
|
|
import re
|
|
import subprocess
|
|
import yaml
|
|
|
|
from cli.helpers import (
|
|
PROJECT_ROOT, GREEN, YELLOW, RED, NC,
|
|
docker_image_exists, log_info, run as run_proc,
|
|
)
|
|
|
|
COMPOSE_FILE = pathlib.Path(__file__).parent.parent / "docker-compose.stack.yml"
|
|
BASE_IMAGES_DIR = pathlib.Path(__file__).parent.parent / "base-images"
|
|
|
|
# Dockerfile.apt -> base-apt, Dockerfile.node-deps -> base-node-deps, etc.
|
|
_DOCKERFILE_RE = re.compile(r"^Dockerfile\.(.+)$")
|
|
|
|
|
|
def _load_image_names() -> list[str]:
|
|
"""Return all image short-names: base images from Dockerfiles + apps from compose."""
|
|
names = []
|
|
|
|
for df in sorted(BASE_IMAGES_DIR.glob("Dockerfile.*")):
|
|
m = _DOCKERFILE_RE.match(df.name)
|
|
if m:
|
|
names.append(f"base-{m.group(1)}")
|
|
|
|
with open(COMPOSE_FILE) as f:
|
|
dc = yaml.safe_load(f)
|
|
for svc_name, svc in dc.get("services", {}).items():
|
|
if "build" not in svc:
|
|
continue
|
|
local = svc.get("image", f"deployment-{svc_name}:latest")
|
|
name = local.split("/")[-1].split(":")[0].removeprefix("deployment-")
|
|
names.append(name)
|
|
|
|
return names
|
|
|
|
|
|
def run_cmd(args: argparse.Namespace, config: dict) -> int:
|
|
local_registry = "localhost:5050"
|
|
nexus_user, nexus_pass = "admin", "nexus"
|
|
|
|
# Derive repo slug from git
|
|
result = subprocess.run(
|
|
["git", "-C", str(PROJECT_ROOT), "remote", "get-url", "origin"],
|
|
capture_output=True, text=True,
|
|
)
|
|
slug = "johndoe6345789/metabuilder-small"
|
|
if result.returncode == 0:
|
|
m = re.search(r"github\.com[:/]([^/]+/[^/.]+)", result.stdout.strip())
|
|
if m:
|
|
slug = m.group(1).lower()
|
|
|
|
source_registry = args.src
|
|
|
|
if args.tag:
|
|
tag = args.tag
|
|
else:
|
|
result = subprocess.run(
|
|
["git", "-C", str(PROJECT_ROOT), "rev-parse", "--abbrev-ref", "HEAD"],
|
|
capture_output=True, text=True,
|
|
)
|
|
tag = result.stdout.strip() if result.returncode == 0 else "main"
|
|
|
|
images = _load_image_names()
|
|
|
|
print(f"{YELLOW}Registry:{NC} {local_registry}")
|
|
print(f"{YELLOW}Slug:{NC} {slug}")
|
|
print(f"{YELLOW}Tag:{NC} {tag}")
|
|
print(f"{YELLOW}Images:{NC} {len(images)} (base-images/ + docker-compose.stack.yml)\n")
|
|
|
|
log_info(f"Logging in to {local_registry}...")
|
|
run_proc(["docker", "login", local_registry, "-u", nexus_user, "--password-stdin"],
|
|
input=nexus_pass.encode())
|
|
|
|
pushed = skipped = failed = 0
|
|
for image in images:
|
|
src = f"{source_registry}/{slug}/{image}:{tag}"
|
|
dst = f"{local_registry}/{slug}/{image}:{tag}"
|
|
|
|
if args.pull:
|
|
print(f" {YELLOW}pulling{NC} {src}...")
|
|
if not docker_image_exists(src):
|
|
result = run_proc(["docker", "pull", src])
|
|
if result.returncode != 0:
|
|
print(f" {YELLOW}skip{NC} {image} (not found in {source_registry})")
|
|
skipped += 1
|
|
continue
|
|
|
|
if not docker_image_exists(src) and not docker_image_exists(dst):
|
|
print(f" {YELLOW}skip{NC} {image} (not found locally)")
|
|
skipped += 1
|
|
continue
|
|
|
|
if docker_image_exists(src):
|
|
run_proc(["docker", "tag", src, dst])
|
|
|
|
print(f" {GREEN}push{NC} {dst}")
|
|
result = run_proc(["docker", "push", dst])
|
|
if result.returncode == 0:
|
|
pushed += 1
|
|
else:
|
|
print(f" {RED}FAILED{NC} {image}")
|
|
failed += 1
|
|
|
|
print(f"\n{GREEN}Done.{NC} pushed={pushed} skipped={skipped} failed={failed}")
|
|
return 1 if failed else 0
|
|
|
|
|
|
run = run_cmd
|