Repository: bitcoin/bitcoin
File: ci/test/02_run_container.py (Python)

Code before:
            f"--label={CI_IMAGE_LABEL}",
            f"--tag={os.environ['CONTAINER_NAME']}",
        ]
        cmd_build += shlex.split(os.getenv("DOCKER_BUILD_CACHE_ARG", ""))
        cmd_build += [os.environ["BASE_READ_ONLY_DIR"]]

        print(f"Building {os.environ['CONTAINER_NAME']} image tag to run in")
        if run(cmd_build, check=False).returncode != 0:
            print(f"Retry building {os.environ['CONTAINER_NAME']} image tag after failure")
            time.sleep(3)
            run(cmd_build)

        run(["docker", "volume", "create", f"{os.environ['CONTAINER_NAME']}_ccache"], check=False)
        run(["docker", "volume", "create", f"{os.environ['CONTAINER_NAME']}_depends"], check=False)
        run(["docker", "volume", "create", f"{os.environ['CONTAINER_NAME']}_depends_sources"], check=False)
        run(["docker", "volume", "create", f"{os.environ['CONTAINER_NAME']}_previous_releases"], check=False)

        CI_CCACHE_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_ccache,dst={os.environ['CCACHE_DIR']}"
        CI_DEPENDS_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_depends,dst={os.environ['DEPENDS_DIR']}/built"
        CI_DEPENDS_SOURCES_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_depends_sources,dst={os.environ['DEPENDS_DIR']}/sources"
        CI_PREVIOUS_RELEASES_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_previous_releases,dst={os.environ['PREVIOUS_RELEASES_DIR']}"
        CI_BUILD_MOUNT = []

        if os.getenv("DANGER_CI_ON_HOST_FOLDERS"):
            # ensure the directories exist
            run(["mkdir", "-p", os.environ["CCACHE_DIR"]])
            run(["mkdir", "-p", f"{os.environ['DEPENDS_DIR']}/built"])
            run(["mkdir", "-p", f"{os.environ['DEPENDS_DIR']}/sources"])
            run(["mkdir", "-p", os.environ["PREVIOUS_RELEASES_DIR"]])
            run(["mkdir", "-p", os.environ["BASE_BUILD_DIR"]])  # Unset by default, must be defined externally

            CI_CCACHE_MOUNT = f"type=bind,src={os.environ['CCACHE_DIR']},dst={os.environ['CCACHE_DIR']}"
            CI_DEPENDS_MOUNT = f"type=bind,src={os.environ['DEPENDS_DIR']}/built,dst={os.environ['DEPENDS_DIR']}/built"
            CI_DEPENDS_SOURCES_MOUNT = f"type=bind,src={os.environ['DEPENDS_DIR']}/sources,dst={os.environ['DEPENDS_DIR']}/sources"
            CI_PREVIOUS_RELEASES_MOUNT = f"type=bind,src={os.environ['PREVIOUS_RELEASES_DIR']},dst={os.environ['PREVIOUS_RELEASES_DIR']}"
            CI_BUILD_MOUNT = [f"--mount=type=bind,src={os.environ['BASE_BUILD_DIR']},dst={os.environ['BASE_BUILD_DIR']}"]

        if os.getenv("DANGER_CI_ON_HOST_CCACHE_FOLDER"):
            if not os.path.isdir(os.environ["CCACHE_DIR"]):
                print(f"Error: Directory '{os.environ['CCACHE_DIR']}' must be created in advance.")
                sys.exit(1)
            CI_CCACHE_MOUNT = f"type=bind,src={os.environ['CCACHE_DIR']},dst={os.environ['CCACHE_DIR']}"

        run(["docker", "network", "create", "--ipv6", "--subnet", "1111:1111::/112", "ci-ip6net"], check=False)

        if os.getenv("RESTART_CI_DOCKER_BEFORE_RUN"):
            print("Restart docker before run to stop and clear all containers started with --rm")
            run(["podman", "container", "rm", "--force", "--all"])  # Similar to "systemctl restart docker"

            # Still prune everything in case the filtered pruning doesn't work, or if labels were not set
            # on a previous run. Belt and suspenders approach, should be fine to remove in the future.

Review comment (performance):
https://man7.org/linux/man-pages/man1/mkdir.1.html seems to support batch creation so maybe we can reduce the noise a bit:
```python
run([
    "mkdir", "-p",
    os.environ["CCACHE_DIR"],
    f"{os.environ['DEPENDS_DIR']}/built",
    f"{os.environ['DEPENDS_DIR']}/sources",
    os.environ["PREVIOUS_RELEASES_DIR"],
    os.environ["BASE_BUILD_DIR"],  # Unset by default, must be defined externally
])
```

