name: E2E tests # yamllint disable-line rule:truthy on: workflow_dispatch: inputs: version: description: "Image tag or digest to test (e.g. dev, 2026.7.1, 2026.8.0b0, sha256:0a1b2c3d…)" default: "dev" required: true image_prefixes: description: "JSON array of image prefixes to test. Will be prefixed to `-homeassistant`" default: >- ["generic-x86-64", "khadas-vim3", "odroid-c2", "odroid-c4", "odroid-m1", "odroid-n2", "qemuarm-64", "qemux86-64", "raspberrypi3-64", "raspberrypi4-64", "raspberrypi5-64", "yellow", "green"] required: true workflow_call: inputs: version: description: "Image tag or digest to test (e.g. dev, 2026.7.1, 2026.8.0b0, sha256:0a1b2c3d…)" required: true type: string image_prefixes: description: "JSON array of image prefixes to test. Will be prefixed to `-homeassistant`" required: true type: string permissions: {} concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.version }}-${{ inputs.image_prefixes }} cancel-in-progress: true jobs: boot_check: name: Boot check ${{ matrix.image_prefix }} image if: github.repository_owner == 'home-assistant' # amd64 images need an x86 runner; all others are aarch64 runs-on: ${{ contains(fromJson('["amd64", "generic-x86-64", "qemux86-64"]'), matrix.image_prefix) && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }} timeout-minutes: 20 strategy: fail-fast: false matrix: image_prefix: ${{ fromJson(inputs.image_prefixes) }} env: BASE_URL: http://localhost:8123 services: homeassistant: # Digests are referenced with '@', tags with ':' image: ghcr.io/home-assistant/${{ matrix.image_prefix }}-homeassistant${{ startsWith(inputs.version, 'sha256:') && '@' || ':' }}${{ inputs.version }} # zizmor: ignore[unpinned-images] ports: - 8123:8123 # Gate steps until Home Assistant answers (60 x 5s ≈ 300s startup budget) options: >- --health-cmd="curl --fail --silent --max-time 10 --output /dev/null http://127.0.0.1:8123/" --health-start-period=10s --health-interval=5s --health-retries=60 steps: - name: Check out code from GitHub uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Set up pnpm uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 with: package_json_file: tests/e2e/package.json - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: "24" cache: pnpm cache-dependency-path: tests/e2e/pnpm-lock.yaml - name: Install E2E test dependencies working-directory: tests/e2e run: pnpm install --frozen-lockfile - name: Install Playwright browser working-directory: tests/e2e run: pnpm exec playwright install --with-deps chromium - name: Run Playwright E2E tests working-directory: tests/e2e run: pnpm exec playwright test - name: Upload Playwright report if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: playwright-report-${{ matrix.image_prefix }} path: | tests/e2e/playwright-report/ tests/e2e/test-results/ - name: Dump container logs if: always() env: CONTAINER: ${{ job.services.homeassistant.id }} run: docker logs "$CONTAINER" > homeassistant.log 2>&1 || true - name: Upload container logs if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: container-logs-${{ matrix.image_prefix }} path: homeassistant.log