You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by po...@apache.org on 2022/06/19 14:17:14 UTC

[airflow] branch main updated: Add verification steps when releasing the images. (#24520)

This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 2936759256 Add verification steps when releasing the images. (#24520)
2936759256 is described below

commit 2936759256273a66cf6343e451d81013a95ec47e
Author: Jarek Potiuk <ja...@polidea.com>
AuthorDate: Sun Jun 19 16:16:59 2022 +0200

    Add verification steps when releasing the images. (#24520)
    
    After the images are pushed in CI we are running the verification
    of the AMD image now.
    
    This cannot be really done during building and pushing the image,
    because we are using multi-platform images using remote builders
    so the image is not even available locally, so we need to actually
    pull the images after they are built in order to verify them.
    
    This PR adds those features:
    * ability to pull images for verification with --pull-flag
    * ability to verify slim images (regular tests are skipped and
      we only expect the preinstalled providers to be available
    * the steps to verify the images (both regular and slim) are
      added to the workflow
---
 .github/workflows/release_dockerhub_image.yml      |  21 +++-
 .../airflow_breeze/commands/ci_image_commands.py   |  12 ++-
 .../commands/production_image_commands.py          |  14 +++
 .../src/airflow_breeze/utils/common_options.py     |   6 ++
 dev/breeze/src/airflow_breeze/utils/image.py       |   1 +
 dev/breeze/src/airflow_breeze/utils/run_tests.py   |   4 +-
 docker_tests/test_prod_image.py                    |  10 +-
 images/breeze/output-commands-hash.txt             |   1 +
 images/breeze/output-verify-image.svg              | 108 ++++++++++----------
 images/breeze/output-verify-prod-image.svg         | 112 +++++++++++----------
 10 files changed, 177 insertions(+), 112 deletions(-)

diff --git a/.github/workflows/release_dockerhub_image.yml b/.github/workflows/release_dockerhub_image.yml
index a6c3e86ddd..cd5fe6e9ce 100644
--- a/.github/workflows/release_dockerhub_image.yml
+++ b/.github/workflows/release_dockerhub_image.yml
@@ -119,12 +119,27 @@ jobs:
           ${{ needs.build-info.outputs.skipLatest }}
           ${{ needs.build-info.outputs.limitPlatform }}
           --limit-python ${{ matrix.python-version }} --slim-images
-      - name: "Docker logout"
-        run: docker logout
-        if: always()
       - name: "Stop ARM instance"
         run: ./scripts/ci/images/ci_stop_arm_instance.sh
         if: always() && github.repository == 'apache/airflow'
+      - name: >
+          Verify regular AMD64 image: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}
+        run: >
+          breeze verify-prod-image
+          --pull-image
+          --image-name
+          ${{github.repository}}:${{github.event.inputs.airflowVersion}}-python${{matrix.python-version}}
+      - name: >
+          Verify slim AMD64 image: ${{ github.event.inputs.airflowVersion }}, ${{ matrix.python-version }}
+        run: >
+          breeze verify-prod-image
+          --pull-image
+          --slim-image
+          --image-name
+          ${{github.repository}}:slim-${{github.event.inputs.airflowVersion}}-python${{matrix.python-version}}
+      - name: "Docker logout"
+        run: docker logout
+        if: always()
       - name: "Fix ownership"
         run: breeze fix-ownership
         if: always()
diff --git a/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py b/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
index c68b3839df..9deac3a276 100644
--- a/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/ci_image_commands.py
@@ -54,6 +54,7 @@ from airflow_breeze.utils.common_options import (
     option_parallelism,
     option_platform,
     option_prepare_buildx_cache,
+    option_pull_image,
     option_push_image,
     option_python,
     option_python_versions,
@@ -181,6 +182,7 @@ CI_IMAGE_TOOLS_PARAMETERS = {
                 "--image-name",
                 "--python",
                 "--image-tag",
+                "--pull-image",
             ],
         }
     ],
@@ -270,7 +272,7 @@ def build_image(
 @option_image_tag
 @option_tag_as_latest
 @click.argument('extra_pytest_args', nargs=-1, type=click.UNPROCESSED)
-def pull_image(
+def pull_ci_image(
     verbose: bool,
     dry_run: bool,
     python: str,
@@ -338,14 +340,16 @@ def pull_image(
 @option_github_repository
 @option_image_tag
 @option_image_name
+@option_pull_image
 @click.argument('extra_pytest_args', nargs=-1, type=click.UNPROCESSED)
-def verify_image(
+def verify_ci_image(
     verbose: bool,
     dry_run: bool,
     python: str,
     github_repository: str,
     image_name: str,
     image_tag: str,
+    pull_image: bool,
     extra_pytest_args: Tuple,
 ):
     """Verify CI image."""
@@ -353,12 +357,16 @@ def verify_image(
     if image_name is None:
         build_params = BuildCiParams(python=python, image_tag=image_tag, github_repository=github_repository)
         image_name = build_params.airflow_image_name_with_tag
+    if pull_image:
+        command_to_run = ["docker", "pull", image_name]
+        run_command(command_to_run, verbose=verbose, dry_run=dry_run, check=True)
     get_console().print(f"[info]Verifying CI image: {image_name}[/]")
     return_code, info = verify_an_image(
         image_name=image_name,
         verbose=verbose,
         dry_run=dry_run,
         image_type='CI',
+        slim_image=False,
         extra_pytest_args=extra_pytest_args,
     )
     sys.exit(return_code)
diff --git a/dev/breeze/src/airflow_breeze/commands/production_image_commands.py b/dev/breeze/src/airflow_breeze/commands/production_image_commands.py
index 8ac7aacab0..0b5ed2e68b 100644
--- a/dev/breeze/src/airflow_breeze/commands/production_image_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/production_image_commands.py
@@ -52,6 +52,7 @@ from airflow_breeze.utils.common_options import (
     option_parallelism,
     option_platform,
     option_prepare_buildx_cache,
+    option_pull_image,
     option_push_image,
     option_python,
     option_python_versions,
@@ -184,6 +185,7 @@ PRODUCTION_IMAGE_TOOLS_PARAMETERS = {
                 "--image-name",
                 "--python",
                 "--image-tag",
+                "--pull-image",
             ],
         }
     ],
@@ -382,6 +384,12 @@ def pull_prod_image(
 @option_github_repository
 @option_image_tag
 @option_image_name
+@option_pull_image
+@click.option(
+    '--slim-image',
+    help='The image to verify is slim and non-slim tests should be skipped.',
+    is_flag=True,
+)
 @click.argument('extra_pytest_args', nargs=-1, type=click.UNPROCESSED)
 def verify_prod_image(
     verbose: bool,
@@ -390,6 +398,8 @@ def verify_prod_image(
     github_repository: str,
     image_name: str,
     image_tag: str,
+    pull_image: bool,
+    slim_image: bool,
     extra_pytest_args: Tuple,
 ):
     """Verify Production image."""
@@ -399,6 +409,9 @@ def verify_prod_image(
             python=python, image_tag=image_tag, github_repository=github_repository
         )
         image_name = build_params.airflow_image_name_with_tag
+    if pull_image:
+        command_to_run = ["docker", "pull", image_name]
+        run_command(command_to_run, verbose=verbose, dry_run=dry_run, check=True)
     get_console().print(f"[info]Verifying PROD image: {image_name}[/]")
     return_code, info = verify_an_image(
         image_name=image_name,
@@ -406,6 +419,7 @@ def verify_prod_image(
         dry_run=dry_run,
         image_type='PROD',
         extra_pytest_args=extra_pytest_args,
+        slim_image=slim_image,
     )
     sys.exit(return_code)
 
diff --git a/dev/breeze/src/airflow_breeze/utils/common_options.py b/dev/breeze/src/airflow_breeze/utils/common_options.py
index 628bb81979..0bc4d5af9f 100644
--- a/dev/breeze/src/airflow_breeze/utils/common_options.py
+++ b/dev/breeze/src/airflow_breeze/utils/common_options.py
@@ -434,3 +434,9 @@ option_airflow_constraints_mode_prod = click.option(
     show_default=True,
     help='Mode of constraints for PROD image building',
 )
+option_pull_image = click.option(
+    '--pull-image',
+    help="Pull image is missing before attempting to verify it.",
+    is_flag=True,
+    envvar='PULL_IMAGE',
+)
diff --git a/dev/breeze/src/airflow_breeze/utils/image.py b/dev/breeze/src/airflow_breeze/utils/image.py
index 36c40cf05a..57ccc2e3a1 100644
--- a/dev/breeze/src/airflow_breeze/utils/image.py
+++ b/dev/breeze/src/airflow_breeze/utils/image.py
@@ -201,6 +201,7 @@ def run_pull_and_verify_image(
         image_type=image_params.image_type,
         dry_run=dry_run,
         verbose=verbose,
+        slim_image=False,
         extra_pytest_args=extra_pytest_args,
     )
 
diff --git a/dev/breeze/src/airflow_breeze/utils/run_tests.py b/dev/breeze/src/airflow_breeze/utils/run_tests.py
index 63c507afe4..6cda9efa1e 100644
--- a/dev/breeze/src/airflow_breeze/utils/run_tests.py
+++ b/dev/breeze/src/airflow_breeze/utils/run_tests.py
@@ -26,7 +26,7 @@ from airflow_breeze.utils.run_utils import run_command
 
 
 def verify_an_image(
-    image_name: str, image_type: str, dry_run: bool, verbose: bool, extra_pytest_args: Tuple
+    image_name: str, image_type: str, dry_run: bool, verbose: bool, slim_image: bool, extra_pytest_args: Tuple
 ) -> Tuple[int, str]:
     command_result = run_command(
         ["docker", "inspect", image_name], dry_run=dry_run, verbose=verbose, check=False, stdout=DEVNULL
@@ -43,6 +43,8 @@ def verify_an_image(
         test_path = AIRFLOW_SOURCES_ROOT / "docker_tests" / "test_ci_image.py"
     env = os.environ.copy()
     env['DOCKER_IMAGE'] = image_name
+    if slim_image:
+        env['TEST_SLIM_IMAGE'] = 'true'
     command_result = run_command(
         [sys.executable, "-m", "pytest", str(test_path), *pytest_args, *extra_pytest_args],
         dry_run=dry_run,
diff --git a/docker_tests/test_prod_image.py b/docker_tests/test_prod_image.py
index 6e47cb0a9d..aae374c4d0 100644
--- a/docker_tests/test_prod_image.py
+++ b/docker_tests/test_prod_image.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import json
+import os
 import subprocess
 import tempfile
 from pathlib import Path
@@ -30,6 +31,7 @@ from docker_tests.docker_tests_utils import (
     run_bash_in_docker,
     run_python_in_docker,
 )
+from setup import PREINSTALLED_PROVIDERS
 
 INSTALLED_PROVIDER_PATH = SOURCE_ROOT / "scripts" / "ci" / "installed_providers.txt"
 
@@ -74,8 +76,11 @@ class TestCommands:
 
 class TestPythonPackages:
     def test_required_providers_are_installed(self):
-        lines = (d.strip() for d in INSTALLED_PROVIDER_PATH.read_text().splitlines())
-        lines = (d for d in lines)
+        if os.environ.get("TEST_SLIM_IMAGE"):
+            lines = PREINSTALLED_PROVIDERS
+        else:
+            lines = (d.strip() for d in INSTALLED_PROVIDER_PATH.read_text().splitlines())
+            lines = (d for d in lines)
         packages_to_install = {f"apache-airflow-providers-{d.replace('.', '-')}" for d in lines}
         assert len(packages_to_install) != 0
 
@@ -163,6 +168,7 @@ class TestPythonPackages:
         "virtualenv": ["virtualenv"],
     }
 
+    @pytest.mark.skipif(os.environ.get("TEST_SLIM_IMAGE") == "true", reason="Skipped with slim image")
     @pytest.mark.parametrize("package_name,import_names", PACKAGE_IMPORTS.items())
     def test_check_dependencies_imports(self, package_name, import_names):
         run_python_in_docker(f"import {','.join(import_names)}")
diff --git a/images/breeze/output-commands-hash.txt b/images/breeze/output-commands-hash.txt
new file mode 100644
index 0000000000..70ac9b305d
--- /dev/null
+++ b/images/breeze/output-commands-hash.txt
@@ -0,0 +1 @@
+8b4116c1808c84d491961283a4ddbec2
diff --git a/images/breeze/output-verify-image.svg b/images/breeze/output-verify-image.svg
index 9c6d1a641f..e2dfddcbb0 100644
--- a/images/breeze/output-verify-image.svg
+++ b/images/breeze/output-verify-image.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 513.5999999999999" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 538.0" xmlns="http://www.w3.org/2000/svg">
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -19,117 +19,121 @@
         font-weight: 700;
     }
 
-    .terminal-4078052804-matrix {
+    .terminal-2021148750-matrix {
         font-family: Fira Code, monospace;
         font-size: 20px;
         line-height: 24.4px;
         font-variant-east-asian: full-width;
     }
 
-    .terminal-4078052804-title {
+    .terminal-2021148750-title {
         font-size: 18px;
         font-weight: bold;
         font-family: arial;
     }
 
-    .terminal-4078052804-r1 { fill: #c5c8c6;font-weight: bold }
-.terminal-4078052804-r2 { fill: #c5c8c6 }
-.terminal-4078052804-r3 { fill: #d0b344;font-weight: bold }
-.terminal-4078052804-r4 { fill: #868887 }
-.terminal-4078052804-r5 { fill: #68a0b3;font-weight: bold }
-.terminal-4078052804-r6 { fill: #98a84b;font-weight: bold }
-.terminal-4078052804-r7 { fill: #8d7b39 }
+    .terminal-2021148750-r1 { fill: #c5c8c6;font-weight: bold }
+.terminal-2021148750-r2 { fill: #c5c8c6 }
+.terminal-2021148750-r3 { fill: #d0b344;font-weight: bold }
+.terminal-2021148750-r4 { fill: #868887 }
+.terminal-2021148750-r5 { fill: #68a0b3;font-weight: bold }
+.terminal-2021148750-r6 { fill: #98a84b;font-weight: bold }
+.terminal-2021148750-r7 { fill: #8d7b39 }
     </style>
 
     <defs>
-    <clipPath id="terminal-4078052804-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="462.59999999999997" />
+    <clipPath id="terminal-2021148750-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="487.0" />
     </clipPath>
-    <clipPath id="terminal-4078052804-line-0">
+    <clipPath id="terminal-2021148750-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-1">
+<clipPath id="terminal-2021148750-line-1">
     <rect x="0" y="25.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-2">
+<clipPath id="terminal-2021148750-line-2">
     <rect x="0" y="50.3" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-3">
+<clipPath id="terminal-2021148750-line-3">
     <rect x="0" y="74.7" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-4">
+<clipPath id="terminal-2021148750-line-4">
     <rect x="0" y="99.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-5">
+<clipPath id="terminal-2021148750-line-5">
     <rect x="0" y="123.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-6">
+<clipPath id="terminal-2021148750-line-6">
     <rect x="0" y="147.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-7">
+<clipPath id="terminal-2021148750-line-7">
     <rect x="0" y="172.3" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-8">
+<clipPath id="terminal-2021148750-line-8">
     <rect x="0" y="196.7" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-9">
+<clipPath id="terminal-2021148750-line-9">
     <rect x="0" y="221.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-10">
+<clipPath id="terminal-2021148750-line-10">
     <rect x="0" y="245.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-11">
+<clipPath id="terminal-2021148750-line-11">
     <rect x="0" y="269.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-12">
+<clipPath id="terminal-2021148750-line-12">
     <rect x="0" y="294.3" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-13">
+<clipPath id="terminal-2021148750-line-13">
     <rect x="0" y="318.7" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-14">
+<clipPath id="terminal-2021148750-line-14">
     <rect x="0" y="343.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-15">
+<clipPath id="terminal-2021148750-line-15">
     <rect x="0" y="367.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-16">
+<clipPath id="terminal-2021148750-line-16">
     <rect x="0" y="391.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-4078052804-line-17">
+<clipPath id="terminal-2021148750-line-17">
     <rect x="0" y="416.3" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="terminal-2021148750-line-18">
+    <rect x="0" y="440.7" width="1464" height="24.65"/>
+            </clipPath>
     </defs>
 
-    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="511.6" rx="8"/><text class="terminal-4078052804-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;verify-image</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="536" rx="8"/><text class="terminal-2021148750-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;verify-image</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
             <circle cx="44" cy="0" r="7" fill="#28c840"/>
             </g>
         
-    <g transform="translate(9, 41)" clip-path="url(#terminal-4078052804-clip-terminal)">
+    <g transform="translate(9, 41)" clip-path="url(#terminal-2021148750-clip-terminal)">
     
-    <g class="terminal-4078052804-matrix">
-    <text class="terminal-4078052804-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-4078052804-line-0)">
-</text><text class="terminal-4078052804-r3" x="12.2" y="44.4" textLength="85.4" clip-path="url(#terminal-4078052804-line-1)">Usage:&#160;</text><text class="terminal-4078052804-r1" x="97.6" y="44.4" textLength="634.4" clip-path="url(#terminal-4078052804-line-1)">breeze&#160;verify-image&#160;[OPTIONS]&#160;[EXTRA_PYTEST_ARGS]...</text><text class="terminal-4078052804-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-4078052804-line-1)">
-</text><text class="terminal-4078052804-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-4078052804-line-2)">
-</text><text class="terminal-4078052804-r2" x="12.2" y="93.2" textLength="195.2" clip-path="url(#terminal-4078052804-line-3)">Verify&#160;CI&#160;image.</text><text class="terminal-4078052804-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-4078052804-line-3)">
-</text><text class="terminal-4078052804-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-4078052804-line-4)">
-</text><text class="terminal-4078052804-r4" x="0" y="142" textLength="24.4" clip-path="url(#terminal-4078052804-line-5)">╭─</text><text class="terminal-4078052804-r4" x="24.4" y="142" textLength="1415.2" clip-path="url(#terminal-4078052804-line-5)">&#160;Verify&#160;image&#160;flags&#160;────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-4078052804-r4" x="1439.6" y="142" textLength="24.4" clip-path="url(#terminal-4 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-4078052804-line-6)">│</text><text class="terminal-4078052804-r5" x="24.4" y="166.4" textLength="12.2" clip-path="url(#terminal-4078052804-line-6)">-</text><text class="terminal-4078052804-r5" x="36.6" y="166.4" textLength="73.2" clip-path="url(#terminal-4078052804-line-6)">-image</text><text class="terminal-4078052804-r5" x="109.8" y="166.4" textLength="61" clip-path="url(#terminal-4078 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-4078052804-line-7)">│</text><text class="terminal-4078052804-r5" x="24.4" y="190.8" textLength="12.2" clip-path="url(#terminal-4078052804-line-7)">-</text><text class="terminal-4078052804-r5" x="36.6" y="190.8" textLength="85.4" clip-path="url(#terminal-4078052804-line-7)">-python</text><text class="terminal-4078052804-r6" x="195.2" y="190.8" textLength="24.4" clip-path="url(#terminal-4 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-4078052804-line-8)">│</text><text class="terminal-4078052804-r4" x="244" y="215.2" textLength="732" clip-path="url(#terminal-4078052804-line-8)">[default:&#160;3.7]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-4078052804-line-9)">│</text><text class="terminal-4078052804-r5" x="24.4" y="239.6" textLength="12.2" clip-path="url(#terminal-4078052804-line-9)">-</text><text class="terminal-4078052804-r5" x="36.6" y="239.6" textLength="73.2" clip-path="url(#terminal-4078052804-line-9)">-image</text><text class="terminal-4078052804-r5" x="109.8" y="239.6" textLength="48.8" clip-path="url(#terminal-40 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="264" textLength="12.2" clip-path="url(#terminal-4078052804-line-10)">│</text><text class="terminal-4078052804-r2" x="244" y="264" textLength="1195.6" clip-path="url(#terminal-4078052804-line-10)">to&#160;run&#160;shell&#160;or&#160;tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-4078052804-line-11)">│</text><text class="terminal-4078052804-r7" x="244" y="288.4" textLength="1195.6" clip-path="url(#terminal-4078052804-line-11)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="312.8" textLength="1464" clip-path="url(#terminal-4078052804-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-4078052804-r2" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-4078052804-line-12)">
-</text><text class="terminal-4078052804-r4" x="0" y="337.2" textLength="24.4" clip-path="url(#terminal-4078052804-line-13)">╭─</text><text class="terminal-4078052804-r4" x="24.4" y="337.2" textLength="1415.2" clip-path="url(#terminal-4078052804-line-13)">&#160;Options&#160;───────────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-4078052804-r4" x="1439.6" y="337.2" textLength="24.4" clip-path="url(#terminal-407 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="361.6" textLength="12.2" clip-path="url(#terminal-4078052804-line-14)">│</text><text class="terminal-4078052804-r5" x="24.4" y="361.6" textLength="12.2" clip-path="url(#terminal-4078052804-line-14)">-</text><text class="terminal-4078052804-r5" x="36.6" y="361.6" textLength="97.6" clip-path="url(#terminal-4078052804-line-14)">-verbose</text><text class="terminal-4078052804-r6" x="280.6" y="361.6" textLength="24.4" clip-path="url(#termin [...]
-</text><text class="terminal-4078052804-r4" x="0" y="386" textLength="12.2" clip-path="url(#terminal-4078052804-line-15)">│</text><text class="terminal-4078052804-r5" x="24.4" y="386" textLength="12.2" clip-path="url(#terminal-4078052804-line-15)">-</text><text class="terminal-4078052804-r5" x="36.6" y="386" textLength="48.8" clip-path="url(#terminal-4078052804-line-15)">-dry</text><text class="terminal-4078052804-r5" x="85.4" y="386" textLength="48.8" clip-path="url(#terminal-4078052804 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="410.4" textLength="12.2" clip-path="url(#terminal-4078052804-line-16)">│</text><text class="terminal-4078052804-r5" x="24.4" y="410.4" textLength="12.2" clip-path="url(#terminal-4078052804-line-16)">-</text><text class="terminal-4078052804-r5" x="36.6" y="410.4" textLength="85.4" clip-path="url(#terminal-4078052804-line-16)">-github</text><text class="terminal-4078052804-r5" x="122" y="410.4" textLength="134.2" clip-path="url(#terminal [...]
-</text><text class="terminal-4078052804-r4" x="0" y="434.8" textLength="12.2" clip-path="url(#terminal-4078052804-line-17)">│</text><text class="terminal-4078052804-r5" x="24.4" y="434.8" textLength="12.2" clip-path="url(#terminal-4078052804-line-17)">-</text><text class="terminal-4078052804-r5" x="36.6" y="434.8" textLength="61" clip-path="url(#terminal-4078052804-line-17)">-help</text><text class="terminal-4078052804-r6" x="280.6" y="434.8" textLength="24.4" clip-path="url(#terminal-40 [...]
-</text><text class="terminal-4078052804-r4" x="0" y="459.2" textLength="1464" clip-path="url(#terminal-4078052804-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-4078052804-r2" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-4078052804-line-18)">
+    <g class="terminal-2021148750-matrix">
+    <text class="terminal-2021148750-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-2021148750-line-0)">
+</text><text class="terminal-2021148750-r3" x="12.2" y="44.4" textLength="85.4" clip-path="url(#terminal-2021148750-line-1)">Usage:&#160;</text><text class="terminal-2021148750-r1" x="97.6" y="44.4" textLength="634.4" clip-path="url(#terminal-2021148750-line-1)">breeze&#160;verify-image&#160;[OPTIONS]&#160;[EXTRA_PYTEST_ARGS]...</text><text class="terminal-2021148750-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-2021148750-line-1)">
+</text><text class="terminal-2021148750-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-2)">
+</text><text class="terminal-2021148750-r2" x="12.2" y="93.2" textLength="195.2" clip-path="url(#terminal-2021148750-line-3)">Verify&#160;CI&#160;image.</text><text class="terminal-2021148750-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-2021148750-line-3)">
+</text><text class="terminal-2021148750-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-2021148750-line-4)">
+</text><text class="terminal-2021148750-r4" x="0" y="142" textLength="24.4" clip-path="url(#terminal-2021148750-line-5)">╭─</text><text class="terminal-2021148750-r4" x="24.4" y="142" textLength="1415.2" clip-path="url(#terminal-2021148750-line-5)">&#160;Verify&#160;image&#160;flags&#160;────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-2021148750-r4" x="1439.6" y="142" textLength="24.4" clip-path="url(#terminal-2 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-2021148750-line-6)">│</text><text class="terminal-2021148750-r5" x="24.4" y="166.4" textLength="12.2" clip-path="url(#terminal-2021148750-line-6)">-</text><text class="terminal-2021148750-r5" x="36.6" y="166.4" textLength="73.2" clip-path="url(#terminal-2021148750-line-6)">-image</text><text class="terminal-2021148750-r5" x="109.8" y="166.4" textLength="61" clip-path="url(#terminal-2021 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-7)">│</text><text class="terminal-2021148750-r5" x="24.4" y="190.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-7)">-</text><text class="terminal-2021148750-r5" x="36.6" y="190.8" textLength="85.4" clip-path="url(#terminal-2021148750-line-7)">-python</text><text class="terminal-2021148750-r6" x="195.2" y="190.8" textLength="24.4" clip-path="url(#terminal-2 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-2021148750-line-8)">│</text><text class="terminal-2021148750-r4" x="244" y="215.2" textLength="732" clip-path="url(#terminal-2021148750-line-8)">[default:&#160;3.7]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-2021148750-line-9)">│</text><text class="terminal-2021148750-r5" x="24.4" y="239.6" textLength="12.2" clip-path="url(#terminal-2021148750-line-9)">-</text><text class="terminal-2021148750-r5" x="36.6" y="239.6" textLength="73.2" clip-path="url(#terminal-2021148750-line-9)">-image</text><text class="terminal-2021148750-r5" x="109.8" y="239.6" textLength="48.8" clip-path="url(#terminal-20 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="264" textLength="12.2" clip-path="url(#terminal-2021148750-line-10)">│</text><text class="terminal-2021148750-r2" x="244" y="264" textLength="1195.6" clip-path="url(#terminal-2021148750-line-10)">to&#160;run&#160;shell&#160;or&#160;tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-2021148750-line-11)">│</text><text class="terminal-2021148750-r7" x="244" y="288.4" textLength="1195.6" clip-path="url(#terminal-2021148750-line-11)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="312.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-12)">│</text><text class="terminal-2021148750-r5" x="24.4" y="312.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-12)">-</text><text class="terminal-2021148750-r5" x="36.6" y="312.8" textLength="61" clip-path="url(#terminal-2021148750-line-12)">-pull</text><text class="terminal-2021148750-r5" x="97.6" y="312.8" textLength="73.2" clip-path="url(#terminal-202 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="337.2" textLength="1464" clip-path="url(#terminal-2021148750-line-13)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-2021148750-r2" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-2021148750-line-13)">
+</text><text class="terminal-2021148750-r4" x="0" y="361.6" textLength="24.4" clip-path="url(#terminal-2021148750-line-14)">╭─</text><text class="terminal-2021148750-r4" x="24.4" y="361.6" textLength="1415.2" clip-path="url(#terminal-2021148750-line-14)">&#160;Options&#160;───────────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-2021148750-r4" x="1439.6" y="361.6" textLength="24.4" clip-path="url(#terminal-202 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="386" textLength="12.2" clip-path="url(#terminal-2021148750-line-15)">│</text><text class="terminal-2021148750-r5" x="24.4" y="386" textLength="12.2" clip-path="url(#terminal-2021148750-line-15)">-</text><text class="terminal-2021148750-r5" x="36.6" y="386" textLength="97.6" clip-path="url(#terminal-2021148750-line-15)">-verbose</text><text class="terminal-2021148750-r6" x="280.6" y="386" textLength="24.4" clip-path="url(#terminal-20211 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="410.4" textLength="12.2" clip-path="url(#terminal-2021148750-line-16)">│</text><text class="terminal-2021148750-r5" x="24.4" y="410.4" textLength="12.2" clip-path="url(#terminal-2021148750-line-16)">-</text><text class="terminal-2021148750-r5" x="36.6" y="410.4" textLength="48.8" clip-path="url(#terminal-2021148750-line-16)">-dry</text><text class="terminal-2021148750-r5" x="85.4" y="410.4" textLength="48.8" clip-path="url(#terminal-20 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="434.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-17)">│</text><text class="terminal-2021148750-r5" x="24.4" y="434.8" textLength="12.2" clip-path="url(#terminal-2021148750-line-17)">-</text><text class="terminal-2021148750-r5" x="36.6" y="434.8" textLength="85.4" clip-path="url(#terminal-2021148750-line-17)">-github</text><text class="terminal-2021148750-r5" x="122" y="434.8" textLength="134.2" clip-path="url(#terminal [...]
+</text><text class="terminal-2021148750-r4" x="0" y="459.2" textLength="12.2" clip-path="url(#terminal-2021148750-line-18)">│</text><text class="terminal-2021148750-r5" x="24.4" y="459.2" textLength="12.2" clip-path="url(#terminal-2021148750-line-18)">-</text><text class="terminal-2021148750-r5" x="36.6" y="459.2" textLength="61" clip-path="url(#terminal-2021148750-line-18)">-help</text><text class="terminal-2021148750-r6" x="280.6" y="459.2" textLength="24.4" clip-path="url(#terminal-20 [...]
+</text><text class="terminal-2021148750-r4" x="0" y="483.6" textLength="1464" clip-path="url(#terminal-2021148750-line-19)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-2021148750-r2" x="1464" y="483.6" textLength="12.2" clip-path="url(#terminal-2021148750-line-19)">
 </text>
     </g>
     </g>
diff --git a/images/breeze/output-verify-prod-image.svg b/images/breeze/output-verify-prod-image.svg
index 48b61a3082..31c7b66b72 100644
--- a/images/breeze/output-verify-prod-image.svg
+++ b/images/breeze/output-verify-prod-image.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 513.5999999999999" xmlns="http://www.w3.org/2000/svg">
+<svg class="rich-terminal" viewBox="0 0 1482 562.4" xmlns="http://www.w3.org/2000/svg">
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -19,117 +19,125 @@
         font-weight: 700;
     }
 
-    .terminal-1294281603-matrix {
+    .terminal-464155386-matrix {
         font-family: Fira Code, monospace;
         font-size: 20px;
         line-height: 24.4px;
         font-variant-east-asian: full-width;
     }
 
-    .terminal-1294281603-title {
+    .terminal-464155386-title {
         font-size: 18px;
         font-weight: bold;
         font-family: arial;
     }
 
-    .terminal-1294281603-r1 { fill: #c5c8c6;font-weight: bold }
-.terminal-1294281603-r2 { fill: #c5c8c6 }
-.terminal-1294281603-r3 { fill: #d0b344;font-weight: bold }
-.terminal-1294281603-r4 { fill: #868887 }
-.terminal-1294281603-r5 { fill: #68a0b3;font-weight: bold }
-.terminal-1294281603-r6 { fill: #98a84b;font-weight: bold }
-.terminal-1294281603-r7 { fill: #8d7b39 }
+    .terminal-464155386-r1 { fill: #c5c8c6;font-weight: bold }
+.terminal-464155386-r2 { fill: #c5c8c6 }
+.terminal-464155386-r3 { fill: #d0b344;font-weight: bold }
+.terminal-464155386-r4 { fill: #868887 }
+.terminal-464155386-r5 { fill: #68a0b3;font-weight: bold }
+.terminal-464155386-r6 { fill: #98a84b;font-weight: bold }
+.terminal-464155386-r7 { fill: #8d7b39 }
     </style>
 
     <defs>
-    <clipPath id="terminal-1294281603-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="462.59999999999997" />
+    <clipPath id="terminal-464155386-clip-terminal">
+      <rect x="0" y="0" width="1463.0" height="511.4" />
     </clipPath>
-    <clipPath id="terminal-1294281603-line-0">
+    <clipPath id="terminal-464155386-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-1">
+<clipPath id="terminal-464155386-line-1">
     <rect x="0" y="25.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-2">
+<clipPath id="terminal-464155386-line-2">
     <rect x="0" y="50.3" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-3">
+<clipPath id="terminal-464155386-line-3">
     <rect x="0" y="74.7" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-4">
+<clipPath id="terminal-464155386-line-4">
     <rect x="0" y="99.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-5">
+<clipPath id="terminal-464155386-line-5">
     <rect x="0" y="123.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-6">
+<clipPath id="terminal-464155386-line-6">
     <rect x="0" y="147.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-7">
+<clipPath id="terminal-464155386-line-7">
     <rect x="0" y="172.3" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-8">
+<clipPath id="terminal-464155386-line-8">
     <rect x="0" y="196.7" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-9">
+<clipPath id="terminal-464155386-line-9">
     <rect x="0" y="221.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-10">
+<clipPath id="terminal-464155386-line-10">
     <rect x="0" y="245.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-11">
+<clipPath id="terminal-464155386-line-11">
     <rect x="0" y="269.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-12">
+<clipPath id="terminal-464155386-line-12">
     <rect x="0" y="294.3" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-13">
+<clipPath id="terminal-464155386-line-13">
     <rect x="0" y="318.7" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-14">
+<clipPath id="terminal-464155386-line-14">
     <rect x="0" y="343.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-15">
+<clipPath id="terminal-464155386-line-15">
     <rect x="0" y="367.5" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-16">
+<clipPath id="terminal-464155386-line-16">
     <rect x="0" y="391.9" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="terminal-1294281603-line-17">
+<clipPath id="terminal-464155386-line-17">
     <rect x="0" y="416.3" width="1464" height="24.65"/>
             </clipPath>
+<clipPath id="terminal-464155386-line-18">
+    <rect x="0" y="440.7" width="1464" height="24.65"/>
+            </clipPath>
+<clipPath id="terminal-464155386-line-19">
+    <rect x="0" y="465.1" width="1464" height="24.65"/>
+            </clipPath>
     </defs>
 
-    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="511.6" rx="8"/><text class="terminal-1294281603-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;verify-prod-image</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="560.4" rx="8"/><text class="terminal-464155386-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">Command:&#160;verify-prod-image</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
             <circle cx="44" cy="0" r="7" fill="#28c840"/>
             </g>
         
-    <g transform="translate(9, 41)" clip-path="url(#terminal-1294281603-clip-terminal)">
+    <g transform="translate(9, 41)" clip-path="url(#terminal-464155386-clip-terminal)">
     
-    <g class="terminal-1294281603-matrix">
-    <text class="terminal-1294281603-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-1294281603-line-0)">
-</text><text class="terminal-1294281603-r3" x="12.2" y="44.4" textLength="85.4" clip-path="url(#terminal-1294281603-line-1)">Usage:&#160;</text><text class="terminal-1294281603-r1" x="97.6" y="44.4" textLength="695.4" clip-path="url(#terminal-1294281603-line-1)">breeze&#160;verify-prod-image&#160;[OPTIONS]&#160;[EXTRA_PYTEST_ARGS]...</text><text class="terminal-1294281603-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-1294281603-line-1)">
-</text><text class="terminal-1294281603-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-1294281603-line-2)">
-</text><text class="terminal-1294281603-r2" x="12.2" y="93.2" textLength="292.8" clip-path="url(#terminal-1294281603-line-3)">Verify&#160;Production&#160;image.</text><text class="terminal-1294281603-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-1294281603-line-3)">
-</text><text class="terminal-1294281603-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-1294281603-line-4)">
-</text><text class="terminal-1294281603-r4" x="0" y="142" textLength="24.4" clip-path="url(#terminal-1294281603-line-5)">╭─</text><text class="terminal-1294281603-r4" x="24.4" y="142" textLength="1415.2" clip-path="url(#terminal-1294281603-line-5)">&#160;Verify&#160;image&#160;flags&#160;────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-1294281603-r4" x="1439.6" y="142" textLength="24.4" clip-path="url(#terminal-1 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-1294281603-line-6)">│</text><text class="terminal-1294281603-r5" x="24.4" y="166.4" textLength="12.2" clip-path="url(#terminal-1294281603-line-6)">-</text><text class="terminal-1294281603-r5" x="36.6" y="166.4" textLength="73.2" clip-path="url(#terminal-1294281603-line-6)">-image</text><text class="terminal-1294281603-r5" x="109.8" y="166.4" textLength="61" clip-path="url(#terminal-1294 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-1294281603-line-7)">│</text><text class="terminal-1294281603-r5" x="24.4" y="190.8" textLength="12.2" clip-path="url(#terminal-1294281603-line-7)">-</text><text class="terminal-1294281603-r5" x="36.6" y="190.8" textLength="85.4" clip-path="url(#terminal-1294281603-line-7)">-python</text><text class="terminal-1294281603-r6" x="195.2" y="190.8" textLength="24.4" clip-path="url(#terminal-1 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-1294281603-line-8)">│</text><text class="terminal-1294281603-r4" x="244" y="215.2" textLength="732" clip-path="url(#terminal-1294281603-line-8)">[default:&#160;3.7]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-1294281603-line-9)">│</text><text class="terminal-1294281603-r5" x="24.4" y="239.6" textLength="12.2" clip-path="url(#terminal-1294281603-line-9)">-</text><text class="terminal-1294281603-r5" x="36.6" y="239.6" textLength="73.2" clip-path="url(#terminal-1294281603-line-9)">-image</text><text class="terminal-1294281603-r5" x="109.8" y="239.6" textLength="48.8" clip-path="url(#terminal-12 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="264" textLength="12.2" clip-path="url(#terminal-1294281603-line-10)">│</text><text class="terminal-1294281603-r2" x="244" y="264" textLength="1195.6" clip-path="url(#terminal-1294281603-line-10)">to&#160;run&#160;shell&#160;or&#160;tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-1294281603-line-11)">│</text><text class="terminal-1294281603-r7" x="244" y="288.4" textLength="1195.6" clip-path="url(#terminal-1294281603-line-11)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="312.8" textLength="1464" clip-path="url(#terminal-1294281603-line-12)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1294281603-r2" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-1294281603-line-12)">
-</text><text class="terminal-1294281603-r4" x="0" y="337.2" textLength="24.4" clip-path="url(#terminal-1294281603-line-13)">╭─</text><text class="terminal-1294281603-r4" x="24.4" y="337.2" textLength="1415.2" clip-path="url(#terminal-1294281603-line-13)">&#160;Options&#160;───────────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-1294281603-r4" x="1439.6" y="337.2" textLength="24.4" clip-path="url(#terminal-129 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="361.6" textLength="12.2" clip-path="url(#terminal-1294281603-line-14)">│</text><text class="terminal-1294281603-r5" x="24.4" y="361.6" textLength="12.2" clip-path="url(#terminal-1294281603-line-14)">-</text><text class="terminal-1294281603-r5" x="36.6" y="361.6" textLength="97.6" clip-path="url(#terminal-1294281603-line-14)">-verbose</text><text class="terminal-1294281603-r6" x="280.6" y="361.6" textLength="24.4" clip-path="url(#termin [...]
-</text><text class="terminal-1294281603-r4" x="0" y="386" textLength="12.2" clip-path="url(#terminal-1294281603-line-15)">│</text><text class="terminal-1294281603-r5" x="24.4" y="386" textLength="12.2" clip-path="url(#terminal-1294281603-line-15)">-</text><text class="terminal-1294281603-r5" x="36.6" y="386" textLength="48.8" clip-path="url(#terminal-1294281603-line-15)">-dry</text><text class="terminal-1294281603-r5" x="85.4" y="386" textLength="48.8" clip-path="url(#terminal-1294281603 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="410.4" textLength="12.2" clip-path="url(#terminal-1294281603-line-16)">│</text><text class="terminal-1294281603-r5" x="24.4" y="410.4" textLength="12.2" clip-path="url(#terminal-1294281603-line-16)">-</text><text class="terminal-1294281603-r5" x="36.6" y="410.4" textLength="85.4" clip-path="url(#terminal-1294281603-line-16)">-github</text><text class="terminal-1294281603-r5" x="122" y="410.4" textLength="134.2" clip-path="url(#terminal [...]
-</text><text class="terminal-1294281603-r4" x="0" y="434.8" textLength="12.2" clip-path="url(#terminal-1294281603-line-17)">│</text><text class="terminal-1294281603-r5" x="24.4" y="434.8" textLength="12.2" clip-path="url(#terminal-1294281603-line-17)">-</text><text class="terminal-1294281603-r5" x="36.6" y="434.8" textLength="61" clip-path="url(#terminal-1294281603-line-17)">-help</text><text class="terminal-1294281603-r6" x="280.6" y="434.8" textLength="24.4" clip-path="url(#terminal-12 [...]
-</text><text class="terminal-1294281603-r4" x="0" y="459.2" textLength="1464" clip-path="url(#terminal-1294281603-line-18)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-1294281603-r2" x="1464" y="459.2" textLength="12.2" clip-path="url(#terminal-1294281603-line-18)">
+    <g class="terminal-464155386-matrix">
+    <text class="terminal-464155386-r2" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-464155386-line-0)">
+</text><text class="terminal-464155386-r3" x="12.2" y="44.4" textLength="85.4" clip-path="url(#terminal-464155386-line-1)">Usage:&#160;</text><text class="terminal-464155386-r1" x="97.6" y="44.4" textLength="695.4" clip-path="url(#terminal-464155386-line-1)">breeze&#160;verify-prod-image&#160;[OPTIONS]&#160;[EXTRA_PYTEST_ARGS]...</text><text class="terminal-464155386-r2" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-464155386-line-1)">
+</text><text class="terminal-464155386-r2" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-464155386-line-2)">
+</text><text class="terminal-464155386-r2" x="12.2" y="93.2" textLength="292.8" clip-path="url(#terminal-464155386-line-3)">Verify&#160;Production&#160;image.</text><text class="terminal-464155386-r2" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-464155386-line-3)">
+</text><text class="terminal-464155386-r2" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-464155386-line-4)">
+</text><text class="terminal-464155386-r4" x="0" y="142" textLength="24.4" clip-path="url(#terminal-464155386-line-5)">╭─</text><text class="terminal-464155386-r4" x="24.4" y="142" textLength="1415.2" clip-path="url(#terminal-464155386-line-5)">&#160;Verify&#160;image&#160;flags&#160;────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-464155386-r4" x="1439.6" y="142" textLength="24.4" clip-path="url(#terminal-464155 [...]
+</text><text class="terminal-464155386-r4" x="0" y="166.4" textLength="12.2" clip-path="url(#terminal-464155386-line-6)">│</text><text class="terminal-464155386-r5" x="24.4" y="166.4" textLength="12.2" clip-path="url(#terminal-464155386-line-6)">-</text><text class="terminal-464155386-r5" x="36.6" y="166.4" textLength="73.2" clip-path="url(#terminal-464155386-line-6)">-image</text><text class="terminal-464155386-r5" x="109.8" y="166.4" textLength="61" clip-path="url(#terminal-464155386-l [...]
+</text><text class="terminal-464155386-r4" x="0" y="190.8" textLength="12.2" clip-path="url(#terminal-464155386-line-7)">│</text><text class="terminal-464155386-r5" x="24.4" y="190.8" textLength="12.2" clip-path="url(#terminal-464155386-line-7)">-</text><text class="terminal-464155386-r5" x="36.6" y="190.8" textLength="85.4" clip-path="url(#terminal-464155386-line-7)">-python</text><text class="terminal-464155386-r6" x="195.2" y="190.8" textLength="24.4" clip-path="url(#terminal-46415538 [...]
+</text><text class="terminal-464155386-r4" x="0" y="215.2" textLength="12.2" clip-path="url(#terminal-464155386-line-8)">│</text><text class="terminal-464155386-r4" x="244" y="215.2" textLength="732" clip-path="url(#terminal-464155386-line-8)">[default:&#160;3.7]&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;& [...]
+</text><text class="terminal-464155386-r4" x="0" y="239.6" textLength="12.2" clip-path="url(#terminal-464155386-line-9)">│</text><text class="terminal-464155386-r5" x="24.4" y="239.6" textLength="12.2" clip-path="url(#terminal-464155386-line-9)">-</text><text class="terminal-464155386-r5" x="36.6" y="239.6" textLength="73.2" clip-path="url(#terminal-464155386-line-9)">-image</text><text class="terminal-464155386-r5" x="109.8" y="239.6" textLength="48.8" clip-path="url(#terminal-464155386 [...]
+</text><text class="terminal-464155386-r4" x="0" y="264" textLength="12.2" clip-path="url(#terminal-464155386-line-10)">│</text><text class="terminal-464155386-r2" x="244" y="264" textLength="1195.6" clip-path="url(#terminal-464155386-line-10)">to&#160;run&#160;shell&#160;or&#160;tests)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;& [...]
+</text><text class="terminal-464155386-r4" x="0" y="288.4" textLength="12.2" clip-path="url(#terminal-464155386-line-11)">│</text><text class="terminal-464155386-r7" x="244" y="288.4" textLength="1195.6" clip-path="url(#terminal-464155386-line-11)">(TEXT)&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#1 [...]
+</text><text class="terminal-464155386-r4" x="0" y="312.8" textLength="12.2" clip-path="url(#terminal-464155386-line-12)">│</text><text class="terminal-464155386-r5" x="24.4" y="312.8" textLength="12.2" clip-path="url(#terminal-464155386-line-12)">-</text><text class="terminal-464155386-r5" x="36.6" y="312.8" textLength="61" clip-path="url(#terminal-464155386-line-12)">-pull</text><text class="terminal-464155386-r5" x="97.6" y="312.8" textLength="73.2" clip-path="url(#terminal-464155386- [...]
+</text><text class="terminal-464155386-r4" x="0" y="337.2" textLength="1464" clip-path="url(#terminal-464155386-line-13)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-464155386-r2" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-464155386-line-13)">
+</text><text class="terminal-464155386-r4" x="0" y="361.6" textLength="24.4" clip-path="url(#terminal-464155386-line-14)">╭─</text><text class="terminal-464155386-r4" x="24.4" y="361.6" textLength="1415.2" clip-path="url(#terminal-464155386-line-14)">&#160;Options&#160;───────────────────────────────────────────────────────────────────────────────────────────────────────────</text><text class="terminal-464155386-r4" x="1439.6" y="361.6" textLength="24.4" clip-path="url(#terminal-46415538 [...]
+</text><text class="terminal-464155386-r4" x="0" y="386" textLength="12.2" clip-path="url(#terminal-464155386-line-15)">│</text><text class="terminal-464155386-r5" x="24.4" y="386" textLength="12.2" clip-path="url(#terminal-464155386-line-15)">-</text><text class="terminal-464155386-r5" x="36.6" y="386" textLength="97.6" clip-path="url(#terminal-464155386-line-15)">-verbose</text><text class="terminal-464155386-r6" x="280.6" y="386" textLength="24.4" clip-path="url(#terminal-464155386-li [...]
+</text><text class="terminal-464155386-r4" x="0" y="410.4" textLength="12.2" clip-path="url(#terminal-464155386-line-16)">│</text><text class="terminal-464155386-r5" x="24.4" y="410.4" textLength="12.2" clip-path="url(#terminal-464155386-line-16)">-</text><text class="terminal-464155386-r5" x="36.6" y="410.4" textLength="48.8" clip-path="url(#terminal-464155386-line-16)">-dry</text><text class="terminal-464155386-r5" x="85.4" y="410.4" textLength="48.8" clip-path="url(#terminal-464155386 [...]
+</text><text class="terminal-464155386-r4" x="0" y="434.8" textLength="12.2" clip-path="url(#terminal-464155386-line-17)">│</text><text class="terminal-464155386-r5" x="24.4" y="434.8" textLength="12.2" clip-path="url(#terminal-464155386-line-17)">-</text><text class="terminal-464155386-r5" x="36.6" y="434.8" textLength="85.4" clip-path="url(#terminal-464155386-line-17)">-github</text><text class="terminal-464155386-r5" x="122" y="434.8" textLength="134.2" clip-path="url(#terminal-464155 [...]
+</text><text class="terminal-464155386-r4" x="0" y="459.2" textLength="12.2" clip-path="url(#terminal-464155386-line-18)">│</text><text class="terminal-464155386-r5" x="24.4" y="459.2" textLength="12.2" clip-path="url(#terminal-464155386-line-18)">-</text><text class="terminal-464155386-r5" x="36.6" y="459.2" textLength="61" clip-path="url(#terminal-464155386-line-18)">-slim</text><text class="terminal-464155386-r5" x="97.6" y="459.2" textLength="73.2" clip-path="url(#terminal-464155386- [...]
+</text><text class="terminal-464155386-r4" x="0" y="483.6" textLength="12.2" clip-path="url(#terminal-464155386-line-19)">│</text><text class="terminal-464155386-r5" x="24.4" y="483.6" textLength="12.2" clip-path="url(#terminal-464155386-line-19)">-</text><text class="terminal-464155386-r5" x="36.6" y="483.6" textLength="61" clip-path="url(#terminal-464155386-line-19)">-help</text><text class="terminal-464155386-r6" x="280.6" y="483.6" textLength="24.4" clip-path="url(#terminal-464155386 [...]
+</text><text class="terminal-464155386-r4" x="0" y="508" textLength="1464" clip-path="url(#terminal-464155386-line-20)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text class="terminal-464155386-r2" x="1464" y="508" textLength="12.2" clip-path="url(#terminal-464155386-line-20)">
 </text>
     </g>
     </g>