But Python does support native folder creation, not sure we should delegate to bash here:
```python
for p in [
    os.environ["CCACHE_DIR"],
    f"{os.environ['DEPENDS_DIR']}/built",
    f"{os.environ['DEPENDS_DIR']}/sources",
    os.environ["PREVIOUS_RELEASES_DIR"],
    os.environ["BASE_BUILD_DIR"],   # Unset by default, must be defined externally
]:
    Path(p).mkdir(parents=True, exist_ok=True)
```

Code after:
            f"--platform={os.environ['CI_IMAGE_PLATFORM']}",
            f"--label={CI_IMAGE_LABEL}",
            f"--tag={os.environ['CONTAINER_NAME']}",
        ]
        cmd_build += shlex.split(os.getenv("DOCKER_BUILD_CACHE_ARG", ""))
        cmd_build += [os.environ["BASE_READ_ONLY_DIR"]]

        print(f"Building {os.environ['CONTAINER_NAME']} image tag to run in")
        if run(cmd_build, check=False).returncode != 0:
            print(f"Retry building {os.environ['CONTAINER_NAME']} image tag after failure")
            time.sleep(3)
            run(cmd_build)

        for suffix in ["ccache", "depends", "depends_sources", "previous_releases"]:
            run(["docker", "volume", "create", f"{os.environ['CONTAINER_NAME']}_{suffix}"], check=False)

        CI_CCACHE_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_ccache,dst={os.environ['CCACHE_DIR']}"
        CI_DEPENDS_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_depends,dst={os.environ['DEPENDS_DIR']}/built"
        CI_DEPENDS_SOURCES_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_depends_sources,dst={os.environ['DEPENDS_DIR']}/sources"
        CI_PREVIOUS_RELEASES_MOUNT = f"type=volume,src={os.environ['CONTAINER_NAME']}_previous_releases,dst={os.environ['PREVIOUS_RELEASES_DIR']}"
        CI_BUILD_MOUNT = []

        if os.getenv("DANGER_CI_ON_HOST_FOLDERS"):
            # ensure the directories exist
            for create_dir in [
                    os.environ["CCACHE_DIR"],
                    f"{os.environ['DEPENDS_DIR']}/built",
                    f"{os.environ['DEPENDS_DIR']}/sources",
                    os.environ["PREVIOUS_RELEASES_DIR"],
                    os.environ["BASE_BUILD_DIR"],  # Unset by default, must be defined externally
            ]:
                Path(create_dir).mkdir(parents=True, exist_ok=True)

            CI_CCACHE_MOUNT = f"type=bind,src={os.environ['CCACHE_DIR']},dst={os.environ['CCACHE_DIR']}"
            CI_DEPENDS_MOUNT = f"type=bind,src={os.environ['DEPENDS_DIR']}/built,dst={os.environ['DEPENDS_DIR']}/built"
            CI_DEPENDS_SOURCES_MOUNT = f"type=bind,src={os.environ['DEPENDS_DIR']}/sources,dst={os.environ['DEPENDS_DIR']}/sources"
            CI_PREVIOUS_RELEASES_MOUNT = f"type=bind,src={os.environ['PREVIOUS_RELEASES_DIR']},dst={os.environ['PREVIOUS_RELEASES_DIR']}"
            CI_BUILD_MOUNT = [f"--mount=type=bind,src={os.environ['BASE_BUILD_DIR']},dst={os.environ['BASE_BUILD_DIR']}"]

        if os.getenv("DANGER_CI_ON_HOST_CCACHE_FOLDER"):
            if not os.path.isdir(os.environ["CCACHE_DIR"]):
                print(f"Error: Directory '{os.environ['CCACHE_DIR']}' must be created in advance.")
                sys.exit(1)
            CI_CCACHE_MOUNT = f"type=bind,src={os.environ['CCACHE_DIR']},dst={os.environ['CCACHE_DIR']}"

        run(["docker", "network", "create", "--ipv6", "--subnet", "1111:1111::/112", "ci-ip6net"], check=False)

        if os.getenv("RESTART_CI_DOCKER_BEFORE_RUN"):
            print("Restart docker before run to stop and clear all containers started with --rm")
            run(["podman", "container", "rm", "--force", "--all"])  # Similar to "systemctl restart docker"