From 6e6a535ee19cf4fa59ca81e1b81ee51ec183878a Mon Sep 17 00:00:00 2001 From: Roger Luethi Date: Mon, 26 Oct 2026 09:18:42 +0100 Subject: [PATCH] build: check the built image before pushing it The Containerfile installs python-osism, the bundled managers, openstackclient, ansible, openstack-project-manager and openstack-simple-stress with separate `uv pip install` runs. Each run resolves on its own and may change versions an earlier run installed, so nothing checks the requirements of the final environment together. The unit and integration tests run in a separate pipenv virtualenv and never exercise the shipped image either. Add a step after the build, before the push, that runs inside the built image: - `uv pip check --system`, which lists every installed package whose declared requirements are not met. Such conflicts can come from requirements declared by packages that are released from other repositories, so the check reports them in the build log instead of failing the job (exit code 1). Any other non-zero exit code means the check itself could not run, e.g. a missing uv (127) or an image that cannot be started (125), and fails the job. - `--help` or `--version` of every command the image bundles: osism, netbox-manager, openstack-image-manager, openstack-flavor-manager, openstack, ansible, the openstack-project-manager scripts manage.py and create.py (run the way osism invokes them), and the openstack-simple-stress main.py. A failing command fails the job. The frontend image does not bundle these, so the step is skipped for it. Tested against the published image built from 180cf92d, registry.osism.tech/osism/osism@sha256:98a47c05d7a6c79a314f3a4c8f3a8f82568c92619172752949409cc67f89ac9e where the check reports 10 incompatibilities with exit code 1, which the step tolerates, and all smoke tests succeed. Against an image without uv, the step fails with exit code 127. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Roger Luethi --- playbooks/build.yml | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/playbooks/build.yml b/playbooks/build.yml index 11b9cc115..41aa1fa0c 100644 --- a/playbooks/build.yml +++ b/playbooks/build.yml @@ -80,6 +80,49 @@ docker images changed_when: true + - name: Run image check script + ansible.builtin.shell: + executable: /bin/bash + chdir: "{{ zuul.project.src_dir }}/{{ image }}" + cmd: | + set -e + set -o pipefail + set -x + + revision=$(git rev-parse --short HEAD) + + # Report conflicts between the requirements of the installed + # packages. The packages are installed by separate resolver runs, + # so nothing else checks them together. Report only: conflicts + # (exit code 1) do not fail the build, but a check that could not + # run (any other non-zero exit code) does. + rc=0 + docker run --rm "$revision" uv pip check --system || rc=$? + if (( rc > 1 )); then + echo "uv pip check could not run (exit code $rc)" >&2 + exit "$rc" + fi + + # Smoke-test the commands bundled in the image + docker run --rm "$revision" osism --help > /dev/null + docker run --rm "$revision" netbox-manager --help > /dev/null + docker run --rm "$revision" openstack-image-manager --help > /dev/null + docker run --rm "$revision" openstack-flavor-manager --help > /dev/null + docker run --rm "$revision" openstack --version > /dev/null + docker run --rm "$revision" ansible --version > /dev/null + docker run --rm \ + --workdir /openstack-project-manager \ + --env PYTHONPATH=/openstack-project-manager \ + "$revision" python3 openstack_project_manager/manage.py --help > /dev/null + docker run --rm \ + --workdir /openstack-project-manager \ + --env PYTHONPATH=/openstack-project-manager \ + "$revision" python3 openstack_project_manager/create.py --help > /dev/null + docker run --rm \ + "$revision" python3 /openstack-simple-stress/openstack_simple_stress/main.py --help > /dev/null + when: not image + changed_when: false + - name: Run push script ansible.builtin.shell: executable: /bin/bash