diff --git a/.github/actions/verify-docker/action.yml b/.github/actions/verify-docker/action.yml new file mode 100644 index 00000000000..94a020d439a --- /dev/null +++ b/.github/actions/verify-docker/action.yml @@ -0,0 +1,20 @@ +name: 'Verify Docker' +description: 'Verify that the runner Docker daemon is available and emit Docker/buildx version diagnostics. No-op on non-Linux runners.' +runs: + using: "composite" + steps: + - name: Verify Docker daemon and emit diagnostics + # Aspire CI only relies on Docker on Linux runners; the macOS and Windows + # GitHub-hosted runners don't have a working Docker daemon. Skip there so + # callers don't need to repeat `if: runner.os == 'Linux'` at every call site. + if: runner.os == 'Linux' + shell: bash + run: | + # Run docker info first as the gating check, but never let it short-circuit + # the diagnostics that follow — those are most useful when the daemon is + # broken. Re-raise its exit code at the end so the step still fails. + rc=0 + docker info || rc=$? + docker version || echo "::warning::docker version failed with exit code $?" + docker buildx version || echo "::warning::docker buildx version failed with exit code $?" + exit $rc diff --git a/.github/workflows/build-cli-e2e-image.yml b/.github/workflows/build-cli-e2e-image.yml index bfd5c5050ae..cd6fa85e661 100644 --- a/.github/workflows/build-cli-e2e-image.yml +++ b/.github/workflows/build-cli-e2e-image.yml @@ -38,7 +38,7 @@ jobs: uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Verify Docker is running - run: docker info + uses: ./.github/actions/verify-docker - name: Export GitHub Actions cache runtime uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 @@ -75,32 +75,29 @@ jobs: echo "Building $display_name with the default Ubuntu apt sources" fi - docker buildx build \ - --load \ - --cache-from "type=gha,scope=$cache_scope" \ - --cache-to "type=gha,scope=$cache_scope,mode=max,ignore-error=true" \ - "${build_args[@]}" \ - -f "$dockerfile" \ - -t "$tag" \ - . - } - - build_java_image() { - local mirror="$1" - local -a build_args=() - - if [[ -n "$mirror" ]]; then - echo "Building Java polyglot image with Ubuntu apt mirror: $mirror" - build_args+=(--build-arg "UBUNTU_APT_MIRROR=$mirror") + if [[ -n "$cache_scope" ]]; then + # Cached path: use the buildx docker-container builder so we can read/write + # BuildKit layers from the GitHub Actions cache. + docker buildx build \ + --load \ + --cache-from "type=gha,scope=$cache_scope" \ + --cache-to "type=gha,scope=$cache_scope,mode=max,ignore-error=true" \ + "${build_args[@]}" \ + -f "$dockerfile" \ + -t "$tag" \ + . else - echo "Building Java polyglot image with the default Ubuntu apt sources" + # Uncached path: build through the default docker daemon driver so the + # image can reference other locally-loaded images via FROM (e.g. the + # polyglot base built earlier in this step). The docker-container buildx + # driver does not have access to the daemon's image store and would try + # to pull such references from a registry. + DOCKER_BUILDKIT=1 docker build \ + "${build_args[@]}" \ + -f "$dockerfile" \ + -t "$tag" \ + . fi - - DOCKER_BUILDKIT=1 docker build \ - "${build_args[@]}" \ - -f tests/Shared/Docker/Dockerfile.e2e-polyglot-java \ - -t "$CLI_E2E_POLYGLOT_JAVA_IMAGE_TAG" \ - . } build_with_mirror_retry() { @@ -121,10 +118,11 @@ jobs: build_with_mirror_retry "polyglot base image" "tests/Shared/Docker/Dockerfile.e2e-polyglot-base" "$CLI_E2E_POLYGLOT_BASE_IMAGE_TAG" "$CLI_E2E_POLYGLOT_BASE_IMAGE_CACHE_SCOPE" docker tag "$CLI_E2E_POLYGLOT_BASE_IMAGE_TAG" "$CLI_E2E_POLYGLOT_IMAGE_TAG" - if ! build_java_image "http://azure.archive.ubuntu.com/ubuntu/"; then - echo "Java polyglot image build failed with the Azure Ubuntu apt mirror; retrying with default Ubuntu apt sources" - build_java_image "" - fi + # The Java polyglot image extends the polyglot base via `FROM + # aspire-e2e-polyglot-base`, which only exists in the local docker daemon. + # Pass an empty cache scope so build_image uses the daemon-backed + # `docker build` path instead of the docker-container buildx driver. + build_with_mirror_retry "Java polyglot image" "tests/Shared/Docker/Dockerfile.e2e-polyglot-java" "$CLI_E2E_POLYGLOT_JAVA_IMAGE_TAG" "" fi - name: Save CLI E2E Docker image tarballs diff --git a/.github/workflows/deployment-tests.yml b/.github/workflows/deployment-tests.yml index dec55080731..0578b7b9346 100644 --- a/.github/workflows/deployment-tests.yml +++ b/.github/workflows/deployment-tests.yml @@ -245,11 +245,7 @@ jobs: echo "✅ Azure authentication successful" - name: Verify Docker is running - run: | - echo "Verifying Docker daemon..." - docker version - docker info | head -20 - echo "✅ Docker is available" + uses: ./.github/actions/verify-docker - name: Run deployment test (${{ matrix.shortname }}) id: run_tests diff --git a/.github/workflows/reproduce-flaky-tests.yml b/.github/workflows/reproduce-flaky-tests.yml index fa46c6f8844..62a38b3a459 100644 --- a/.github/workflows/reproduce-flaky-tests.yml +++ b/.github/workflows/reproduce-flaky-tests.yml @@ -177,9 +177,8 @@ jobs: env: WSL_INTEROP: "" - - name: Verify Docker is running (Linux) - if: runner.os == 'Linux' - run: docker info + - name: Verify Docker is running + uses: ./.github/actions/verify-docker - name: Download prebuilt CLI E2E Docker image if: ${{ needs.setup.outputs.is_cli_e2e == 'true' && runner.os == 'Linux' }} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index f295648f7aa..5232d5dbac6 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -114,9 +114,7 @@ jobs: WSL_INTEROP: "" - name: Verify Docker is running - # nested docker containers not supported on windows - if: runner.os == 'Linux' - run: docker info + uses: ./.github/actions/verify-docker - name: Download prebuilt CLI E2E Docker image if: ${{ fromJson(inputs.properties).requiresCliArchive == true && runner.os == 'Linux' }} diff --git a/.github/workflows/tests-daily-smoke.yml b/.github/workflows/tests-daily-smoke.yml index 62c86da7cf0..06b6a9dbfc8 100644 --- a/.github/workflows/tests-daily-smoke.yml +++ b/.github/workflows/tests-daily-smoke.yml @@ -53,7 +53,7 @@ jobs: run: ./restore.sh - name: Verify Docker is running - run: docker info + uses: ./.github/actions/verify-docker - name: Download prebuilt CLI E2E Docker image uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3a7a5b97e50..1f6f0580a8f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -86,7 +86,6 @@ jobs: name: Build CLI E2E Docker image uses: ./.github/workflows/build-cli-e2e-image.yml needs: setup_for_tests - if: ${{ fromJson(needs.setup_for_tests.outputs.tests_matrix_requires_cli_archive).include[0] != null }} tests_no_nugets: name: ${{ matrix.shortname }} diff --git a/docs/ci/verify-docker.md b/docs/ci/verify-docker.md new file mode 100644 index 00000000000..83e34bdd091 --- /dev/null +++ b/docs/ci/verify-docker.md @@ -0,0 +1,7 @@ +# Verify Docker action + +Workflows that need Docker should use `.github/actions/verify-docker` instead of running `docker info` directly. The action checks that the Docker daemon is reachable with `docker info` and always emits `docker version` and `docker buildx version` so logs are useful when the daemon is broken. + +The action is a no-op on non-Linux runners, so callers can use it unconditionally even from cross-OS jobs — there's no need to gate the step with `if: runner.os == 'Linux'`. + +Extend this action when CI needs a stronger Docker runner contract.