--- name: E2E Tests (pull request) on: # Argo Events Trigger (automated): # - Triggered by: Enterprise CI/docker-image status check (success) # - Payload: { ref: "", inputs: { commit_sha: "" } } # - Uses commit-specific docker image # - Checks for relevant file changes before running tests # # Manual Trigger: # - Enter PR number only - commit SHA is resolved automatically from PR head # - Uses commit-specific docker image # - E2E tests always run (no file change check) # workflow_dispatch: inputs: pr_number: description: "PR number to test (for manual triggers)" type: string required: false commit_sha: description: "Commit SHA to test (for Argo Events)" type: string required: false run_rolling_upgrades: description: "Also run Playwright rolling-upgrade coverage (upgrade-from/to matrix, then the full suite on each upgraded server)" type: boolean required: false default: false permissions: {} jobs: resolve-pr: permissions: contents: read pull-requests: read runs-on: ubuntu-24.04 outputs: PR_NUMBER: "${{ steps.resolve.outputs.PR_NUMBER }}" COMMIT_SHA: "${{ steps.resolve.outputs.COMMIT_SHA }}" SERVER_IMAGE_TAG: "${{ steps.e2e-check.outputs.image_tag }}" HEAD_REF: "${{ steps.resolve.outputs.HEAD_REF }}" steps: - name: ci/checkout-repo uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false fetch-depth: 0 - name: ci/resolve-pr-and-commit id: resolve env: GH_TOKEN: ${{ github.token }} GITHUB_REPOSITORY: ${{ github.repository }} INPUT_PR_NUMBER: ${{ inputs.pr_number }} INPUT_COMMIT_SHA: ${{ inputs.commit_sha }} run: | # Validate inputs if [ -n "$INPUT_PR_NUMBER" ] && ! [[ "$INPUT_PR_NUMBER" =~ ^[0-9]+$ ]]; then echo "::error::Invalid PR number format. Must be numeric." exit 1 fi if [ -n "$INPUT_COMMIT_SHA" ] && ! [[ "$INPUT_COMMIT_SHA" =~ ^[a-f0-9]{7,40}$ ]]; then echo "::error::Invalid commit SHA format. Must be 7-40 hex characters." exit 1 fi # Manual trigger: PR number provided, resolve commit SHA from PR head if [ -n "$INPUT_PR_NUMBER" ]; then echo "Manual trigger: resolving commit SHA from PR #${INPUT_PR_NUMBER}" PR_DATA=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${INPUT_PR_NUMBER}") COMMIT_SHA=$(echo "$PR_DATA" | jq -r '.head.sha') if [ -z "$COMMIT_SHA" ] || [ "$COMMIT_SHA" = "null" ]; then echo "::error::Could not resolve commit SHA for PR #${INPUT_PR_NUMBER}" exit 1 fi echo "PR_NUMBER=${INPUT_PR_NUMBER}" >> $GITHUB_OUTPUT echo "COMMIT_SHA=${COMMIT_SHA}" >> $GITHUB_OUTPUT echo "HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref')" >> $GITHUB_OUTPUT exit 0 fi # Argo Events trigger: commit SHA provided, resolve PR number if [ -n "$INPUT_COMMIT_SHA" ]; then echo "Automated trigger: resolving PR number from commit ${INPUT_COMMIT_SHA}" PR_DATA=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${INPUT_COMMIT_SHA}/pulls" \ --jq '.[0] // empty' 2>/dev/null || echo "") PR_NUMBER=$(echo "$PR_DATA" | jq -r '.number // empty' 2>/dev/null || echo "") if [ -z "$PR_NUMBER" ]; then echo "::error::No PR found for commit ${INPUT_COMMIT_SHA}. This workflow is for PRs only." exit 1 fi echo "Found PR #${PR_NUMBER} for commit ${INPUT_COMMIT_SHA}" # Skip if PR is already merged to master or a release branch. # The e2e-tests-on-merge workflow handles post-merge E2E tests. PR_MERGED=$(echo "$PR_DATA" | jq -r '.merged_at // empty' 2>/dev/null || echo "") PR_BASE_REF=$(echo "$PR_DATA" | jq -r '.base.ref // empty' 2>/dev/null || echo "") if [ -n "$PR_MERGED" ]; then if [ "$PR_BASE_REF" = "master" ] || [[ "$PR_BASE_REF" =~ ^release-[0-9]+\.[0-9]+$ ]]; then echo "PR #${PR_NUMBER} is already merged to ${PR_BASE_REF}. Skipping - handled by e2e-tests-on-merge workflow." echo "PR_NUMBER=" >> $GITHUB_OUTPUT echo "COMMIT_SHA=" >> $GITHUB_OUTPUT echo "HEAD_REF=" >> $GITHUB_OUTPUT exit 0 fi fi echo "PR_NUMBER=${PR_NUMBER}" >> $GITHUB_OUTPUT echo "COMMIT_SHA=${INPUT_COMMIT_SHA}" >> $GITHUB_OUTPUT echo "HEAD_REF=$(echo "$PR_DATA" | jq -r '.head.ref // empty' 2>/dev/null || echo "")" >> $GITHUB_OUTPUT exit 0 fi # Neither provided echo "::error::Either pr_number or commit_sha must be provided" exit 1 - name: ci/check-e2e-test-only if: steps.resolve.outputs.PR_NUMBER != '' id: e2e-check uses: ./.github/actions/check-e2e-test-only with: pr_number: ${{ steps.resolve.outputs.PR_NUMBER }} check-changes: permissions: contents: read pull-requests: read needs: resolve-pr if: needs.resolve-pr.outputs.PR_NUMBER != '' runs-on: ubuntu-24.04 outputs: should_run: "${{ steps.check.outputs.should_run }}" should_run_fips: "${{ steps.check.outputs.should_run_fips }}" should_run_rolling_upgrades: "${{ steps.check.outputs.should_run_rolling_upgrades }}" steps: - name: ci/checkout-repo uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false ref: ${{ needs.resolve-pr.outputs.COMMIT_SHA }} fetch-depth: 0 - name: ci/check-relevant-changes id: check env: GH_TOKEN: ${{ github.token }} GITHUB_REPOSITORY: ${{ github.repository }} PR_NUMBER: ${{ needs.resolve-pr.outputs.PR_NUMBER }} COMMIT_SHA: ${{ needs.resolve-pr.outputs.COMMIT_SHA }} INPUT_PR_NUMBER: ${{ inputs.pr_number }} HEAD_REF: ${{ needs.resolve-pr.outputs.HEAD_REF }} INPUT_RUN_ROLLING_UPGRADES: ${{ inputs.run_rolling_upgrades }} run: | # Get the base branch of the PR and changed files BASE_SHA=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.base.sha') CHANGED_FILES=$(git diff --name-only "${BASE_SHA}...${COMMIT_SHA}") echo "Changed files:" echo "$CHANGED_FILES" # Determine should_run for regular E2E tests if [ -n "$INPUT_PR_NUMBER" ]; then # Manual trigger: always run E2E tests echo "Manual trigger detected - skipping file change check for regular E2E" SHOULD_RUN="true" else # Automated trigger: check for relevant file changes echo "Automated trigger detected - checking for relevant file changes" SHOULD_RUN="false" if echo "$CHANGED_FILES" | grep -qE '^server/.*\.go$'; then echo "Found server Go file changes" SHOULD_RUN="true" fi if echo "$CHANGED_FILES" | grep -qE '^webapp/.*\.(ts|tsx|js|jsx)$'; then echo "Found webapp TypeScript/JavaScript file changes" SHOULD_RUN="true" fi if echo "$CHANGED_FILES" | grep -qE '^e2e-tests/.*\.(ts|tsx|js|jsx)$'; then echo "Found e2e-tests TypeScript/JavaScript file changes" SHOULD_RUN="true" fi if echo "$CHANGED_FILES" | grep -qE '^\.github/workflows/e2e-.*\.yml$'; then echo "Found E2E CI workflow file changes" SHOULD_RUN="true" fi fi echo "should_run=${SHOULD_RUN}" >> $GITHUB_OUTPUT echo "Should run E2E tests: ${SHOULD_RUN}" # Check for FIPS-related conditions SHOULD_RUN_FIPS="false" if echo "$HEAD_REF" | grep -iqE 'fips'; then echo "Branch name '$HEAD_REF' contains 'fips'" SHOULD_RUN_FIPS="true" fi if echo "$CHANGED_FILES" | grep -qE '(^|/)go\.mod$'; then echo "Found go.mod file changes" SHOULD_RUN_FIPS="true" fi if echo "$CHANGED_FILES" | grep -qE '^server/build/Dockerfile\.buildenv-fips$'; then echo "Found FIPS Dockerfile changes" SHOULD_RUN_FIPS="true" fi echo "should_run_fips=${SHOULD_RUN_FIPS}" >> $GITHUB_OUTPUT echo "Should run FIPS E2E tests: ${SHOULD_RUN_FIPS}" # Rolling upgrades: opt-in on manual dispatch, or auto when the PR touches the harness. SHOULD_RUN_ROLLING_UPGRADES="false" if [ "$INPUT_RUN_ROLLING_UPGRADES" = "true" ]; then echo "Manual rolling-upgrades opt-in detected" SHOULD_RUN_ROLLING_UPGRADES="true" elif echo "$CHANGED_FILES" | grep -qE '^e2e-tests/playwright/(upgrade-specs/|script/resolve_upgrade_matrix\.mjs)'; then echo "Found Playwright upgrade-path harness changes" SHOULD_RUN_ROLLING_UPGRADES="true" elif echo "$CHANGED_FILES" | grep -qE '^\.github/workflows/e2e-tests-playwright-rolling-upgrades'; then echo "Found Playwright rolling-upgrade workflow changes" SHOULD_RUN_ROLLING_UPGRADES="true" # Server-side surfaces an upgrade has to survive: schema and config migrations, the # app-layer data migrations, and the version list the from-version matrix is derived from. elif echo "$CHANGED_FILES" | grep -qE '^server/(channels/db/migrations/|config/migrations/|channels/app/(migrations|permissions_migrations)\.go$|public/model/version\.go$)'; then echo "Found server migration or version changes" SHOULD_RUN_ROLLING_UPGRADES="true" fi echo "should_run_rolling_upgrades=${SHOULD_RUN_ROLLING_UPGRADES}" >> $GITHUB_OUTPUT echo "Should run rolling upgrades: ${SHOULD_RUN_ROLLING_UPGRADES}" e2e-cypress: needs: - resolve-pr - check-changes if: needs.resolve-pr.outputs.PR_NUMBER != '' permissions: contents: read statuses: write id-token: write pull-requests: write uses: ./.github/workflows/e2e-tests-cypress.yml with: commit_sha: "${{ needs.resolve-pr.outputs.COMMIT_SHA }}" server: "onprem" server_image_tag: "${{ needs.resolve-pr.outputs.SERVER_IMAGE_TAG }}" enable_reporting: true report_type: "PR" pr_number: "${{ needs.resolve-pr.outputs.PR_NUMBER }}" should_run: "${{ needs.check-changes.outputs.should_run }}" secrets: MM_LICENSE: "${{ secrets.MM_E2E_TEST_LICENSE_ONPREM_ENT }}" AUTOMATION_DASHBOARD_URL: "${{ secrets.MM_E2E_AUTOMATION_DASHBOARD_URL }}" AUTOMATION_DASHBOARD_TOKEN: "${{ secrets.MM_E2E_AUTOMATION_DASHBOARD_TOKEN }}" PUSH_NOTIFICATION_SERVER: "${{ secrets.MM_E2E_PUSH_NOTIFICATION_SERVER }}" REPORT_WEBHOOK_URL: "${{ secrets.MM_E2E_REPORT_WEBHOOK_URL }}" CWS_URL: "${{ secrets.MM_E2E_CWS_URL }}" CWS_EXTRA_HTTP_HEADERS: "${{ secrets.MM_E2E_CWS_EXTRA_HTTP_HEADERS }}" e2e-playwright: needs: - resolve-pr - check-changes if: needs.resolve-pr.outputs.PR_NUMBER != '' permissions: contents: read statuses: write id-token: write pull-requests: write uses: ./.github/workflows/e2e-tests-playwright.yml with: commit_sha: "${{ needs.resolve-pr.outputs.COMMIT_SHA }}" server: "onprem" server_image_tag: "${{ needs.resolve-pr.outputs.SERVER_IMAGE_TAG }}" enable_reporting: true report_type: "PR" pr_number: "${{ needs.resolve-pr.outputs.PR_NUMBER }}" should_run: "${{ needs.check-changes.outputs.should_run }}" run_rolling_upgrades: "${{ needs.check-changes.outputs.should_run_rolling_upgrades }}" secrets: MM_LICENSE: "${{ secrets.MM_E2E_TEST_LICENSE_ONPREM_ENT }}" REPORT_WEBHOOK_URL: "${{ secrets.MM_E2E_REPORT_WEBHOOK_URL }}" # Enterprise FIPS Edition e2e-cypress-fips: needs: - resolve-pr - check-changes if: needs.resolve-pr.outputs.PR_NUMBER != '' && needs.check-changes.outputs.should_run_fips == 'true' permissions: contents: read statuses: write id-token: write pull-requests: write uses: ./.github/workflows/e2e-tests-cypress.yml with: commit_sha: "${{ needs.resolve-pr.outputs.COMMIT_SHA }}" server: "onprem" server_edition: fips server_image_tag: "${{ needs.resolve-pr.outputs.SERVER_IMAGE_TAG }}" enable_reporting: true report_type: "PR" pr_number: "${{ needs.resolve-pr.outputs.PR_NUMBER }}" secrets: MM_LICENSE: "${{ secrets.MM_E2E_TEST_LICENSE_ONPREM_ENT }}" AUTOMATION_DASHBOARD_URL: "${{ secrets.MM_E2E_AUTOMATION_DASHBOARD_URL }}" AUTOMATION_DASHBOARD_TOKEN: "${{ secrets.MM_E2E_AUTOMATION_DASHBOARD_TOKEN }}" PUSH_NOTIFICATION_SERVER: "${{ secrets.MM_E2E_PUSH_NOTIFICATION_SERVER }}" REPORT_WEBHOOK_URL: "${{ secrets.MM_E2E_REPORT_WEBHOOK_URL }}" CWS_URL: "${{ secrets.MM_E2E_CWS_URL }}" CWS_EXTRA_HTTP_HEADERS: "${{ secrets.MM_E2E_CWS_EXTRA_HTTP_HEADERS }}" e2e-playwright-fips: needs: - resolve-pr - check-changes if: needs.resolve-pr.outputs.PR_NUMBER != '' && needs.check-changes.outputs.should_run_fips == 'true' permissions: contents: read statuses: write id-token: write pull-requests: write uses: ./.github/workflows/e2e-tests-playwright.yml with: commit_sha: "${{ needs.resolve-pr.outputs.COMMIT_SHA }}" server: "onprem" server_edition: fips server_image_tag: "${{ needs.resolve-pr.outputs.SERVER_IMAGE_TAG }}" enable_reporting: true report_type: "PR" pr_number: "${{ needs.resolve-pr.outputs.PR_NUMBER }}" run_rolling_upgrades: "${{ needs.check-changes.outputs.should_run_rolling_upgrades }}" secrets: MM_LICENSE: "${{ secrets.MM_E2E_TEST_LICENSE_ONPREM_ENT }}" REPORT_WEBHOOK_URL: "${{ secrets.MM_E2E_REPORT_WEBHOOK_URL }}"