Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions .github/workflows/build-cli-e2e-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Builds CLI E2E images shared across split test jobs.
# Podman uses a separate privileged runtime path and is intentionally left on its
# existing per-job Dockerfile path.
name: Build CLI E2E Docker Image

on:
workflow_call:
inputs:
includePolyglotImages:
required: false
type: boolean
default: true

env:
CLI_E2E_DOTNET_IMAGE_ARTIFACT: cli-e2e-dotnet-image
CLI_E2E_DOTNET_IMAGE_TAG: aspire-cli-e2e-dotnet:prebuilt
CLI_E2E_DOTNET_IMAGE_CACHE_SCOPE: cli-e2e-dotnet
CLI_E2E_POLYGLOT_IMAGE_ARTIFACT: cli-e2e-polyglot-image
CLI_E2E_POLYGLOT_IMAGE_TAG: aspire-cli-e2e-polyglot:prebuilt
CLI_E2E_POLYGLOT_JAVA_IMAGE_ARTIFACT: cli-e2e-polyglot-java-image
CLI_E2E_POLYGLOT_JAVA_IMAGE_TAG: aspire-cli-e2e-polyglot-java:prebuilt
CLI_E2E_POLYGLOT_BASE_IMAGE_TAG: aspire-e2e-polyglot-base:latest
CLI_E2E_POLYGLOT_BASE_IMAGE_CACHE_SCOPE: cli-e2e-polyglot-base
CLI_E2E_INCLUDE_POLYGLOT_IMAGES: ${{ inputs.includePolyglotImages }}
Comment thread
sebastienros marked this conversation as resolved.

jobs:
build:
name: Build CLI E2E Docker image
runs-on: ${{ github.repository_owner == 'microsoft' && '8-core-ubuntu-latest' || 'ubuntu-latest' }}
timeout-minutes: 45

steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Verify Docker is running
run: docker info
Comment thread
sebastienros marked this conversation as resolved.

- name: Export GitHub Actions cache runtime
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
for (const name of ['ACTIONS_RUNTIME_TOKEN', 'ACTIONS_RUNTIME_URL', 'ACTIONS_CACHE_URL', 'ACTIONS_RESULTS_URL']) {
const value = process.env[name];
if (value) {
core.setSecret(value);
core.exportVariable(name, value);
}
}

- name: Build CLI E2E Docker image
shell: bash
run: |
set -euo pipefail

docker buildx create --name cli-e2e-builder --use
docker buildx inspect --bootstrap

build_image() {
local display_name="$1"
local dockerfile="$2"
local tag="$3"
local cache_scope="$4"
local mirror="$5"
local -a build_args=(--build-arg SKIP_SOURCE_BUILD=true)

if [[ -n "$mirror" ]]; then
echo "Building $display_name with Ubuntu apt mirror: $mirror"
build_args+=(--build-arg "UBUNTU_APT_MIRROR=$mirror")
else
echo "Building $display_name with the default Ubuntu apt sources"
fi

docker buildx build \
--load \
--cache-from "type=gha,scope=$cache_scope" \
Comment thread
sebastienros marked this conversation as resolved.
--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")
else
echo "Building Java polyglot image with the default Ubuntu apt sources"
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() {
local display_name="$1"
local dockerfile="$2"
local tag="$3"
local cache_scope="$4"

if ! build_image "$display_name" "$dockerfile" "$tag" "$cache_scope" "http://azure.archive.ubuntu.com/ubuntu/"; then
echo "$display_name build failed with the Azure Ubuntu apt mirror; retrying with default Ubuntu apt sources"
build_image "$display_name" "$dockerfile" "$tag" "$cache_scope" ""
fi
}

build_with_mirror_retry ".NET image" "tests/Shared/Docker/Dockerfile.e2e" "$CLI_E2E_DOTNET_IMAGE_TAG" "$CLI_E2E_DOTNET_IMAGE_CACHE_SCOPE"

if [[ "$CLI_E2E_INCLUDE_POLYGLOT_IMAGES" == "true" ]]; then
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
fi

mkdir -p artifacts/cli-e2e-image
docker save "$CLI_E2E_DOTNET_IMAGE_TAG" | gzip > artifacts/cli-e2e-image/aspire-cli-e2e-dotnet.tar.gz
if [[ "$CLI_E2E_INCLUDE_POLYGLOT_IMAGES" == "true" ]]; then
docker save "$CLI_E2E_POLYGLOT_IMAGE_TAG" | gzip > artifacts/cli-e2e-image/aspire-cli-e2e-polyglot.tar.gz
docker save "$CLI_E2E_POLYGLOT_JAVA_IMAGE_TAG" | gzip > artifacts/cli-e2e-image/aspire-cli-e2e-polyglot-java.tar.gz
fi

- name: Upload CLI E2E .NET Docker image
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.CLI_E2E_DOTNET_IMAGE_ARTIFACT }}
path: artifacts/cli-e2e-image/aspire-cli-e2e-dotnet.tar.gz
retention-days: 1

