diff --git a/.github/workflows/e2e-fulltests-ci.yml b/.github/workflows/e2e-fulltests-ci.yml index aeaff17f76..24b743b3f5 100644 --- a/.github/workflows/e2e-fulltests-ci.yml +++ b/.github/workflows/e2e-fulltests-ci.yml @@ -13,6 +13,10 @@ on: type: string description: If testing a PR, this must be specified as well. required: false + ROLLING_RELEASE_FROM_TAG: + type: string + description: If specified, the server will be initialized with the given release tag, perform a rolling upgrade, then run the full E2E test. + required: false MM_ENV: type: string required: false @@ -56,11 +60,14 @@ jobs: BUILD_ID: "${{ steps.generate.outputs.BUILD_ID }}" TM4J_ENABLE: "${{ steps.generate.outputs.TM4J_ENABLE }}" REPORT_TYPE: "${{ steps.generate.outputs.REPORT_TYPE }}" + ROLLING_RELEASE_commit_sha: "${{ steps.generate.outputs.ROLLING_RELEASE_commit_sha }}" + ROLLING_RELEASE_SERVER_IMAGE: "${{ steps.generate.outputs.ROLLING_RELEASE_SERVER_IMAGE }}" env: GH_TOKEN: "${{ github.token }}" REF: "${{ inputs.ref || github.sha }}" PR_NUMBER: "${{ inputs.PR_NUMBER || '' }}" REPORT_TYPE: "${{ inputs.REPORT_TYPE }}" + ROLLING_RELEASE_FROM_TAG: "${{ inputs.ROLLING_RELEASE_FROM_TAG }}" # We could exclude the @smoke group for PRs, but then we wouldn't have it in the report TEST_FILTER_PR: >- --stage="@prod" @@ -103,7 +110,6 @@ jobs: SERVER_IMAGE_TAG="${COMMIT_SHA::7}" SERVER_IMAGE_ORG=mattermostdevelopment BUILD_ID_SUFFIX="${REPORT_TYPE@L}-${SERVER}-ent" - STATUS_CHECK_CONTEXT="E2E Tests/test${MM_ENV:+/$MM_ENV_HASH}" WORKERS_NUMBER=20 TEST_FILTER="$TEST_FILTER_PR" COMPUTED_REPORT_TYPE="${REPORT_TYPE}" @@ -121,7 +127,7 @@ jobs: SERVER_IMAGE_TAG=master SERVER_IMAGE_ORG=mattermostdevelopment BUILD_ID_SUFFIX="${_IS_TEST_UNSTABLE:+unstable-}daily-${SERVER}-ent" - STATUS_CHECK_CONTEXT="E2E Tests/test-${BUILD_ID_SUFFIX}${MM_ENV:+/$MM_ENV_HASH}" + BUILD_ID_SUFFIX_IN_STATUS_CHECK=true WORKERS_NUMBER=10 # Daily tests are not time critical, and it's more efficient to run on fewer workers TEST_FILTER="${!_TEST_FILTER_VARIABLE} ${_IS_TEST_UNSTABLE:+--invert}" TM4J_ENABLE=true @@ -136,7 +142,7 @@ jobs: SERVER_IMAGE_TAG="$(cut -c2- <<<$REF)" # Remove the leading 'v' from the given tag name, to generate the docker image tag SERVER_IMAGE_ORG=mattermost BUILD_ID_SUFFIX="release-${SERVER}-ent" - STATUS_CHECK_CONTEXT="E2E Tests/test-${BUILD_ID_SUFFIX}${MM_ENV:+/$MM_ENV_HASH}" + BUILD_ID_SUFFIX_IN_STATUS_CHECK=true WORKERS_NUMBER=20 TEST_FILTER="${!_TEST_FILTER_VARIABLE}" TM4J_ENABLE=true @@ -149,17 +155,28 @@ jobs: echo "Fatal: unimplemented test type. Aborting." exit 1 esac + if [ -n "$ROLLING_RELEASE_FROM_TAG" ]; then + ROLLING_RELEASE_COMMIT_SHA=$(git rev-parse --verify "$ROLLING_RELEASE_FROM_TAG") + ROLLING_RELEASE_SERVER_IMAGE_TAG=$(echo "$ROLLING_RELEASE_FROM_TAG" | sed 's/^v//') # Remove the leading 'v' from the given tag name, to generate the docker image tag + ROLLING_RELEASE_SERVER_IMAGE="mattermost/mattermost-enterprise-edition:${ROLLING_RELEASE_SERVER_IMAGE_TAG}" + BUILD_ID_SUFFIX="rolling${ROLLING_RELEASE_FROM_TAG/-/_}-$BUILD_ID_SUFFIX" + BUILD_ID_SUFFIX_IN_STATUS_CHECK=true + ### Run sanity assertions after variable generations + git show-ref --verify "refs/tags/${ROLLING_RELEASE_FROM_TAG}" # 'inputs.ROLLING_RELEASE_FROM_TAG' must be a tag, for release report types + fi echo "commit_sha=${COMMIT_SHA}" >> $GITHUB_OUTPUT echo "BRANCH=${BRANCH}" >> $GITHUB_OUTPUT echo "SERVER_IMAGE=${SERVER_IMAGE_ORG}/mattermost-enterprise-edition:${SERVER_IMAGE_TAG}" >> $GITHUB_OUTPUT echo "SERVER=${SERVER}" >> $GITHUB_OUTPUT echo "server_uppercase=${SERVER@U}" >> $GITHUB_OUTPUT echo "ENABLED_DOCKER_SERVICES=postgres inbucket minio openldap elasticsearch keycloak" >> $GITHUB_OUTPUT - echo "status_check_context=${STATUS_CHECK_CONTEXT}" >> $GITHUB_OUTPUT + echo "status_check_context=E2E Tests/test${BUILD_ID_SUFFIX_IN_STATUS_CHECK:+-$BUILD_ID_SUFFIX}${MM_ENV:+/$MM_ENV_HASH}" >> $GITHUB_OUTPUT echo "workers_number=${WORKERS_NUMBER}" >> $GITHUB_OUTPUT echo "TEST_FILTER=${TEST_FILTER}" >> $GITHUB_OUTPUT echo "TM4J_ENABLE=${TM4J_ENABLE:-}" >> $GITHUB_OUTPUT echo "REPORT_TYPE=${COMPUTED_REPORT_TYPE}" >> $GITHUB_OUTPUT + echo "ROLLING_RELEASE_commit_sha=${ROLLING_RELEASE_COMMIT_SHA}" >> $GITHUB_OUTPUT + echo "ROLLING_RELEASE_SERVER_IMAGE=${ROLLING_RELEASE_SERVER_IMAGE}" >> $GITHUB_OUTPUT # BUILD_ID format: $pipelineID-$imageTag-$testType-$serverType-$serverEdition # Reference on BUILD_ID parsing: https://github.com/saturninoabril/automation-dashboard/blob/175891781bf1072c162c58c6ec0abfc5bcb3520e/lib/common_utils.ts#L3-L23 echo "BUILD_ID=${{ github.run_id }}_${{ github.run_attempt }}-${SERVER_IMAGE_TAG}-${BUILD_ID_SUFFIX}" >> $GITHUB_OUTPUT @@ -200,6 +217,8 @@ jobs: BRANCH: "${{ needs.generate-test-variables.outputs.BRANCH }}" BUILD_ID: "${{ needs.generate-test-variables.outputs.BUILD_ID }}" REPORT_TYPE: "${{ needs.generate-test-variables.outputs.REPORT_TYPE }}" + ROLLING_RELEASE_commit_sha: "${{ needs.generate-test-variables.outputs.ROLLING_RELEASE_commit_sha }}" + ROLLING_RELEASE_SERVER_IMAGE: "${{ needs.generate-test-variables.outputs.ROLLING_RELEASE_SERVER_IMAGE }}" secrets: MM_LICENSE: "${{ secrets[format('MM_E2E_TEST_LICENSE_{0}_ENT', needs.generate-test-variables.outputs.server_uppercase)] }}" AUTOMATION_DASHBOARD_URL: "${{ secrets.MM_E2E_AUTOMATION_DASHBOARD_URL }}" diff --git a/.github/workflows/e2e-tests-ci-template.yml b/.github/workflows/e2e-tests-ci-template.yml index ede42c7e3d..b731437ecf 100644 --- a/.github/workflows/e2e-tests-ci-template.yml +++ b/.github/workflows/e2e-tests-ci-template.yml @@ -55,6 +55,12 @@ on: REPORT_TYPE: type: string required: false + ROLLING_RELEASE_commit_sha: + type: string + required: false + ROLLING_RELEASE_SERVER_IMAGE: + type: string + required: false secrets: MM_LICENSE: required: false @@ -238,7 +244,7 @@ jobs: os: [ubuntu-latest-8-cores] worker_index: ${{ fromJSON(needs.generate-build-variables.outputs.workers) }} # https://docs.github.com/en/actions/learn-github-actions/expressions#example-returning-a-json-object runs-on: "${{ matrix.os }}" - timeout-minutes: 60 + timeout-minutes: 90 needs: - cypress-check - playwright-check @@ -263,6 +269,8 @@ jobs: CYPRESS_pushNotificationServer: "${{ secrets.PUSH_NOTIFICATION_SERVER }}" CWS_URL: "${{ secrets.CWS_URL }}" CWS_EXTRA_HTTP_HEADERS: "${{ secrets.CWS_EXTRA_HTTP_HEADERS }}" + ROLLING_RELEASE_COMMIT_SHA: "${{ inputs.ROLLING_RELEASE_commit_sha }}" + ROLLING_RELEASE_SERVER_IMAGE: "${{ inputs.ROLLING_RELEASE_SERVER_IMAGE }}" steps: - name: ci/checkout-repo uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 @@ -287,7 +295,30 @@ jobs: cache-dependency-path: "e2e-tests/cypress/package-lock.json" - name: ci/e2e-test run: | + make cloud-init + if [ -n "$ROLLING_RELEASE_SERVER_IMAGE" ]; then + echo "RollingRelease: checking out E2E test cases from revision ${ROLLING_RELEASE_COMMIT_SHA}, for initial smoketest" + git checkout "${ROLLING_RELEASE_COMMIT_SHA}" -- cypress/ && git status + ( + echo "RollingRelease: running initial smoketest against image $ROLLING_RELEASE_SERVER_IMAGE" + export SERVER_IMAGE="$ROLLING_RELEASE_SERVER_IMAGE" + export TEST_FILTER="" + export AUTOMATION_DASHBOARD_URL="" + make + ) + echo "RollingRelease: asserting smoketest result has zero failures." + FAILURES=$(find cypress/results -name '*.json' | xargs -l jq -r '.stats.failures' | jq -s add) + if [ "$FAILURES" -ne "0" ]; then + echo "RollingRelease: initial smoketest for rolling release E2E run has nonzero ($FAILURES) failures. Aborting test run." >&2 + exit 1 + fi + rm -rfv cypress/results + echo "RollingRelease: reset the E2E test cases to the revision to test" + git reset --hard HEAD && git status + echo "RollingRelease: smoketest completed. Starting full E2E tests." + fi make + make cloud-teardown - name: ci/e2e-test-store-results uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: @@ -343,6 +374,7 @@ jobs: TYPE: "${{ inputs.REPORT_TYPE }}" SERVER: "${{ inputs.SERVER }}" SERVER_IMAGE: "${{ inputs.SERVER_IMAGE }}" + AUTOMATION_DASHBOARD_URL: "${{ secrets.AUTOMATION_DASHBOARD_URL }}" WEBHOOK_URL: "${{ secrets.REPORT_WEBHOOK_URL }}" BRANCH: "${{ inputs.BRANCH }}" BUILD_ID: "${{ inputs.BUILD_ID }}" diff --git a/e2e-tests/.ci/report.publish.sh b/e2e-tests/.ci/report.publish.sh index 9d946e9b89..4fc4dc045e 100755 --- a/e2e-tests/.ci/report.publish.sh +++ b/e2e-tests/.ci/report.publish.sh @@ -35,6 +35,7 @@ export BUILD_TAG="${SERVER_IMAGE##*/}" export MM_DOCKER_IMAGE="${BUILD_TAG%%:*}" # NB: the 'mattermostdevelopment/' prefix is assumed export MM_DOCKER_TAG="${BUILD_TAG##*:}" export SERVER_TYPE="${SERVER}" +export AUTOMATION_DASHBOARD_FRONTEND_URL="${AUTOMATION_DASHBOARD_URL:+${AUTOMATION_DASHBOARD_URL%%/api}}" if [ -n "${TM4J_API_KEY:-}" ]; then # Set additional variables required for Zephyr reporting diff --git a/e2e-tests/.ci/server.cloud_init.sh b/e2e-tests/.ci/server.cloud_init.sh index a5072306bf..b4eb95c4df 100755 --- a/e2e-tests/.ci/server.cloud_init.sh +++ b/e2e-tests/.ci/server.cloud_init.sh @@ -2,10 +2,14 @@ set -e -u -o pipefail cd "$(dirname "$0")" . .e2erc +[ -f .env.cloud ] && . .env.cloud if [ "$SERVER" != "cloud" ]; then mme2e_log "Skipping cloud instance initialization: operation supported only for cloud server, but running with SERVER='$SERVER'" exit 0 +elif [ -n "${MM_CUSTOMER_ID:-}" ]; then + mme2e_log "Skipping cloud user creation: customer with ID '$MM_CUSTOMER_ID' is already configured. Please run 'make cloud-teardown' before creating a new user." + exit 0 fi mme2e_log "Initializing cloud tests" diff --git a/e2e-tests/.ci/server.cloud_teardown.sh b/e2e-tests/.ci/server.cloud_teardown.sh index 84666fd98b..a67d41e2c4 100755 --- a/e2e-tests/.ci/server.cloud_teardown.sh +++ b/e2e-tests/.ci/server.cloud_teardown.sh @@ -2,9 +2,10 @@ set -e -u -o pipefail cd "$(dirname "$0")" . .e2erc +[ -f .env.cloud ] && . .env.cloud -if [ "$SERVER" != "cloud" ]; then - mme2e_log "Skipping cloud instance teardown: operation supported only for cloud server, but running with SERVER='$SERVER'" +if [ -z "${MM_CUSTOMER_ID:-}" ]; then + mme2e_log "Skipping cloud instance teardown: MM_CUSTOMER_ID variable is empty, no cloud user to cleanup." exit 0 fi @@ -20,5 +21,6 @@ MME2E_ENVCHECK_MSG="variable required for tearing down cloud tests, but is empty mme2e_log "Deleting customer $MM_CUSTOMER_ID." curl -fsSL -X DELETE -H @- "${CWS_URL}/api/v1/tests/customers/$MM_CUSTOMER_ID/payment-customer" <<<"${CWS_EXTRA_HTTP_HEADERS:-}" +rm -fv .env.cloud mme2e_log "Test cloud customer deleted, MM_CUSTOMER_ID: $MM_CUSTOMER_ID." diff --git a/e2e-tests/.ci/server.prepare.sh b/e2e-tests/.ci/server.prepare.sh index a619db53d3..404efb43ff 100755 --- a/e2e-tests/.ci/server.prepare.sh +++ b/e2e-tests/.ci/server.prepare.sh @@ -26,16 +26,33 @@ if [ "$TEST" = "cypress" ]; then ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress npm i ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress cypress install mme2e_log "Prepare Cypress: populating fixtures" - ${MME2E_DC_SERVER} exec -T -- server curl -L --silent https://github.com/mattermost/mattermost-plugin-gitlab/releases/download/v1.3.0/com.github.manland.mattermost-plugin-gitlab-1.3.0.tar.gz | ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee tests/fixtures/com.github.manland.mattermost-plugin-gitlab-1.3.0.tar.gz >/dev/null - ${MME2E_DC_SERVER} exec -T -- server curl -L --silent https://github.com/mattermost/mattermost-plugin-demo/releases/download/v0.9.0/com.mattermost.demo-plugin-0.9.0.tar.gz | ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee tests/fixtures/com.mattermost.demo-plugin-0.9.0.tar.gz >/dev/null - ${MME2E_DC_SERVER} exec -T -- server curl -L --silent https://github.com/mattermost/mattermost-plugin-demo/releases/download/v0.8.0/com.mattermost.demo-plugin-0.8.0.tar.gz | ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee tests/fixtures/com.mattermost.demo-plugin-0.8.0.tar.gz >/dev/null ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee tests/fixtures/keycloak.crt >/dev/null <../../server/build/docker/keycloak/keycloak.crt + for PLUGIN_URL in \ + "https://github.com/mattermost/mattermost-plugin-gitlab/releases/download/v1.3.0/com.github.manland.mattermost-plugin-gitlab-1.3.0.tar.gz" \ + "https://github.com/mattermost/mattermost-plugin-demo/releases/download/v0.9.0/com.mattermost.demo-plugin-0.9.0.tar.gz" \ + "https://github.com/mattermost/mattermost-plugin-demo/releases/download/v0.8.0/com.mattermost.demo-plugin-0.8.0.tar.gz" + do + PLUGIN_NAME="${PLUGIN_URL##*/}" + PLUGIN_PATH="tests/fixtures/$PLUGIN_NAME" + if ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress test -f "$PLUGIN_PATH"; then + mme2e_log "Skipping installation of plugin $PLUGIN_NAME: file exists" + continue + fi + mme2e_log "Downloading $PLUGIN_NAME to fixtures directory" + ${MME2E_DC_SERVER} exec -T -- server curl -L --silent "${PLUGIN_URL}" | ${MME2E_DC_SERVER} exec -T -u "$MME2E_UID" -- cypress tee "$PLUGIN_PATH" >/dev/null + done fi # Run service-specific initialization steps for SERVICE in $ENABLED_DOCKER_SERVICES; do case "$SERVICE" in openldap) + LDIF_FILE=../../server/tests/test-data.ldif + LDIF_CANARY=$(sed -n -E 's/^dn:[[:space:]]*(.*)$/\1/p' ${LDIF_FILE} | tail -n1) + if ${MME2E_DC_SERVER} exec -T -- openldap bash -c "ldapsearch -x -D \"cn=admin,dc=mm,dc=test,dc=com\" -w mostest -b \"$LDIF_CANARY\" >/dev/null"; then + mme2e_log "Skipping configuration for the $SERVICE container: already initialized" + continue + fi mme2e_log "Configuring the $SERVICE container" ${MME2E_DC_SERVER} exec -T -- openldap bash -c 'ldapadd -x -D "cn=admin,dc=mm,dc=test,dc=com" -w mostest' <../../server/tests/test-data.ldif ;; diff --git a/e2e-tests/.ci/server.start.sh b/e2e-tests/.ci/server.start.sh index 8e22082038..73f8d03b20 100755 --- a/e2e-tests/.ci/server.start.sh +++ b/e2e-tests/.ci/server.start.sh @@ -3,10 +3,6 @@ set -e -u -o pipefail cd "$(dirname "$0")" . .e2erc -# Cleanup old containers, if any -mme2e_log "Stopping leftover E2E containers, if any are running" -${MME2E_DC_SERVER} down -v --remove-orphans - # Wait for the required server image mme2e_log "Waiting for server image to be available" mme2e_wait_image "$SERVER_IMAGE" 4 30 diff --git a/e2e-tests/Makefile b/e2e-tests/Makefile index a223cb23f1..9945f270da 100644 --- a/e2e-tests/Makefile +++ b/e2e-tests/Makefile @@ -2,11 +2,11 @@ SHELL := /bin/bash .PHONY: all run stop clean all: run -run: cloud-init generate-server start-server prepare-server run-test cloud-teardown +run: generate-server start-server prepare-server run-test stop: stop-server stop-dashboard clean clean: rm -fv .ci/server.yml - rm -fv .ci/.env* + rm -fv .ci/.env.{server,dashboard,cypress,playwright} .PHONY: generate-server start-server prepare-server run-test stop-server restart-server generate-server: diff --git a/e2e-tests/README.md b/e2e-tests/README.md index 50f23281b0..359e287167 100644 --- a/e2e-tests/README.md +++ b/e2e-tests/README.md @@ -37,11 +37,12 @@ Instructions, detailed: * Only Cypress is currently using the dashboard; Playwright is not. 3. `make`: start and prepare the server, then run the Cypress smoke tests * You can track the progress of the run in the `http://localhost:4000/cycles` dashboard if you launched it locally - * When running with `SERVER=cloud`, this will automatically create a cloud customer against the specified `CWS_URL` service, and delete that user after the run is complete. + * For `SERVER=cloud` runs, you'll need to first create a cloud customer against the specified `CWS_URL` service by running `make cloud-init`. The user isn't automatically removed, and may be reused across multiple runs until you run `make cloud-teardown` to delete it. * If you want to run the Playwright tests instead of the Cypress ones, you can run `TEST=playwright make` * If you just want to run a local server instance, without any further testing, you can run `TEST=none make` * If you're using the automation dashboard, you have the option of sharding the E2E test run: you can launch the `make` command in parallel on different machines (NB: you must use the same `BUILD_ID` and `BRANCH` values that you used for `make generate-test-cycle`) to distribute running the test cases across them. When doing this, you should also set on each machine the `CI_BASE_URL` variable to a value that uniquely identifies the instance where `make` is running. 4. `make stop`: tears down the server (and the dashboard, if running) + * This will stop and cleanup all of the E2E testing containers, including the database and its persistent volume. * This also implicitly runs `make clean`, which also removes any generated environment or docker-compose files. Notes: @@ -54,6 +55,7 @@ Notes: * If you need to introduce variables that you want to control from `.ci/env`: you need to update the scripts under the `.ci/` dir and configure them to write the new variables' values over to the appropriate `.env.*` file. In particular, avoid defining variables that depend on other variables within the docker-compose override files: this is to ensure uniformity in their availability and simplifies the question of what container has access to which variable considerably. * Exceptions are of course accepted wherever it makes sense (e.g. if you need to group variables based on some common functionality) - The `publish-report` Make target is meant for internal usage. Usage and variables are documented in the respective scripts. +- `make start-server` won't cleanup containers that don't change across runs. This means that you can use it to emulate a Mattermost server upgrade while retaining your database data by simply changing the `SERVER_IMAGE` variable on your machine, and then re-runing `make start-server` (and `make prepare-server` if you intend to run cypress again, since its container is also recreated). But this also means that if you want to run a clean local environment, you may have to manually run `make stop` to cleanup any running containers and their volumes, which include e.g. the database. ##### For code changes: * `make fmt-ci` to format and check yaml files and shell scripts. diff --git a/e2e-tests/cypress/save_report.js b/e2e-tests/cypress/save_report.js index 8fd2cd6330..3f332ed737 100644 --- a/e2e-tests/cypress/save_report.js +++ b/e2e-tests/cypress/save_report.js @@ -23,6 +23,7 @@ * - TM4J_FOLDER_ID=[folder_id], e.g. 847997 * For sending hooks to Mattermost channels * - FULL_REPORT, WEBHOOK_URL and DIAGNOSTIC_WEBHOOK_URL + * - If AUTOMATION_DASHBOARD_FRONTEND_URL is set, a link to the corresponding cycle will be included in the report message * Test type * - TYPE=[type]; valid values: "PR", "RELEASE", "MASTER", "MASTER_UNSTABLE", "CLOUD", "CLOUD_UNSTABLE", "NONE" * Server type diff --git a/e2e-tests/cypress/utils/report.js b/e2e-tests/cypress/utils/report.js index c30ab98954..5589b11254 100644 --- a/e2e-tests/cypress/utils/report.js +++ b/e2e-tests/cypress/utils/report.js @@ -117,6 +117,8 @@ function generateTestReport(summary, isUploadedToS3, reportLink, environment, te TEST_CYCLE_LINK_PREFIX, MM_ENV, SERVER_TYPE, + BUILD_ID, + AUTOMATION_DASHBOARD_FRONTEND_URL, } = process.env; const {statsFieldValue, stats} = summary; const { @@ -216,6 +218,12 @@ function generateTestReport(summary, isUploadedToS3, reportLink, environment, te testCycleLink = testCycleKey ? `| [Recorded test executions](${TEST_CYCLE_LINK_PREFIX}${testCycleKey})` : ''; } + const automationDashboardField = AUTOMATION_DASHBOARD_FRONTEND_URL ? `| [Automation Dashboard](${AUTOMATION_DASHBOARD_FRONTEND_URL}/cycle/${BUILD_ID})` : ''; + + const rollingReleaseMatchRegex = BUILD_ID.match(/-rolling(?[^-]+)-/); + const rollingReleaseFrom = rollingReleaseMatchRegex?.groups?.version; + const rollingReleaseFromField = rollingReleaseFrom ? `\nRolling release upgrade from: ${rollingReleaseFrom}` : ''; + const startAt = dayjs(stats.start); const endAt = dayjs(stats.end); const statsDuration = dayjs.duration(endAt.diff(startAt)).format('H:mm:ss'); @@ -229,7 +237,7 @@ function generateTestReport(summary, isUploadedToS3, reportLink, environment, te author_icon: 'https://mattermost.com/wp-content/uploads/2022/02/icon_WS.png', author_link: 'https://www.mattermost.com/', title, - text: `${quickSummary} | ${statsDuration} ${testCycleLink}\n${runnerEnvValue}${SERVER_TYPE ? '\nTest server: ' + SERVER_TYPE : ''}${MM_ENV ? '\nTest server override: ' + MM_ENV : ''}`, + text: `${quickSummary} | ${statsDuration} ${testCycleLink} ${automationDashboardField}\n${runnerEnvValue}${SERVER_TYPE ? '\nTest server: ' + SERVER_TYPE : ''}${rollingReleaseFromField}${MM_ENV ? '\nTest server override: ' + MM_ENV : ''}`, }], }; }