From d2d6d1a854e440af56bda9d53bba0ec6e3089a91 Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Tue, 12 Sep 2023 20:59:49 -0600 Subject: [PATCH] build_ostree_image Add ability to build an ostree image with `-e build_ostree_image -- $image_name` --- README.md | 27 + setup.py | 2 +- src/tox_lsr/config_files/tox-default.ini | 12 + src/tox_lsr/osbuild-manifests/Makefile | 234 ++++++ .../osbuild-manifests/distro/cs8.ipp.yml | 28 + .../osbuild-manifests/distro/cs9.ipp.yml | 20 + .../osbuild-manifests/distro/f37.ipp.yml | 19 + .../osbuild-manifests/distro/f38.ipp.yml | 49 ++ .../osbuild-manifests/files/qm.container | 0 .../osbuild-manifests/images/lsr.mpp.yml | 73 ++ .../include/arch-x86_64.ipp.yml | 23 + .../osbuild-manifests/include/build.ipp.yml | 101 +++ .../include/computed-vars.ipp.yml | 237 ++++++ .../include/defaults.ipp.yml | 455 +++++++++++ .../osbuild-manifests/include/empty.ipp.yml | 1 + .../include/image-ostree.ipp.yml | 362 +++++++++ .../include/image-regular.ipp.yml | 163 ++++ .../osbuild-manifests/include/image.ipp.yml | 737 ++++++++++++++++++ .../include/target-qemu.ipp.yml | 5 + .../osbuild-manifests/tools/runosbuild | 108 +++ .../test_scripts/build_ostree_image.sh | 51 ++ tests/fixtures/test_tox_merge_ini/result.ini | 9 + 22 files changed, 2715 insertions(+), 1 deletion(-) create mode 100644 src/tox_lsr/osbuild-manifests/Makefile create mode 100644 src/tox_lsr/osbuild-manifests/distro/cs8.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/distro/cs9.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/distro/f37.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/distro/f38.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/files/qm.container create mode 100644 src/tox_lsr/osbuild-manifests/images/lsr.mpp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/arch-x86_64.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/build.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/computed-vars.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/defaults.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/empty.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/image-ostree.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/image-regular.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/image.ipp.yml create mode 100644 src/tox_lsr/osbuild-manifests/include/target-qemu.ipp.yml create mode 100755 src/tox_lsr/osbuild-manifests/tools/runosbuild create mode 100644 src/tox_lsr/test_scripts/build_ostree_image.sh diff --git a/README.md b/README.md index 0ecc292..9f759fe 100644 --- a/README.md +++ b/README.md @@ -717,6 +717,33 @@ Older versions of `runqemu.py` would examine the `--image-name` or `--image-file` value to determine if the image is an EL6 image, but this is now deprecated. You must specify `--ssh-el6` if you need it. +### Building ostree images + +Requirements: You will need to install the following packages to build and run: +osbuild-ostree osbuild-tools edk2-ovmf + +tox-lsr can build images for [ostree](https://coreos.github.io/rpm-ostree/). The +`/usr` file system is read-only, which means the RPM packages and any other +files in `/usr` must be provided when the image is built. This means that the +system roles cannot actually manage (install, remove) packages on the system, +they can only verify that the required packages are available. You can use +`-e build_ostree_image -- $image_name` to build an ostree image for testing. +If you want to build for an image that is not supported by tox-lsr, download the +appropriate `$image_name.ipp.yml` into your `~/.config` directory. The image +will be available as `~/.cache/linux-system-roles/$image_name-ostree.qcow2` You +can test with the image like this: + +```bash +TEST_USE_OVMF=true tox -e qemu-ansible-core-2.15 -- \ + --image-file ~/.cache/linux-system-roles/fedora-38-ostree.qcow2 \ + --log-level debug tests/tests_default.yml +``` + +#### .ostree directory + +`build_ostree_image` uses the role `.ostree` directory to determine which +packages to build into the image. + ### Container testing Integration tests can be run using containers. `tox` will start one or diff --git a/setup.py b/setup.py index d675f74..c393978 100755 --- a/setup.py +++ b/setup.py @@ -38,7 +38,7 @@ "src/tox_lsr/test_scripts/lsr_ci_preinstall", "src/tox_lsr/test_scripts/lsr_ci_runtox", ], - package_data={"": ["config_files/*", "test_scripts/*"]}, + package_data={"": ["config_files/*", "test_scripts/*", "osbuild-manifests/**"]}, entry_points={ "tox": ["lsr = tox_lsr.hooks"], }, diff --git a/src/tox_lsr/config_files/tox-default.ini b/src/tox_lsr/config_files/tox-default.ini index 6df2c2e..2ec9db2 100644 --- a/src/tox_lsr/config_files/tox-default.ini +++ b/src/tox_lsr/config_files/tox-default.ini @@ -493,3 +493,15 @@ commands = bash {lsr_scriptdir}/setup_module_utils.sh --output README.html README.md \ {env:RUN_CONVERT_README_EXTRA_ARGS:} {posargs} {[lsr_config]commands_post} + +[testenv:build_ostree_image] +changedir = {toxinidir} +allowlist_externals = + bash + cat + rm + make + sudo +setenv = + {[testenv]setenv} +commands = bash {lsr_scriptdir}/build_ostree_image.sh {posargs} diff --git a/src/tox_lsr/osbuild-manifests/Makefile b/src/tox_lsr/osbuild-manifests/Makefile new file mode 100644 index 0000000..90f0d17 --- /dev/null +++ b/src/tox_lsr/osbuild-manifests/Makefile @@ -0,0 +1,234 @@ +NULL= +EMPTY := +SPACE := $(EMPTY) $(EMPTY) +COMMA := , +ESCAPEDSPACE := \$(SPACE) +ESCAPEDSPACE_REPLACEMENT := @@SPACE@@ + +# This is useful to handle space in forech rules +handle-escaped-space = $(subst $(ESCAPEDSPACE),$(ESCAPEDSPACE_REPLACEMENT),$1) +apply-escaped-space = $(subst $(ESCAPEDSPACE_REPLACEMENT),$(SPACE),$1) + +HOST_ARCH:=$(shell arch) + +ARCHES := x86_64 aarch64 + + +export VM=0 + +OSBUILD_MPP=osbuild-mpp + +DEFINES= +DEFINES_ARGS:=$(foreach def,$(call handle-escaped-space,$(DEFINES)),-D '$(call apply-escaped-space,$(def))') +MPP_ARGS= +export OSBUILD_ARGS= + +BUILDDIR=_build +export STOREDIR=$(BUILDDIR)/osbuild_store +export OUTPUTDIR=$(BUILDDIR)/image_output + +IMAGEDIR= +DESTDIR=. +EXTRA_DISTRO= + +DISTROS := $(basename $(basename $(notdir f,$(wildcard distro/*.ipp.yml)))) $(if $(EXTRA_DISTRO),$(basename $(basename $(notdir $(EXTRA_DISTRO))))) +MANIFESTS := $(wildcard images/*.mpp.yml) $(foreach DIR,$(IMAGEDIR),$(wildcard $(DIR)/*)) + +EXTRA_MPP_ARGS= # For internal use +ifdef OSTREE_REPO +EXTRA_MPP_ARGS +=-D ostree_parent_refs='$(shell tools/ot-refs $(OSTREE_REPO))' +endif + +export CHECKPOINTS=build +IMAGETYPES := regular ostree +FORMATS := img qcow2 oci.tar repo rootfs ext4 tar aboot +aarch64_TARGETS := ridesx4 rpi4 qdrive3 abootqemu +COMMON_TARGETS := qemu aws +HOST_TARGETS := $(COMMON_TARGETS) $($(HOST_ARCH)_TARGETS) +ALL_TARGETS := $(COMMON_TARGETS) $(foreach a,$(ARCHES), $($(a)_TARGETS)) + +manifest-get-name = $(basename $(basename $(notdir $1))) +manifest-get-dir = $(notdir $(patsubst %/,%,$(dir $1))) +image-name-noarch = $1-$3-$(call manifest-get-name,$2)-$4 +image-name = $(call image-name-noarch,$1,$2,$3,$4).$5 + +# variable name for image type +regular_IMAGETYPE := regular +ostree_IMAGETYPE := ostree + +help: + @echo + @echo This makefile is a wrapper around osbuild-mpp and osbuild to easily build images + @echo + @echo To build a raw image, run \"make image.img\", or to build a qcow2 image, run \"make image.qcow2\". + @echo This will build any image from a file called \"image.mpp.yml\" in the \"images\" subdirectory. You can + @echo pass IMAGEDIR=/some/other/path to make also to pick up manifests from an external directory. + @echo + @echo For example, to build a minimal qcow2 image with ostree support targeting qemu, run: + @echo ' make cs9-qemu-minimal-ostree.$(HOST_ARCH).qcow2' + @echo + @echo Other extensions are also supported: + @echo \ \* .repo: Generate a repo with an ostree commit \(only works for ostree targets\) + @echo \ \* .rootfs: Generate a directory with the rootfs content + @echo \ \* .tar: Generate a tar file with the rootfs content + @echo \ \* .ext4: Generate an ext4 filesystem with the rootfs content \(size from \"image_size\"\) + @echo \ \* .oci.tar: Generate an oci container image with the rootfs content + @echo \ \* .aboot: Generate an ext4 root filesystem and an android boot image \(for aboot targets\) + @echo + @echo You can pass variable declarations to osbuild-mpp with the DEFINES make variable. + @echo Multiple defines are separated by space, if you need a space inside a value escape it using \"\\ \". + @echo For example, to add extra rpms to a minimal regular image, use: + @echo " make cs9-qemu-minimal-regular.$(HOST_ARCH).qcow2 DEFINES='extra_rpms=[\"gdb\",\"strace\"]'" + @echo + @echo To easily run the image with qemu, you can use the included runvm tool, like: + @echo \ \ ./runvm cs9-qemu-minimal-regular.$(HOST_ARCH).qcow2 + @echo + @echo There are some additional targets: + @echo \ \ manifests: generates resolved json manifests for all images without building them. + @echo \ \ clean_caches: Removes intermediate image build artifacts \(that improve rebuild speed\) + @echo \ \ clean_downloads: Removes files downloaded during image builds + @echo \ \ clean: Run clean_caches and clean_downloads + @echo \ \ osbuildvm-images: Build a image that can be used to build images inside a VM + @echo + @echo There are also some common conversion rules: + @echo \ \ foo.aboot.simg will build aboot.img / rootfs.img and convert rootfs.img using img2simg + @echo \ \ foo.ext4.simg will build foo.ext4 and then convert it with img2simg + @echo \ \ foo.simg will build foo.img and then convert it with img2simg + @echo \ \ foo.tar.gz will build $foo.tar and then gzip it + @echo + @echo "When building a custom variant of an image (say with an extra package) you can use a" + @echo custom @suffix to change the name of the produced file. For example: + @echo " make cs9-qemu-minimal-ostree@gdb.$(HOST_ARCH).qcow2 DEFINES='extra_rpms=[\"gdb\"]'" + @echo + @echo If you pass VM=1, then the images used from \"make osbuildvm-images\" will be used to do the + @echo actual building. This means that you don\'t need sudo rights to run osbuild, and it means + @echo architectures other than the current ones can be built. + @echo + @echo Available image targets can be listed with \"make list-targets\" + @echo + +list-targets: + @echo Available image targets \(for $(HOST_ARCH)\) are: + @echo + @$(foreach d, $(DISTROS), $(foreach m, $(MANIFESTS), $(foreach t, $(HOST_TARGETS), $(foreach i,$(IMAGETYPES), echo -e " " $(call image-name,$d,$m,$t,$i,$(HOST_ARCH)).[$(subst $(SPACE),$(COMMA),$(FORMATS))];)))) + @echo + +# We pre-create all the toplevel dirs, so that they are owned by the user, not root (when created under sudo) +.PHONY: $(BUILDDIR) +$(BUILDDIR): + @mkdir -p $(BUILDDIR) + @mkdir -p $(STOREDIR)/{objects,refs,sources/org.osbuild.files,tmp} + @mkdir -p $(OUTPUTDIR) + +# Template rule for producing osbuild json manifest from mpp yaml and image type +# $1 == distro name +# $2 == yaml manifest path +# $3 == Target name +# $4 == Image type +# $5 == Arch +define json-rule +$(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json: $2 $(BUILDDIR) + $(OSBUILD_MPP) -D $(if $(EXTRA_DISTRO),distro_dir="\"$(dir $(EXTRA_DISTRO))\"",distro_dir="\"distro\"") -I . -D image_type="\"$($4_IMAGETYPE)\"" -D arch=\"$5\" -D distro_name="\"$1\"" -D target="\"$3\"" $(DEFINES_ARGS) $(EXTRA_MPP_ARGS) $(MPP_ARGS) $$< $$@ +.PHONY: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json +endef + +$(foreach d, $(DISTROS), \ + $(foreach m, $(MANIFESTS), \ + $(foreach a,$(ARCHES), \ + $(foreach t,$(COMMON_TARGETS) $($(a)_TARGETS), \ + $(foreach i,$(IMAGETYPES), \ + $(eval $(call json-rule,$d,$m,$t,$i,$a))))))) + +# Template rule for producing image from json manifest +# $1 == distro name +# $2 == Manifest path +# $3 == Target +# $4 == Image type +# $5 == Arch +# $6 == Export format (extension) +define image-rule +$(call image-name,$1,$2,$3,$4,$5).$6: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json + @tools/runosbuild $(DESTDIR)/"$$@" "$$<" "$3" "$4" "$5" "$6" + +$(call image-name-noarch,$1,$2,$3,$4)@%.$5.$6: $(BUILDDIR)/$(call image-name,$1,$2,$3,$4,$5).json + @tools/runosbuild $(DESTDIR)/"$$@" "$$<" "$3" "$4" "$5" "$6" +endef + +$(foreach d, $(DISTROS), \ + $(foreach m, $(MANIFESTS), \ + $(foreach a,$(ARCHES), \ + $(foreach t, $(COMMON_TARGETS) $($(a)_TARGETS), \ + $(foreach f,$(FORMATS), \ + $(foreach i,$(IMAGETYPES), \ + $(eval $(call image-rule,$d,$m,$t,$i,$a,$f)))))))) + +# Rule to pre-generate all manifests +manifests: $(foreach d, $(DISTROS),$(foreach m, $(MANIFESTS), $(foreach a,$(ARCHES), $(foreach t, $(COMMON_TARGETS) $($(a)_TARGETS), $(foreach i,$(IMAGETYPES), $(BUILDDIR)/$(call image-name,$d,$m,$t,$i,$a).json))))) + +define packages-rule +.PHONY: packages-$(call manifest-get-name,$1).json +packages-$(call manifest-get-name,$1).json: $1 + osbuild-mpp $$< -D arch=\"x86_64\" - | jq -f tools/extract-rpms.jq > $$@.x86_64 + osbuild-mpp $$< -D arch=\"aarch64\" - | jq -f tools/extract-rpms.jq > $$@.aarch64 + echo 1 | jq --indent 4 -f tools/create-packagelist.jq --slurpfile x86_64 $$@.x86_64 --slurpfile aarch64 $$@.aarch64 > $$@ +endef + +$(foreach m, $(MANIFESTS), $(eval $(call packages-rule,$m))) + +.PHONY: clean_downloads +clean_downloads: + sudo rm -rf _build/osbuild_store/sources/org.osbuild.files/* + +.PHONY: clean_caches +clean_caches: + sudo rm -rf $(STOREDIR)/refs/* + sudo rm -rf $(STOREDIR)/refs_tars/* + sudo rm -rf $(STOREDIR)/objects/* + sudo rm -rf $(STOREDIR)/tmp/* + sudo rm -rf $(STOREDIR)/image_output/* + +.PHONY: clean +clean: clean_downloads clean_caches + +ifeq ($(VM), 1) +VM_SUDO= +VM_OSBUILD="osbuildvm/osbuildvm --arch=$(HOST_ARCH)" +else +VM_SUDO=sudo +VM_OSBUILD=sudo osbuild +endif + +.PHONY: osbuildvm-images +osbuildvm-images: $(BUILDDIR) + osbuild-mpp osbuildvm/osbuildvm.mpp.yml _build/osbuildvm-$(HOST_ARCH).json + $(VM_OSBUILD) --store $(STOREDIR) --output-directory $(OUTPUTDIR) --export osbuildvm _build/osbuildvm-$(HOST_ARCH).json + cp $(OUTPUTDIR)/osbuildvm/disk.qcow2 _build/osbuildvm-$(HOST_ARCH).img + cp $(OUTPUTDIR)/osbuildvm/initramfs _build/osbuildvm-$(HOST_ARCH).initramfs + cp $(OUTPUTDIR)/osbuildvm/vmlinuz _build/osbuildvm-$(HOST_ARCH).vmlinuz + $(VM_SUDO) rm -rf $(OUTPUTDIR)/osbuildvm + +%.aboot.simg : %.aboot + img2simg $ export pipeline name +declare -A EXPORT_BY_EXT +EXPORT_BY_EXT[img]=image +EXPORT_BY_EXT[oci.tar]=container +EXPORT_BY_EXT[qcow2]=qcow2 +EXPORT_BY_EXT[repo]=ostree-commit +EXPORT_BY_EXT[rootfs]=rootfs +EXPORT_BY_EXT[ext4]=ext4 +EXPORT_BY_EXT[tar]=tar +EXPORT_BY_EXT[aboot]=aboot + +# Map extension to name of exported file by pipeline +declare -A EXPORT_FILE_BY_EXT +EXPORT_FILE_BY_EXT[img]=disk.img +EXPORT_FILE_BY_EXT[qcow2]=disk.qcow2 +EXPORT_FILE_BY_EXT[oci.tar]=container.tar +EXPORT_FILE_BY_EXT[repo]=repo +EXPORT_FILE_BY_EXT[rootfs]= +EXPORT_FILE_BY_EXT[ext4]=rootfs.ext4 +EXPORT_FILE_BY_EXT[tar]=rootfs.tar +EXPORT_FILE_BY_EXT[aboot]=images + +EXPORT=${EXPORT_BY_EXT[${EXTENSION}]} +EXPORT_FILE=${EXPORT_FILE_BY_EXT[${EXTENSION}]} + +HOST_ARCH=$(arch) +CURRENT_UIDGID="$(id -u):$(id -g)" + +if [ $ARCH == $HOST_ARCH -a $VM == 0 ]; then + SUDO="sudo" + OSBUILD="sudo osbuild" +else + SUDO= + OSBUILD="osbuildvm/osbuildvm --arch=$ARCH" +fi + +EXPORT_ARGS="--export $EXPORT" + +CHECKPOINT_ARGS= +for CP in $CHECKPOINTS; do + CHECKPOINT_ARGS="${CHECKPOINT_ARGS} --checkpoint ${CP}" +done + +CHOWNARGS= +if [ $EXTENSION == repo -o $EXTENSION == aboot ]; then + CHOWNARGS=-R # Chown entire repo dir as it doesn't care about permissions +fi + +EXPORTDIRS=$OUTPUTDIR/$EXPORT + +# If OSTREE_REPO is set, and we're building an image that has an +# ostree commit, then we also export that commit to the repo specified +# by OSTREE_REPO. +ALSO_EXPORT_OSTREE=0 +if [ "$OSTREE_REPO" != "" -a "$IMAGETYPE" == "ostree" ]; then + ALSO_EXPORT_OSTREE=1 + if [ $EXPORT != "ostree-commit" ]; then + EXPORT_ARGS="$EXPORT_ARGS --export ostree-commit" + EXPORTDIRS="$EXPORTDIRS $OUTPUTDIR/ostree-commit" + fi + + # Ensure we have a repo to export to + ostree init --repo=$OSTREE_REPO --mode archive +fi + +set -x + +$SUDO rm -rf $EXPORTDIRS +mkdir -p $EXPORTDIRS # Own export dirs by user, not root + +$OSBUILD $CHECKPOINT_ARGS --store $STOREDIR --output-directory $OUTPUTDIR $EXPORT_ARGS $OSBUILD_ARGS $JSON + +if [ $ALSO_EXPORT_OSTREE == "1" ]; then + ostree pull-local --repo=$OSTREE_REPO $OUTPUTDIR/ostree-commit/repo +fi + +# Extract and chown exported file +rm -rf $DEST +$SUDO chown $CHOWNARGS $CURRENT_UIDGID $OUTPUTDIR/$EXPORT/$EXPORT_FILE +$SUDO mv $OUTPUTDIR/$EXPORT/$EXPORT_FILE $DEST + +$SUDO rm -rf $EXPORTDIRS diff --git a/src/tox_lsr/test_scripts/build_ostree_image.sh b/src/tox_lsr/test_scripts/build_ostree_image.sh new file mode 100644 index 0000000..47f6771 --- /dev/null +++ b/src/tox_lsr/test_scripts/build_ostree_image.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -euo pipefail + +#uncomment if you use $ME - otherwise set in utils.sh +#ME=$(basename "$0") +SCRIPTDIR=$(readlink -f "$(dirname "$0")") + +. "${SCRIPTDIR}/utils.sh" + +set -x + +lsr_distro_ver="" +osbuild_distro_ver="" +OSBUILD_DIR="${OSBUILD_DIR:-"$(dirname "$SCRIPTDIR")/osbuild-manifests"}" + +# input is the distro_ver format used by runqemu --image-name +# lsr_distro_ver is the format used by role/.ostree/ +get_distro_ver() { + if [[ "$1" =~ ^rhel-([0-9]+)-([0-9]+) ]]; then + lsr_distro_ver="RedHat-${BASH_REMATCH[1]}.${BASH_REMATCH[2]}" + osbuild_distro_ver="rhel_${BASH_REMATCH[1]}_${BASH_REMATCH[2]}" + elif [[ "$1" =~ ^centos-([0-9]+) ]]; then + lsr_distro_ver="CentOS-${BASH_REMATCH[1]}" + osbuild_distro_ver="cs${BASH_REMATCH[1]}" + elif [[ "$1" =~ ^fedora-([0-9]+) ]]; then + lsr_distro_ver="Fedora-${BASH_REMATCH[1]}" + osbuild_distro_ver="f${BASH_REMATCH[1]}" + fi +} + +# image_name is e.g. rhel-8-9, centos-9, fedora-38 +image_name="$1" +IMAGE_DIR="${IMAGE_DIR:-"$HOME/.cache/linux-system-roles"}" +CACHE_DIR="${CACHE_DIR:-"$IMAGE_DIR/$image_name"}" +IMAGE_FILE="${IMAGE_FILE:-"$IMAGE_DIR/${image_name}-ostree.qcow2"}" + +get_distro_ver "$image_name" + +if [ -f .ostree/get_ostree_data.sh ]; then + PKGS_JSON="$(.ostree/get_ostree_data.sh packages testing "$lsr_distro_ver" json)" +fi + +if [ ! -f "$OSBUILD_DIR/distro/${osbuild_distro_ver}.ipp.yml" ]; then + extra_distro="EXTRA_DISTRO=$HOME/.config/${osbuild_distro_ver}.ipp.yml" +fi +make -C "$OSBUILD_DIR" BUILDDIR="$CACHE_DIR" OUTPUTDIR="$IMAGE_DIR" DESTDIR="$IMAGE_DIR" \ + "${osbuild_distro_ver}-qemu-lsr-ostree.x86_64.qcow2" \ + ${extra_distro:-} \ + DEFINES=extra_rpms="${PKGS_JSON}" +mv "$IMAGE_DIR/${osbuild_distro_ver}-qemu-lsr-ostree.x86_64.qcow2" "$IMAGE_FILE" diff --git a/tests/fixtures/test_tox_merge_ini/result.ini b/tests/fixtures/test_tox_merge_ini/result.ini index 8711ca7..0ac48f3 100644 --- a/tests/fixtures/test_tox_merge_ini/result.ini +++ b/tests/fixtures/test_tox_merge_ini/result.ini @@ -416,3 +416,12 @@ commands = override_custom_cmd deps = override_custom_deps1 override_custom_deps2 +[testenv:build_ostree_image] +changedir = {toxinidir} +allowlist_externals = bash + cat + rm + make + sudo +setenv = {[testenv]setenv} +commands = bash {lsr_scriptdir}/build_ostree_image.sh {posargs}