- name: Upload CLI E2E polyglot Docker image
if: ${{ inputs.includePolyglotImages }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.CLI_E2E_POLYGLOT_IMAGE_ARTIFACT }}
path: artifacts/cli-e2e-image/aspire-cli-e2e-polyglot.tar.gz
retention-days: 1

- name: Upload CLI E2E Java Docker image
if: ${{ inputs.includePolyglotImages }}
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.CLI_E2E_POLYGLOT_JAVA_IMAGE_ARTIFACT }}
path: artifacts/cli-e2e-image/aspire-cli-e2e-polyglot-java.tar.gz
retention-days: 1
57 changes: 56 additions & 1 deletion .github/workflows/reproduce-flaky-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.generate.outputs.matrix }}
is_cli_e2e: ${{ steps.detect_cli_e2e.outputs.is_cli_e2e }}
steps:
- name: Validate configuration
shell: bash
Expand Down Expand Up @@ -89,6 +90,16 @@ jobs:

if [[ $ERRORS -ne 0 ]]; then exit 1; fi

- name: Detect CLI E2E project
id: detect_cli_e2e
shell: bash
run: |
if [ "${{ env.TEST_PROJECT }}" = "Cli.EndToEnd" ]; then
echo "is_cli_e2e=true" >> "$GITHUB_OUTPUT"
else
echo "is_cli_e2e=false" >> "$GITHUB_OUTPUT"
fi

- name: Generate runner matrix
id: generate
shell: bash
Expand All @@ -113,9 +124,21 @@ jobs:
echo "Each runner will execute ${{ env.ITERATIONS_PER_RUNNER }} iterations"
echo "Total test executions: $(( TOTAL * ${{ env.ITERATIONS_PER_RUNNER }} ))"

build_cli_e2e_image:
name: Build CLI E2E Docker image
needs: setup
if: ${{ needs.setup.outputs.is_cli_e2e == 'true' }}
uses: ./.github/workflows/build-cli-e2e-image.yml

reproduce:
name: "${{ matrix.os }} #${{ matrix.index }}"
needs: setup
needs: [setup, build_cli_e2e_image]
if: >-
${{
!cancelled() &&
needs.setup.result == 'success' &&
(needs.build_cli_e2e_image.result == 'success' || needs.build_cli_e2e_image.result == 'skipped')
}}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
Expand Down Expand Up @@ -158,6 +181,38 @@ jobs:
if: runner.os == 'Linux'
run: docker info

