diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a2ebe2389..56e099b101 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,6 +8,99 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true permissions: {} + +x-e2e-server-job: &e2e-server-job + needs: [pre-job, build-e2e-images] + if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true }} + runs-on: ${{ matrix.runner }} + permissions: + contents: read + defaults: + run: + working-directory: ./e2e + strategy: + matrix: + runner: [ubuntu-latest, ubuntu-24.04-arm] + +x-e2e-web-job: &e2e-web-job + needs: [pre-job, build-e2e-images] + if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).web == true }} + runs-on: ${{ matrix.runner }} + permissions: + contents: read + defaults: + run: + working-directory: ./e2e + strategy: + matrix: + runner: [ubuntu-latest, ubuntu-24.04-arm] + +x-e2e-steps: + token: &e2e-token-step + id: token + uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1 + with: + app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} + private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} + checkout: &e2e-checkout-step + name: Checkout code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + submodules: 'recursive' + token: ${{ steps.token.outputs.token }} + setup-pnpm: &e2e-setup-pnpm-step + name: Setup pnpm + uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 + setup-node: &e2e-setup-node-step + name: Setup Node + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version-file: './e2e/.nvmrc' + cache: 'pnpm' + cache-dependency-path: '**/pnpm-lock.yaml' + setup-sdk: &e2e-setup-sdk-step + name: Run setup typescript-sdk + run: pnpm install --frozen-lockfile && pnpm build + working-directory: ./open-api/typescript-sdk + if: ${{ !cancelled() }} + setup-web: &e2e-setup-web-step + name: Run setup web + run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync + working-directory: ./web + if: ${{ !cancelled() }} + setup-cli: &e2e-setup-cli-step + name: Run setup cli + run: pnpm install --frozen-lockfile && pnpm build + working-directory: ./cli + if: ${{ !cancelled() }} + install-deps: &e2e-install-deps-step + name: Install dependencies + run: pnpm install --frozen-lockfile + if: ${{ !cancelled() }} + install-playwright: &e2e-install-playwright-step + name: Install Playwright Browsers + run: pnpm exec playwright install chromium --only-shell + if: ${{ !cancelled() }} + download-images: &e2e-download-images-step + name: Download Docker images + uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 + with: + name: docker-images-${{ matrix.runner }} + path: e2e + load-images: &e2e-load-images-step + name: Load Docker images + run: docker load < docker-images.tar.gz + docker-compose-up: &e2e-docker-compose-up-step + name: Start Docker Compose + run: docker compose up -d --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300 + if: ${{ !cancelled() }} + capture-docker-logs: &e2e-capture-docker-logs-step + name: Capture Docker logs + if: always() + run: docker compose logs --no-color > docker-compose-logs.txt + working-directory: ./e2e + jobs: pre-job: runs-on: ubuntu-latest @@ -397,10 +490,10 @@ jobs: - name: Run medium tests run: pnpm test:medium if: ${{ !cancelled() }} - e2e-tests-server-cli: - name: End-to-End Tests (Server & CLI) + build-e2e-images: + name: Build E2E Docker Images needs: pre-job - if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true }} + if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).server == true || fromJSON(needs.pre-job.outputs.should_run).cli == true || fromJSON(needs.pre-job.outputs.should_run).web == true }} runs-on: ${{ matrix.runner }} permissions: contents: read @@ -411,111 +504,86 @@ jobs: matrix: runner: [ubuntu-latest, ubuntu-24.04-arm] steps: - - id: token - uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1 + - *e2e-token-step + - *e2e-checkout-step + - name: Build Docker images + run: docker compose build + - name: Save Docker images + run: docker save immich-server:latest immich-e2e-e2e-auth-server | gzip > docker-images.tar.gz + - name: Upload Docker images + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: - app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} - private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} - - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - submodules: 'recursive' - token: ${{ steps.token.outputs.token }} - - name: Setup pnpm - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 - - name: Setup Node - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version-file: './e2e/.nvmrc' - cache: 'pnpm' - cache-dependency-path: '**/pnpm-lock.yaml' - - name: Run setup typescript-sdk - run: pnpm install --frozen-lockfile && pnpm build - working-directory: ./open-api/typescript-sdk - if: ${{ !cancelled() }} - - name: Run setup web - run: pnpm install --frozen-lockfile && pnpm exec svelte-kit sync - working-directory: ./web - if: ${{ !cancelled() }} - - name: Run setup cli - run: pnpm install --frozen-lockfile && pnpm build - working-directory: ./cli - if: ${{ !cancelled() }} - - name: Install dependencies - run: pnpm install --frozen-lockfile - if: ${{ !cancelled() }} - - name: Start Docker Compose - run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300 - if: ${{ !cancelled() }} + name: docker-images-${{ matrix.runner }} + path: e2e/docker-images.tar.gz + retention-days: 1 + e2e-tests-server-cli: + <<: *e2e-server-job + name: End-to-End Tests (Server & CLI) + steps: + - *e2e-token-step + - *e2e-checkout-step + - *e2e-setup-pnpm-step + - *e2e-setup-node-step + - *e2e-setup-sdk-step + - *e2e-setup-web-step + - *e2e-setup-cli-step + - *e2e-install-deps-step + - *e2e-download-images-step + - *e2e-load-images-step + - *e2e-docker-compose-up-step - name: Run e2e tests (api & cli) env: VITEST_DISABLE_DOCKER_SETUP: true run: pnpm test if: ${{ !cancelled() }} - - name: Run e2e tests (maintenance) - env: - VITEST_DISABLE_DOCKER_SETUP: true - run: pnpm test:maintenance - if: ${{ !cancelled() }} - - name: Capture Docker logs - if: always() - run: docker compose logs --no-color > docker-compose-logs.txt - working-directory: ./e2e + - *e2e-capture-docker-logs-step - name: Archive Docker logs uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 if: always() with: name: e2e-server-docker-logs-${{ matrix.runner }} path: e2e/docker-compose-logs.txt - e2e-tests-web: - name: End-to-End Tests (Web) - needs: pre-job - if: ${{ fromJSON(needs.pre-job.outputs.should_run).e2e == true || fromJSON(needs.pre-job.outputs.should_run).web == true }} - runs-on: ${{ matrix.runner }} - permissions: - contents: read - defaults: - run: - working-directory: ./e2e - strategy: - matrix: - runner: [ubuntu-latest, ubuntu-24.04-arm] + e2e-tests-server-maintenance: + <<: *e2e-server-job + name: End-to-End Tests (Server Maintenance) steps: - - id: token - uses: immich-app/devtools/actions/create-workflow-token@05e16407c0a5492138bb38139c9d9bf067b40886 # create-workflow-token-action-v1.0.1 + - *e2e-token-step + - *e2e-checkout-step + - *e2e-setup-pnpm-step + - *e2e-setup-node-step + - *e2e-setup-sdk-step + - *e2e-setup-web-step + - *e2e-setup-cli-step + - *e2e-install-deps-step + - *e2e-download-images-step + - *e2e-load-images-step + - *e2e-docker-compose-up-step + - name: Run e2e tests (maintenance) + env: + VITEST_DISABLE_DOCKER_SETUP: true + run: pnpm test:maintenance + if: ${{ !cancelled() }} + - *e2e-capture-docker-logs-step + - name: Archive Docker logs + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + if: always() with: - app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} - private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} - - - name: Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - persist-credentials: false - submodules: 'recursive' - token: ${{ steps.token.outputs.token }} - - name: Setup pnpm - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 - - name: Setup Node - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 - with: - node-version-file: './e2e/.nvmrc' - cache: 'pnpm' - cache-dependency-path: '**/pnpm-lock.yaml' - - name: Run setup typescript-sdk - run: pnpm install --frozen-lockfile && pnpm build - working-directory: ./open-api/typescript-sdk - if: ${{ !cancelled() }} - - name: Install dependencies - run: pnpm install --frozen-lockfile - if: ${{ !cancelled() }} - - name: Install Playwright Browsers - run: pnpm exec playwright install chromium --only-shell - if: ${{ !cancelled() }} - - name: Docker build - run: docker compose up -d --build --renew-anon-volumes --force-recreate --remove-orphans --wait --wait-timeout 300 - if: ${{ !cancelled() }} + name: e2e-server-maintenance-docker-logs-${{ matrix.runner }} + path: e2e/docker-compose-logs.txt + e2e-tests-web: + <<: *e2e-web-job + name: End-to-End Tests (Web) + steps: + - *e2e-token-step + - *e2e-checkout-step + - *e2e-setup-pnpm-step + - *e2e-setup-node-step + - *e2e-setup-sdk-step + - *e2e-install-deps-step + - *e2e-install-playwright-step + - *e2e-download-images-step + - *e2e-load-images-step + - *e2e-docker-compose-up-step - name: Run e2e tests (web) env: PLAYWRIGHT_DISABLE_WEBSERVER: true @@ -527,6 +595,27 @@ jobs: with: name: e2e-web-test-results-${{ matrix.runner }} path: e2e/playwright-report/ + - *e2e-capture-docker-logs-step + - name: Archive Docker logs + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + if: always() + with: + name: e2e-web-docker-logs-${{ matrix.runner }} + path: e2e/docker-compose-logs.txt + e2e-tests-web-ui: + <<: *e2e-web-job + name: End-to-End Tests (Web UI) + steps: + - *e2e-token-step + - *e2e-checkout-step + - *e2e-setup-pnpm-step + - *e2e-setup-node-step + - *e2e-setup-sdk-step + - *e2e-install-deps-step + - *e2e-install-playwright-step + - *e2e-download-images-step + - *e2e-load-images-step + - *e2e-docker-compose-up-step - name: Run ui tests (web) env: PLAYWRIGHT_DISABLE_WEBSERVER: true @@ -538,6 +627,27 @@ jobs: with: name: e2e-ui-test-results-${{ matrix.runner }} path: e2e/playwright-report/ + - *e2e-capture-docker-logs-step + - name: Archive Docker logs + uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 + if: always() + with: + name: e2e-web-ui-docker-logs-${{ matrix.runner }} + path: e2e/docker-compose-logs.txt + e2e-tests-web-maintenance: + <<: *e2e-web-job + name: End-to-End Tests (Web Maintenance) + steps: + - *e2e-token-step + - *e2e-checkout-step + - *e2e-setup-pnpm-step + - *e2e-setup-node-step + - *e2e-setup-sdk-step + - *e2e-install-deps-step + - *e2e-install-playwright-step + - *e2e-download-images-step + - *e2e-load-images-step + - *e2e-docker-compose-up-step - name: Run maintenance tests env: PLAYWRIGHT_DISABLE_WEBSERVER: true @@ -549,19 +659,16 @@ jobs: with: name: e2e-maintenance-isolated-test-results-${{ matrix.runner }} path: e2e/playwright-report/ - - name: Capture Docker logs - if: always() - run: docker compose logs --no-color > docker-compose-logs.txt - working-directory: ./e2e + - *e2e-capture-docker-logs-step - name: Archive Docker logs uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 if: always() with: - name: e2e-web-docker-logs-${{ matrix.runner }} + name: e2e-web-maintenance-docker-logs-${{ matrix.runner }} path: e2e/docker-compose-logs.txt success-check-e2e: name: End-to-End Tests Success - needs: [e2e-tests-server-cli, e2e-tests-web] + needs: [e2e-tests-server-cli, e2e-tests-server-maintenance, e2e-tests-web, e2e-tests-web-ui, e2e-tests-web-maintenance] permissions: {} runs-on: ubuntu-latest if: always()