diff --git a/stages/org.osbuild.ostree.commit b/stages/org.osbuild.ostree.commit new file mode 100755 index 00000000..84d7a217 --- /dev/null +++ b/stages/org.osbuild.ostree.commit @@ -0,0 +1,118 @@ +#!/usr/bin/python3 +""" +Assemble a file system tree into a ostree commit + +Needs a file system tree that is already conforming to the ostree +system layout[1], specified via the `tree` input and commits it +to a repository. The repository must have been created at `/repo`. + +Additional metadata is stored in `/compose.json` which contains +the commit compose information. This is also returned via the +metadata API to osbuild. + +[1] https://ostree.readthedocs.io/en/stable/manual/adapting-existing/ +""" + + +import json +import os +import subprocess +import sys +import tempfile + +from osbuild import api +from osbuild.util import ostree + + +SCHEMA_2 = """ +"options": { + "additionalProperties": false, + "required": ["ref"], + "properties": { + "ref": { + "description": "OStree ref to create for the commit", + "type": "string", + "default": "" + }, + "os_version": { + "description": "Set the version of the OS as commit metadata", + "type": "string" + }, + "parent": { + "description": "commit id of the parent commit", + "type": "string" + } + } +}, +"inputs": { + "type": "object", + "additionalProperties": false, + "required": ["tree"], + "properties": { + "tree": { + "type": "object", + "additionalProperties": true + } + } +} +""" + + +def main(inputs, output_dir, options, meta): + tree = inputs["tree"]["path"] + + ref = options["ref"] + os_version = options.get("os_version", None) + parent = options.get("parent", None) + + # rpm-ostree compose commit wants to consume the commit + # so for now, we copy the whole tree and let it have its + # way + with tempfile.TemporaryDirectory(dir=output_dir) as root: + subprocess.run(["cp", "--reflink=auto", "-a", + f"{tree}/.", root], + check=True) + + repo = os.path.join(output_dir, "repo") + + treefile = ostree.Treefile() + treefile["ref"] = ref + + argv = ["rpm-ostree", "compose", "commit"] + argv += [f"--repo={repo}"] + + if parent: + argv += [f"--parent={parent}"] + + if os_version: + argv += [ + f"--add-metadata-string=version={os_version}", + ] + + argv += [ + f"--add-metadata-string=rpmostree.inputhash={meta['id']}", + f"--write-composejson-to={output_dir}/compose.json" + ] + + with treefile.as_tmp_file() as path: + argv += [path, root] + + subprocess.run(argv, + stdout=sys.stderr, + check=True) + + with open(os.path.join(output_dir, "compose.json"), "r") as f: + compose = json.load(f) + + api.metadata({"compose": compose}) + + +if __name__ == '__main__': + args = api.arguments() + + r = main(args["inputs"], + args["tree"], + args["options"], + args["meta"]) + + sys.exit(r)