build: allow specific upstream versions to be ignored (#217)

This commit is contained in:
Markus Küffner
2025-07-05 20:34:40 +02:00
committed by GitHub
parent 706dcb6a80
commit 7121c94889
4 changed files with 73 additions and 48 deletions

View File

@@ -23,7 +23,7 @@ venv/bin/pip install -r scripts/build/requirements.txt
Usage description: Usage description:
```bash ```bash
$ python scripts/build/build.py --help $ python scripts/build/build.py --help
usage: Build [-h] [--backfill BACKFILL] [--registry REGISTRY] [--platform PLATFORM] [--push] [--dry-run] [--force] [--version VERSION] [--upstream UPSTREAM] app usage: Build [-h] [--backfill BACKFILL] [--registry REGISTRY] [--platform PLATFORM] [--push] [--dry-run] [--force] [--version VERSION] [--upstream UPSTREAM] [--suffix SUFFIX] [--config CONFIG] app
Build container images for prind Build container images for prind
@@ -40,4 +40,6 @@ options:
--force Build images even though they exist in the registry [default: False] --force Build images even though they exist in the registry [default: False]
--version VERSION Which upstream Ref to build. Will overwrite automatic Version extraction from upstream --version VERSION Which upstream Ref to build. Will overwrite automatic Version extraction from upstream
--upstream UPSTREAM Overwrite upstream Repo Url. Will skip Url extraction from Dockerfile --upstream UPSTREAM Overwrite upstream Repo Url. Will skip Url extraction from Dockerfile
--suffix SUFFIX Suffix to add after the image tag. Skips the creation of the 'latest' tag
--config CONFIG Path to the build.yaml file
``` ```

View File

@@ -10,6 +10,7 @@ import os
import re import re
import git import git
import sys import sys
import yaml
import getpass import getpass
import logging import logging
import argparse import argparse
@@ -33,6 +34,7 @@ parser.add_argument("--force",action="store_true",default=False,help="Build imag
parser.add_argument("--version",help="Which upstream Ref to build. Will overwrite automatic Version extraction from upstream") parser.add_argument("--version",help="Which upstream Ref to build. Will overwrite automatic Version extraction from upstream")
parser.add_argument("--upstream",help="Overwrite upstream Repo Url. Will skip Url extraction from Dockerfile") parser.add_argument("--upstream",help="Overwrite upstream Repo Url. Will skip Url extraction from Dockerfile")
parser.add_argument("--suffix",help="Suffix to add after the image tag. Skips the creation of the 'latest' tag") parser.add_argument("--suffix",help="Suffix to add after the image tag. Skips the creation of the 'latest' tag")
parser.add_argument("--config",help="Path to the build.yaml file",default="scripts/build/build.yaml")
args = parser.parse_args() args = parser.parse_args()
#--- #---
@@ -45,6 +47,11 @@ ch = logging.StreamHandler()
ch.setFormatter(formatter) ch.setFormatter(formatter)
logger.addHandler(ch) logger.addHandler(ch)
#---
# Read config
with open(args.config,"r") as file:
cfg = yaml.safe_load(file)
#--- #---
# static definitions # static definitions
context = "docker/" + args.app context = "docker/" + args.app
@@ -56,7 +63,8 @@ build = {
"summary": { "summary": {
"success": [], "success": [],
"failure": [], "failure": [],
"skipped": [] "skipped": [],
"ignored": []
}, },
"labels": { "labels": {
"org.prind.version": os.environ.get("GITHUB_SHA",(git.Repo(search_parent_directories=True)).head.object.hexsha), "org.prind.version": os.environ.get("GITHUB_SHA",(git.Repo(search_parent_directories=True)).head.object.hexsha),
@@ -127,56 +135,63 @@ else:
#--- #---
# Build all targets for all versions # Build all targets for all versions
for version in build["versions"].keys(): for version in build["versions"].keys():
for target in build["targets"]:
# Create list of docker tags # Check if specific version is in ignore list
docker_image = "/".join(filter(None, (args.registry, args.app))) if version in cfg["ignore"].get(args.app, []):
tags = [ logger.warning("Version " + version + " will be ignored as configured in " + args.config)
docker_image + ":" + (version if target == "run" else '-'.join([version, target])) + (f"_{args.suffix}" if args.suffix else ""), build["summary"]["ignored"].append(version)
*(docker_image + (":latest" if target == "run" else '-'.join([":latest", target])) for _i in range(1) if build["versions"][version]["latest"] and not args.suffix),
]
try: else:
if args.force: for target in build["targets"]:
logger.warning("Build is forced")
raise # Create list of docker tags
else: docker_image = "/".join(filter(None, (args.registry, args.app)))
# Check if the image already exists tags = [
docker.buildx.imagetools.inspect(tags[0]) docker_image + ":" + (version if target == "run" else '-'.join([version, target])) + (f"_{args.suffix}" if args.suffix else ""),
logger.info("Image " + tags[0] + " exists, nothing to to.") *(docker_image + (":latest" if target == "run" else '-'.join([":latest", target])) for _i in range(1) if build["versions"][version]["latest"] and not args.suffix),
build["summary"]["skipped"].append(tags[0]) ]
except:
if args.dry_run: try:
logger.debug("[dry-run] Would build " + tags[0]) if args.force:
else: logger.warning("Build is forced")
try: raise
# Build if image does not exist else:
logger.info("Building " + tags[0]) # Check if the image already exists
stream = ( docker.buildx.imagetools.inspect(tags[0])
docker.buildx.build( logger.info("Image " + tags[0] + " exists, nothing to to.")
# Build specific build["summary"]["skipped"].append(tags[0])
context_path = context, except:
build_args = {"REPO": build["upstream"], "VERSION": version}, if args.dry_run:
platforms = args.platform, logger.debug("[dry-run] Would build " + tags[0])
target = target, else:
push = args.push, try:
tags = tags, # Build if image does not exist
labels = { logger.info("Building " + tags[0])
**build["labels"], stream = (
"org.prind.image.version": version docker.buildx.build(
}, # Build specific
stream_logs = True context_path = context,
build_args = {"REPO": build["upstream"], "VERSION": version},
platforms = args.platform,
target = target,
push = args.push,
tags = tags,
labels = {
**build["labels"],
"org.prind.image.version": version
},
stream_logs = True
)
) )
)
for line in stream: for line in stream:
logger.info("BUILD: " + line.strip()) logger.info("BUILD: " + line.strip())
logger.info("Successfully built " + tags[0]) logger.info("Successfully built " + tags[0])
build["summary"]["success"].append(tags[0]) build["summary"]["success"].append(tags[0])
except: except:
logger.critical("Failed to build " + tags[0]) logger.critical("Failed to build " + tags[0])
build["summary"]["failure"].append(tags[0]) build["summary"]["failure"].append(tags[0])
logger.info("Build Summary: " + str(build["summary"])) logger.info("Build Summary: " + str(build["summary"]))
if len(build["summary"]["failure"]) > 0: if len(build["summary"]["failure"]) > 0:

7
scripts/build/build.yaml Normal file
View File

@@ -0,0 +1,7 @@
# This is a basic configuration file for build.py
# Ignore specific refs when building images
# This is helpful is upstream tags contain a bug that prevents the automated build system to succeed
ignore:
klipperscreen:
- v0.4.6 # https://github.com/KlipperScreen/KlipperScreen/commit/c520390fe459865eb96361bd04944d61cde27cf9#commitcomment-161345136

View File

@@ -1,2 +1,3 @@
GitPython==3.1.44 GitPython==3.1.44
python-on-whales==0.77.0 python-on-whales==0.77.0
PyYAML==6.0.2