osbuild: support for checkpoints during build
Add a new `--checkpoint` option, which can be provided multiple times, that indicate after which stages a the current stage of the tree should be committed to the object store; the tree id will be the treesum of the tree at that point and a reference is created with the id of the stage at the point. The argument to `--checkpoint` is the id of the stage. If not all the given checkpoints can be found the execution will be aborted.
This commit is contained in:
parent
8d98696f47
commit
6f4d286ff4
2 changed files with 32 additions and 0 deletions
|
|
@ -10,6 +10,25 @@ BOLD = "\033[1m"
|
|||
RED = "\033[31m"
|
||||
|
||||
|
||||
def mark_checkpoints(pipeline, checkpoints):
|
||||
points = set(checkpoints)
|
||||
def mark_stage(stage):
|
||||
for c in points:
|
||||
if stage.id == c:
|
||||
stage.checkpoint = True
|
||||
points.remove(c)
|
||||
return
|
||||
|
||||
def mark_pipeline(pl):
|
||||
for stage in pl.stages:
|
||||
mark_stage(stage)
|
||||
if pl.build:
|
||||
mark_pipeline(pl.build)
|
||||
|
||||
mark_pipeline(pipeline)
|
||||
return points
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Build operating system images")
|
||||
parser.add_argument("pipeline_path", metavar="PIPELINE",
|
||||
|
|
@ -25,6 +44,8 @@ def main():
|
|||
help="json file containing a dictionary of secrets that are passed to sources")
|
||||
parser.add_argument("-l", "--libdir", metavar="DIRECTORY", type=os.path.abspath,
|
||||
help="the directory containing stages, assemblers, and the osbuild library")
|
||||
parser.add_argument("--checkpoint", metavar="CHECKPOINT", action="append", type=str, default=None,
|
||||
help="stage to commit to the object store during build (can be passed multiple times)")
|
||||
parser.add_argument("--json", action="store_true",
|
||||
help="output results in JSON format")
|
||||
args = parser.parse_args()
|
||||
|
|
@ -51,6 +72,14 @@ def main():
|
|||
with open(args.secrets) as f:
|
||||
secrets = json.load(f)
|
||||
|
||||
if args.checkpoint:
|
||||
missed = mark_checkpoints(pipeline, args.checkpoint)
|
||||
if missed:
|
||||
for checkpoint in missed:
|
||||
print(f"Checkpoint {BOLD}{checkpoint}{RESET} not found!")
|
||||
print(f"{RESET}{BOLD}{RED}Failed{RESET}")
|
||||
return 1
|
||||
|
||||
try:
|
||||
r = pipeline.run(
|
||||
args.store,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ class Stage:
|
|||
self.build = build
|
||||
self.base = base
|
||||
self.options = options
|
||||
self.checkpoint = False
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
|
|
@ -271,6 +272,8 @@ class Pipeline:
|
|||
var=store,
|
||||
source_options=source_options,
|
||||
secrets=secrets)
|
||||
if stage.checkpoint:
|
||||
object_store.snapshot(tree, stage.id)
|
||||
results["stages"].append(r.as_dict())
|
||||
except BuildError as err:
|
||||
results["stages"].append(err.as_dict())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue