# We use github cache to save snapshots between runs. # For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used. # If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. # These are then downloaded before running the E2E, providing the reference snapshots. # If there are any errors, the diff image is uploaded to artifacts, and the user is notified. name: E2E on: push: branches-ignore: - 'gh-readonly-queue/**' pull_request: merge_group: permissions: contents: read env: # For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used. targetHash: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || (github.event.before == '0000000000000000000000000000000000000000' && 'develop' || github.event.before) }} jobs: cache: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 18.x - name: Cache snapshots id: cache-snapshot uses: actions/cache@v4 with: save-always: true path: ./cypress/snapshots key: ${{ runner.os }}-snapshots-${{ env.targetHash }} # If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. - name: Switch to base branch if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} uses: actions/checkout@v4 with: ref: ${{ env.targetHash }} - name: Cypress run uses: cypress-io/github-action@v4 id: cypress-snapshot-gen if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} with: start: pnpm run dev wait-on: 'http://localhost:9000' browser: chrome e2e: runs-on: ubuntu-latest needs: cache strategy: fail-fast: false matrix: node-version: [18.x] containers: [1, 2, 3, 4] steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 # uses version from "packageManager" field in package.json - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} # These cached snapshots are downloaded, providing the reference snapshots. - name: Cache snapshots id: cache-snapshot uses: actions/cache/restore@v3 with: path: ./cypress/snapshots key: ${{ runner.os }}-snapshots-${{ env.targetHash }} # Install NPM dependencies, cache them correctly # and run all Cypress tests - name: Cypress run uses: cypress-io/github-action@v4 id: cypress # If CYPRESS_RECORD_KEY is set, run in parallel on all containers # Otherwise (e.g. if running from fork), we run on a single container only if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }} with: start: pnpm run dev:coverage wait-on: 'http://localhost:9000' browser: chrome # Disable recording if we don't have an API key # e.g. if this action was run from a fork record: ${{ secrets.CYPRESS_RECORD_KEY != '' }} parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }} env: CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} VITEST_COVERAGE: true CYPRESS_COMMIT: ${{ github.sha }} - name: Upload Coverage to Codecov uses: codecov/codecov-action@v3 # Run step only pushes to develop and pull_requests if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}} with: files: coverage/cypress/lcov.info flags: e2e name: mermaid-codecov fail_ci_if_error: false verbose: true token: 6845cc80-77ee-4e17-85a1-026cd95e0766 # We upload the artifacts into numbered archives to prevent overwriting - name: Upload Artifacts uses: actions/upload-artifact@v4 if: ${{ always() }} with: name: snapshots-${{ matrix.containers }} retention-days: 1 path: ./cypress/snapshots combineArtifacts: needs: e2e runs-on: ubuntu-latest if: ${{ always() }} steps: # Download all snapshot artifacts and merge them into a single folder - name: Download All Artifacts uses: actions/download-artifact@v4 with: path: snapshots pattern: snapshots-* merge-multiple: true # For successful push events, we save the snapshots cache - name: Save snapshots cache id: cache-upload if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }} uses: actions/cache/save@v3 with: path: ./snapshots key: ${{ runner.os }}-snapshots-${{ github.event.after }} - name: Flatten images to a folder if: ${{ needs.e2e.result == 'failure' }} run: | mkdir errors cd snapshots find . -mindepth 2 -type d -name "*__diff_output__*" -exec sh -c 'mv "$0"/*.png ../errors/' {} \; - name: Upload Error snapshots if: ${{ needs.e2e.result == 'failure' }} uses: actions/upload-artifact@v4 id: upload-artifacts with: name: error-snapshots retention-days: 10 path: errors/ - name: Notify Users if: ${{ needs.e2e.result == 'failure' }} run: | echo "::error title=Visual tests failed::You can view images that failed by downloading the error-snapshots artifact: ${{ steps.upload-artifacts.outputs.artifact-url }}"