- name: Download prebuilt CLI E2E Docker image
if: ${{ needs.setup.outputs.is_cli_e2e == 'true' && runner.os == 'Linux' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-dotnet-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Download prebuilt CLI E2E Java Docker image
if: ${{ needs.setup.outputs.is_cli_e2e == 'true' && runner.os == 'Linux' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-polyglot-java-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Download prebuilt CLI E2E polyglot Docker image
if: ${{ needs.setup.outputs.is_cli_e2e == 'true' && runner.os == 'Linux' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-polyglot-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Load prebuilt CLI E2E Docker image
if: ${{ needs.setup.outputs.is_cli_e2e == 'true' && runner.os == 'Linux' }}
shell: bash
run: |
set -euo pipefail
eng/scripts/load-cli-e2e-images.sh \
--image-dir "${{ github.workspace }}/cli-e2e-image" \
--require-dotnet true \
--require-polyglot true \
--require-java true

- name: Unlock macOS keychain
if: runner.os == 'macOS'
uses: ./.github/actions/unlock-macos-keychain
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,38 @@ jobs:
if: runner.os == 'Linux'
run: docker info

- name: Download prebuilt CLI E2E Docker image
if: ${{ fromJson(inputs.properties).requiresCliArchive == true && runner.os == 'Linux' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-dotnet-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Download prebuilt CLI E2E polyglot Docker image
if: ${{ fromJson(inputs.properties).requiresCliArchive == true && runner.os == 'Linux' }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-polyglot-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Download prebuilt CLI E2E Java Docker image
if: ${{ fromJson(inputs.properties).requiresCliArchive == true && runner.os == 'Linux' && contains(inputs.testShortName, 'Java') }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-polyglot-java-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Load prebuilt CLI E2E Docker images
Comment thread
sebastienros marked this conversation as resolved.
if: ${{ fromJson(inputs.properties).requiresCliArchive == true && runner.os == 'Linux' }}
shell: bash
run: |
set -euo pipefail
eng/scripts/load-cli-e2e-images.sh \
--image-dir "${{ github.workspace }}/cli-e2e-image" \
--require-dotnet true \
--require-polyglot true \
--require-java "${{ contains(inputs.testShortName, 'Java') }}"

- name: Download built nugets
if: ${{ fromJson(inputs.properties).requiresNugets == true }}
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
Expand Down
15 changes: 12 additions & 3 deletions .github/workflows/specialized-test-runner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,15 @@ jobs:
if: ${{ github.repository_owner == 'microsoft' && (needs.generate_tests_matrix.outputs.requiresNugets == 'true' || needs.generate_tests_matrix.outputs.requiresCliArchive == 'true') }}
uses: ./.github/workflows/build-cli-native-archives.yml

build_cli_e2e_image:
name: Build CLI E2E Docker image
needs: [generate_tests_matrix]
if: ${{ github.repository_owner == 'microsoft' && needs.generate_tests_matrix.outputs.requiresCliArchive == 'true' }}
uses: ./.github/workflows/build-cli-e2e-image.yml

run_tests:
name: ${{ matrix.tests.project }}
needs: [generate_tests_matrix, build_packages, build_cli_archives]
needs: [generate_tests_matrix, build_packages, build_cli_archives, build_cli_e2e_image]
strategy:
fail-fast: false
matrix:
Expand All @@ -156,7 +162,8 @@ jobs:
github.repository_owner == 'microsoft' &&
!cancelled() &&
needs.generate_tests_matrix.result == 'success' &&
(needs.build_packages.result == 'success' || needs.build_packages.result == 'skipped')
(needs.build_packages.result == 'success' || needs.build_packages.result == 'skipped') &&
(needs.build_cli_e2e_image.result == 'success' || needs.build_cli_e2e_image.result == 'skipped')
}}
uses: ./.github/workflows/run-tests.yml
with:
Expand All @@ -172,7 +179,7 @@ jobs:
if: ${{ always() && github.repository_owner == 'microsoft' }}
runs-on: ubuntu-latest
name: Final Results
needs: [generate_tests_matrix, build_packages, build_cli_archives, run_tests]
needs: [generate_tests_matrix, build_packages, build_cli_archives, build_cli_e2e_image, run_tests]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Expand Down Expand Up @@ -244,6 +251,8 @@ jobs:
needs.run_tests.result == 'failure' ||
needs.run_tests.result == 'cancelled' ||
needs.run_tests.result == 'skipped' ||
(needs.build_cli_e2e_image.result == 'failure') ||
(needs.build_cli_e2e_image.result == 'cancelled') ||
(needs.build_packages.result == 'failure') ||
(needs.build_packages.result == 'cancelled')
)
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/tests-daily-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,15 @@ permissions:
contents: read

jobs:
build_cli_e2e_image:
name: Build CLI E2E Docker image
uses: ./.github/workflows/build-cli-e2e-image.yml
with:
includePolyglotImages: false

smoke-test:
name: CLI Smoke Test (${{ inputs.quality || 'dev' }})
needs: build_cli_e2e_image
runs-on: ubuntu-latest
timeout-minutes: 30

Expand All @@ -45,6 +52,23 @@ jobs:
- name: Restore
run: ./restore.sh

- name: Verify Docker is running
run: docker info

- name: Download prebuilt CLI E2E Docker image
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: cli-e2e-dotnet-image
path: ${{ github.workspace }}/cli-e2e-image

- name: Load prebuilt CLI E2E Docker image
shell: bash
run: |
set -euo pipefail
eng/scripts/load-cli-e2e-images.sh \
--image-dir "${{ github.workspace }}/cli-e2e-image" \
--require-dotnet true

- name: Build E2E test project
run: dotnet build tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj

Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/tests-outerloop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#
# COPILOT INSTRUCTIONS:
# - Keep the shared 'paths:' entries (specialized-test-runner.yml,
# run-tests.yml) in sync across tests-outerloop.yml and
# tests-quarantine.yml. Each workflow also lists itself.
# run-tests.yml, build-cli-e2e-image.yml) in sync across
# tests-outerloop.yml and tests-quarantine.yml. Each workflow also lists itself.
# - Validate that each path exists in the repository before adding or
# updating the list
# - No external YAML file is used—only the workflow YAMLs themselves
Expand All @@ -28,6 +28,7 @@ on:
- '.github/workflows/tests-outerloop.yml'
- '.github/workflows/specialized-test-runner.yml'
- '.github/workflows/run-tests.yml'
- '.github/workflows/build-cli-e2e-image.yml'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
Loading
Loading