diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 6ef8a30d55a96..1ce938bccbdd2 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -16,6 +16,7 @@ on: - reopened - ready_for_review - labeled + - unlabeled concurrency: group: cypress-${{ github.head_ref || github.run_id }} @@ -38,6 +39,7 @@ permissions: jobs: gate: runs-on: ubuntu-latest-low + name: Fail Crypress tests if labels are missing (force-e2e-tests, 3. to review, or 4. to release) steps: - name: Evaluate e2e tests execution conditions id: gate-e2e @@ -61,7 +63,7 @@ jobs: if (hasForceLabel || hasToReviewLabel || hasToReleaseLabel || cypressTouched) { return } else { - core.setFailed('Skipping Cypress: draft state, missing labels or no cypress path changes.') + core.setFailed('Skipping Cypress: missing required labels (force-e2e-tests, 3. to review, or 4. to release), or no cypress path changes.') } init: @@ -88,7 +90,7 @@ jobs: id: check_composer uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3.1.0 with: - files: 'composer.json' + files: "composer.json" - name: Install composer dependencies if: steps.check_composer.outputs.files_exists == 'true' @@ -98,8 +100,8 @@ jobs: uses: skjnldsv/read-package-engines-version-actions@06d6baf7d8f41934ab630e97d9e6c0bc9c9ac5e4 # v3 id: versions with: - fallbackNode: '^24' - fallbackNpm: '^11.3' + fallbackNode: "^24" + fallbackNpm: "^11.3" - name: Set up node ${{ steps.versions.outputs.nodeVersion }} uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 @@ -141,7 +143,7 @@ jobs: matrix: # Run multiple copies of the current job in parallel # Please increase the number or runners as your tests suite grows (0 based index for e2e tests) - containers: ['setup', '0', '1', '2', '3', '4'] + containers: ["setup", "0", "1", "2", "3", "4"] # Hack as strategy.job-total includes the "setup" and GitHub does not allow math expressions # Always align this number with the total of e2e runners (max. index + 1) total-containers: [5] @@ -151,7 +153,7 @@ jobs: # Only start mysql if we are running the setup tests image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-mysql-8.4:latest' || ''}} # zizmor: ignore[unpinned-images] ports: - - '3306/tcp' + - "3306/tcp" env: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_USER: oc_autotest @@ -163,7 +165,7 @@ jobs: # Only start mariadb if we are running the setup tests image: ${{matrix.containers == 'setup' && 'mariadb:11.4' || ''}} # zizmor: ignore[unpinned-images] ports: - - '3306/tcp' + - "3306/tcp" env: MYSQL_ROOT_PASSWORD: rootpassword MYSQL_USER: oc_autotest @@ -175,7 +177,7 @@ jobs: # Only start postgres if we are running the setup tests image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-postgres-17:latest' || ''}} # zizmor: ignore[unpinned-images] ports: - - '5432/tcp' + - "5432/tcp" env: POSTGRES_USER: root POSTGRES_PASSWORD: rootpassword @@ -186,10 +188,10 @@ jobs: # Only start oracle if we are running the setup tests image: ${{matrix.containers == 'setup' && 'ghcr.io/gvenzl/oracle-free:23' || ''}} # zizmor: ignore[unpinned-images] ports: - - '1521' + - "1521" env: ORACLE_PASSWORD: oracle - options: --health-cmd healthcheck.sh --health-interval 20s --health-timeout 10s --health-retries 10 + options: --health-cmd healthcheck.sh --health-interval 20s --health-timeout 10s --health-retries 10 name: runner ${{ matrix.containers }} @@ -214,7 +216,7 @@ jobs: if: steps.cache.outputs.cache-hit != 'true' uses: andstor/file-existence-action@558493d6c74bf472d87c84eab196434afc2fa029 # v3.1.0 with: - files: 'composer.json' + files: "composer.json" - name: Install composer dependencies if: steps.check_composer.outputs.files_exists == 'true' && steps.cache.outputs.cache-hit != 'true' @@ -289,11 +291,7 @@ jobs: summary: runs-on: ubuntu-latest-low needs: [init, cypress] - - if: always() - name: cypress-summary - steps: - name: Summary status run: if ${{ needs.init.result != 'success' || ( needs.cypress.result != 'success' && needs.cypress.result != 'skipped' ) }}; then exit 1; fi diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 7f36a406a797c..a5ecb5c9fb32f 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -12,6 +12,7 @@ on: - reopened - ready_for_review - labeled + - unlabeled permissions: contents: read @@ -19,6 +20,7 @@ permissions: jobs: gate: runs-on: ubuntu-latest-low + name: Fail Playwright tests if labels are missing (force-e2e-tests, 3. to review, or 4. to release) steps: - name: Evaluate e2e tests execution conditions id: gate-e2e @@ -42,7 +44,7 @@ jobs: if (hasForceLabel || hasToReviewLabel || hasToReleaseLabel || playwrightTouched) { return } else { - core.setFailed('Skipping Playwright: draft state, missing labels or no playwright path changes.') + core.setFailed('Skipping Playwright: missing required labels (force-e2e-tests, 3. to review, or 4. to release), or no playwright path changes.') } playwright-setup: @@ -51,28 +53,28 @@ jobs: runs-on: ubuntu-latest needs: gate steps: - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - with: - persist-credentials: false - submodules: true # for 3rdparty - - name: Read package.json - uses: nextcloud-libraries/parse-package-engines-action@122ae05d4257008180a514e1ddeb0c1b9d094bdd # v0.1.0 - id: versions - - name: Set up node - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: ${{ steps.versions.outputs.node-version }} - - name: Set up npm - run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}' - - name: Install dependencies and build - run: | - npm ci - npm run build --if-present - - name: Save context - uses: buildjet/cache/save@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2 - with: - key: playwright-context-${{ github.run_id }} - path: ./ + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + submodules: true # for 3rdparty + - name: Read package.json + uses: nextcloud-libraries/parse-package-engines-action@122ae05d4257008180a514e1ddeb0c1b9d094bdd # v0.1.0 + id: versions + - name: Set up node + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: ${{ steps.versions.outputs.node-version }} + - name: Set up npm + run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}' + - name: Install dependencies and build + run: | + npm ci + npm run build --if-present + - name: Save context + uses: buildjet/cache/save@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2 + with: + key: playwright-context-${{ github.run_id }} + path: ./ playwright-tests: needs: [gate, playwright-setup] @@ -89,129 +91,124 @@ jobs: package-manager-version: ${{ steps.versions.outputs.package-manager-version }} steps: - - name: Restore context - id: cache - uses: buildjet/cache/restore@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2 - with: - key: playwright-context-${{ github.run_id }} - path: ./ - - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - if: steps.cache.outputs.cache-hit != 'true' - with: - persist-credentials: false - submodules: true # for 3rdparty - - - name: Read package.json - if: steps.cache.outputs.cache-hit != 'true' - uses: nextcloud-libraries/parse-package-engines-action@122ae05d4257008180a514e1ddeb0c1b9d094bdd # v0.1.0 - id: versions - - - name: Set up node - if: steps.cache.outputs.cache-hit != 'true' - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version: ${{ steps.versions.outputs.node-version }} - - - name: Set up npm - if: steps.cache.outputs.cache-hit != 'true' - run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}' - - - name: Install dependencies and build - if: steps.cache.outputs.cache-hit != 'true' - run: | - npm ci - npm run build --if-present - - - name: Install Playwright browsers - run: npx playwright install --with-deps - - - name: Run Playwright tests - run: npm run playwright -- --shard='${{ matrix.shardIndex }}/${{ matrix.shardTotal }}' - - - name: Show logs - if: failure() - run: | - for id in $(docker ps -aq); do - docker container inspect "$id" --format '=== Logs for container {{.Name}} ===' - docker logs "$id" >> nextcloud.log - done - echo '=== Nextcloud server logs ===' - docker exec nextcloud-e2e-test-server_server cat data/nextcloud.log - - - name: Upload blob report to GitHub Actions Artifacts - if: ${{ !cancelled() }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: blob-report-${{ matrix.shardIndex }} - path: blob-report - retention-days: 1 + - name: Restore context + id: cache + uses: buildjet/cache/restore@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2 + with: + key: playwright-context-${{ github.run_id }} + path: ./ + + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + if: steps.cache.outputs.cache-hit != 'true' + with: + persist-credentials: false + submodules: true # for 3rdparty + + - name: Read package.json + if: steps.cache.outputs.cache-hit != 'true' + uses: nextcloud-libraries/parse-package-engines-action@122ae05d4257008180a514e1ddeb0c1b9d094bdd # v0.1.0 + id: versions + + - name: Set up node + if: steps.cache.outputs.cache-hit != 'true' + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: ${{ steps.versions.outputs.node-version }} + + - name: Set up npm + if: steps.cache.outputs.cache-hit != 'true' + run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}' + + - name: Install dependencies and build + if: steps.cache.outputs.cache-hit != 'true' + run: | + npm ci + npm run build --if-present + + - name: Install Playwright browsers + run: npx playwright install --with-deps + + - name: Run Playwright tests + run: npm run playwright -- --shard='${{ matrix.shardIndex }}/${{ matrix.shardTotal }}' + + - name: Show logs + if: failure() + run: | + for id in $(docker ps -aq); do + docker container inspect "$id" --format '=== Logs for container {{.Name}} ===' + docker logs "$id" >> nextcloud.log + done + echo '=== Nextcloud server logs ===' + docker exec nextcloud-e2e-test-server_server cat data/nextcloud.log + + - name: Upload blob report to GitHub Actions Artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: blob-report-${{ matrix.shardIndex }} + path: blob-report + retention-days: 1 merge-reports: # Merge reports after playwright-tests, even if some shards have failed - if: ${{ !cancelled() }} - needs: [gate, playwright-tests] - + if: ${{ !cancelled() && steps.gate.conclusion != 'failure' }} + needs: [playwright-tests] runs-on: ubuntu-latest-low steps: - - name: Restore context - id: cache - uses: buildjet/cache/restore@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2 - with: - key: playwright-context-${{ github.run_id }} - path: ./ - - - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - if: steps.cache.outputs.cache-hit != 'true' - with: - persist-credentials: false - - - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - if: steps.cache.outputs.cache-hit != 'true' - with: - node-version: ${{ needs.playwright-tests.outputs.node-version }} - - - name: Set up npm - if: steps.cache.outputs.cache-hit != 'true' - run: npm i -g 'npm@${{ needs.playwright-tests.outputs.package-manager-version }}' - - - name: Install dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: npm ci - - - name: Download blob reports from GitHub Actions Artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - path: all-blob-reports - pattern: blob-report-* - merge-multiple: true - - - name: Merge into HTML Report - run: npx playwright merge-reports --config tests/playwright/merge.config.ts --reporter html,github ./all-blob-reports - - - name: Upload HTML report - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: html-report--attempt-${{ github.run_attempt }} - path: playwright-report - retention-days: 7 - - - name: Show the logs - run: | - echo 'To view the report:' - echo ' 1. Extract the folder from the zip file' - echo ' 2. run "npx playwright show-report name-of-my-extracted-playwright-report"' + - name: Restore context + id: cache + uses: buildjet/cache/restore@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2 + with: + key: playwright-context-${{ github.run_id }} + path: ./ + + - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + if: steps.cache.outputs.cache-hit != 'true' + with: + persist-credentials: false + + - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + if: steps.cache.outputs.cache-hit != 'true' + with: + node-version: ${{ needs.playwright-tests.outputs.node-version }} + + - name: Set up npm + if: steps.cache.outputs.cache-hit != 'true' + run: npm i -g 'npm@${{ needs.playwright-tests.outputs.package-manager-version }}' + + - name: Install dependencies + if: steps.cache.outputs.cache-hit != 'true' + run: npm ci + + - name: Download blob reports from GitHub Actions Artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + path: all-blob-reports + pattern: blob-report-* + merge-multiple: true + + - name: Merge into HTML Report + run: npx playwright merge-reports --config tests/playwright/merge.config.ts --reporter html,github ./all-blob-reports + + - name: Upload HTML report + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: html-report--attempt-${{ github.run_attempt }} + path: playwright-report + retention-days: 7 + + - name: Show the logs + run: | + echo 'To view the report:' + echo ' 1. Extract the folder from the zip file' + echo ' 2. run "npx playwright show-report name-of-my-extracted-playwright-report"' summary: permissions: contents: none runs-on: ubuntu-latest-low needs: [gate, playwright-tests] - - if: always() - name: playwright-test-summary - steps: - name: Summary status run: if ${{ needs.playwright-tests.result != 'success' }}; then exit 1; fi