From: Michael Ferrari Date: Sun, 9 Jun 2024 08:23:11 +0000 (+0200) Subject: Add `mkosi.postoutput` scripts X-Git-Tag: v23.1~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2092b70b7b58d2c059d80e6739094e8ff5a6446c;p=thirdparty%2Fmkosi.git Add `mkosi.postoutput` scripts --- diff --git a/mkosi/__init__.py b/mkosi/__init__.py index b607e6adb..0405f56c3 100644 --- a/mkosi/__init__.py +++ b/mkosi/__init__.py @@ -830,6 +830,47 @@ def run_finalize_scripts(context: Context) -> None: ) +def run_postoutput_scripts(context: Context) -> None: + if not context.config.postoutput_scripts: + return + + env = dict( + DISTRIBUTION=str(context.config.distribution), + RELEASE=context.config.release, + ARCHITECTURE=str(context.config.architecture), + SRCDIR="/work/src", + OUTPUTDIR="/work/out", + MKOSI_UID=str(INVOKING_USER.uid), + MKOSI_GID=str(INVOKING_USER.gid), + MKOSI_CONFIG="/work/config.json", + ) + + if context.config.profile: + env["PROFILE"] = context.config.profile + + with ( + finalize_source_mounts(context.config, ephemeral=context.config.build_sources_ephemeral) as sources, + finalize_config_json(context.config) as json, + ): + for script in context.config.postoutput_scripts: + with complete_step(f"Running post-output script {script}…"): + run( + ["/work/postoutput"], + env=env | context.config.environment, + sandbox=context.config.sandbox( + binary=None, + mounts=[ + *sources, + Mount(script, "/work/postoutput", ro=True), + Mount(json, "/work/config.json", ro=True), + Mount(context.staging, "/work/out"), + ], + options=["--dir", "/work/src", "--chdir", "/work/src", "--dir", "/work/out"] + ), + stdin=sys.stdin, + ) + + def certificate_common_name(context: Context, certificate: Path) -> str: output = run( [ @@ -2744,6 +2785,7 @@ def check_inputs(config: Config) -> None: config.build_scripts, config.postinst_scripts, config.finalize_scripts, + config.postoutput_scripts, ): if not os.access(script, os.X_OK): die(f"{script} is not executable") @@ -3853,6 +3895,7 @@ def build_image(context: Context) -> None: output_base.unlink(missing_ok=True) output_base.symlink_to(context.config.output_with_compression) + run_postoutput_scripts(context) finalize_staging(context) print_output_size(context.config.output_dir_or_cwd() / context.config.output_with_compression) diff --git a/mkosi/config.py b/mkosi/config.py index a6a9eddee..859ea68c4 100644 --- a/mkosi/config.py +++ b/mkosi/config.py @@ -1417,6 +1417,7 @@ class Config: build_scripts: list[Path] postinst_scripts: list[Path] finalize_scripts: list[Path] + postoutput_scripts: list[Path] clean_scripts: list[Path] build_sources: list[ConfigTree] build_sources_ephemeral: bool @@ -2290,6 +2291,17 @@ SETTINGS = ( help="Postinstall script to run outside image", compat_names=("FinalizeScript",), ), + ConfigSetting( + dest="postoutput_scripts", + long="--postoutput-script", + metavar="PATH", + name="PostOutputScripts", + section="Content", + parse=config_make_list_parser(delimiter=",", parse=make_path_parser()), + paths=("mkosi.postoutput",), + path_default=False, + help="Output postprocessing script to run outside image", + ), ConfigSetting( dest="build_sources", metavar="PATH", @@ -3360,6 +3372,7 @@ def parse_config(argv: Sequence[str] = (), *, resources: Path = Path("/")) -> tu *config.build_scripts, *config.postinst_scripts, *config.finalize_scripts, + *config.postoutput_scripts, ) with chdir(path if path.is_dir() else Path.cwd()): @@ -3985,6 +3998,7 @@ def summary(config: Config) -> str: Build Scripts: {line_join_list(config.build_scripts)} Postinstall Scripts: {line_join_list(config.postinst_scripts)} Finalize Scripts: {line_join_list(config.finalize_scripts)} + Postoutput Scripts: {line_join_list(config.postoutput_scripts)} Build Sources: {line_join_list(config.build_sources)} Build Sources Ephemeral: {yes_no(config.build_sources_ephemeral)} Script Environment: {line_join_list(env)} diff --git a/mkosi/resources/mkosi.md b/mkosi/resources/mkosi.md index ee101451c..7a12aa544 100644 --- a/mkosi/resources/mkosi.md +++ b/mkosi/resources/mkosi.md @@ -878,6 +878,11 @@ boolean argument: either `1`, `yes`, or `true` to enable, or `0`, `no`, the finalize scripts for this image. See the **Scripts** section for more information. +`PostOutputScripts=`, `--postoutput-script` +: Takes a comma-separated list of paths to executables that are used as + the post output scripts for this image. See the **Scripts** section for more + information. + `BuildSources=`, `--build-sources=` : Takes a comma separated list of colon separated path pairs. The first path of each pair refers to a directory to mount from the host. The @@ -1951,6 +1956,7 @@ Then, for each image, we execute the following steps: 1. Run finalize scripts (`mkosi.finalize`) 1. Generate unified kernel image if configured to do so 1. Generate final output format +1. Run post-output scripts (`mkosi.postoutput`) # Scripts @@ -2017,6 +2023,11 @@ current working directory. The following scripts are supported: * If **`mkosi.finalize`** (`FinalizeScripts=`) exists, it is executed as the last step of preparing an image. +* If **`mkosi.postoutput`** (`PostOutputScripts=`) exists, it is executed right + after all the output files have been generated, before they are finally + moved into the output directory. This can be used to generate additional or + alternative outputs, e.g. `SHA256FILES` or SBOM manifests. + * If **`mkosi.clean`** (`CleanScripts=`) exists, it is executed right after the outputs of a previous build have been cleaned up. A clean script can clean up any outputs that mkosi does not know about (e.g. @@ -2134,33 +2145,33 @@ Scripts executed by mkosi receive the following environment variables: Consult this table for which script receives which environment variables: -| Variable | `configure` | `sync` | `prepare` | `build` | `postinst` | `finalize` | `clean` | -|---------------------|:-----------:|:------:|:---------:|:-------:|:----------:|:----------:|:-------:| -| `ARCHITECTURE` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `QEMU_ARCHITECTURE` | ✓ | | | | | | | -| `DISTRIBUTION` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `RELEASE` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `PROFILE` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `CACHED` | | ✓ | | | | | | -| `CHROOT_SCRIPT` | | | ✓ | ✓ | ✓ | ✓ | | -| `SRCDIR` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `CHROOT_SRCDIR` | | | ✓ | ✓ | ✓ | ✓ | | -| `BUILDDIR` | | | | ✓ | | | | -| `CHROOT_BUILDDIR` | | | | ✓ | | | | -| `DESTDIR` | | | | ✓ | | | | -| `CHROOT_DESTDIR` | | | | ✓ | | | | -| `OUTPUTDIR` | | | | ✓ | ✓ | ✓ | ✓ | -| `CHROOT_OUTPUTDIR` | | | | ✓ | ✓ | ✓ | | -| `BUILDROOT` | | | ✓ | ✓ | ✓ | ✓ | | -| `PACKAGEDIR` | | | ✓ | ✓ | ✓ | ✓ | | -| `ARTIFACTDIR` | | | ✓ | ✓ | ✓ | ✓ | | -| `WITH_DOCS` | | | ✓ | ✓ | | | | -| `WITH_TESTS` | | | ✓ | ✓ | | | | -| `WITH_NETWORK` | | | ✓ | ✓ | ✓ | ✓ | | -| `SOURCE_DATE_EPOCH` | | | ✓ | ✓ | ✓ | ✓ | ✓ | -| `MKOSI_UID` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `MKOSI_GID` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| `MKOSI_CONFIG` | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Variable | `configure` | `sync` | `prepare` | `build` | `postinst` | `finalize` | `postoutput` | `clean` | +|---------------------|:-----------:|:------:|:---------:|:-------:|:----------:|:----------:|:------------:|:-------:| +| `ARCHITECTURE` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| `QEMU_ARCHITECTURE` | ✓ | | | | | | | | +| `DISTRIBUTION` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| `RELEASE` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| `PROFILE` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | | ✓ | +| `CACHED` | | ✓ | | | | | | | +| `CHROOT_SCRIPT` | | | ✓ | ✓ | ✓ | ✓ | | | +| `SRCDIR` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| `CHROOT_SRCDIR` | | | ✓ | ✓ | ✓ | ✓ | | | +| `BUILDDIR` | | | | ✓ | | | | | +| `CHROOT_BUILDDIR` | | | | ✓ | | | | | +| `DESTDIR` | | | | ✓ | | | | | +| `CHROOT_DESTDIR` | | | | ✓ | | | | | +| `OUTPUTDIR` | | | | ✓ | ✓ | ✓ | ✓ | ✓ | +| `CHROOT_OUTPUTDIR` | | | | ✓ | ✓ | ✓ | | | +| `BUILDROOT` | | | ✓ | ✓ | ✓ | ✓ | | | +| `PACKAGEDIR` | | | ✓ | ✓ | ✓ | ✓ | | | +| `ARTIFACTDIR` | | | ✓ | ✓ | ✓ | ✓ | | | +| `WITH_DOCS` | | | ✓ | ✓ | | | | | +| `WITH_TESTS` | | | ✓ | ✓ | | | | | +| `WITH_NETWORK` | | | ✓ | ✓ | ✓ | ✓ | | | +| `SOURCE_DATE_EPOCH` | | | ✓ | ✓ | ✓ | ✓ | | ✓ | +| `MKOSI_UID` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| `MKOSI_GID` | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| `MKOSI_CONFIG` | | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | Additionally, when a script is executed, a few scripts are made available via `$PATH` to simplify common usecases. diff --git a/tests/test_json.py b/tests/test_json.py index 051a21ca7..fd44bd3d2 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -216,6 +216,9 @@ def test_config() -> None: "PostInstallationScripts": [ "/bar/qux" ], + "PostOutputScripts": [ + "/foo/src" + ], "PrepareScripts": [ "/run/foo" ], @@ -431,6 +434,7 @@ def test_config() -> None: packages=[], passphrase=None, postinst_scripts=[Path("/bar/qux")], + postoutput_scripts=[Path("/foo/src")], prepare_scripts=[Path("/run/foo")], profile="profile", proxy_client_certificate=Path("/my/client/cert"),