Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fe9514e
fix(cmt): POST directly to matterwick instead of relying on workflow_…
May 21, 2026
c41490b
fix(cmt): drop all GITHUB_TOKEN scopes for cmt-provisioner
May 25, 2026
0ce5d27
fix(cmt): quote ${RUN_ID} expansion in jq invocation
May 25, 2026
e2e49b9
fix(e2e): drop push trigger from e2e-nightly-trigger.yml
May 25, 2026
cd36811
fix(e2e): fix macOS e2e failures from crash dialogs and teardown
yasserfaraazkhan May 26, 2026
ddcc6c0
fix(e2e): add blank line before comment to satisfy eslint lines-aroun…
yasserfaraazkhan May 26, 2026
8298749
fix(e2e): use execFileSync instead of execSync, fix misleading comment
yasserfaraazkhan May 26, 2026
a926985
fix(e2e): unblock macOS tests and report per-OS results
yasserfaraazkhan May 26, 2026
0b1facd
fix(ci): pin policy-tests-windows to windows-2022 + add intercom tests
yasserfaraazkhan May 26, 2026
bb174ef
fix(e2e): address remaining macOS/Linux/Windows failures
yasserfaraazkhan May 26, 2026
e7e0dc9
fix(e2e): split inline try/catch onto multiple lines for eslint
yasserfaraazkhan May 26, 2026
b3d7682
fix(e2e): address CI failures across Linux, macOS, and Windows
yasserfaraazkhan May 26, 2026
de6d112
fix tests
yasserfaraazkhan May 26, 2026
7508c9f
Merge remote-tracking branch 'origin/master' into fix/cmt-direct-disp…
yasserfaraazkhan May 26, 2026
090b52d
fix(e2e): fix bad_servers expired-cert reload and copy_link contextmenu
yasserfaraazkhan May 26, 2026
25e40fc
fix(e2e): fix Windows CI failures for deeplink, fullscreen, minimize,…
yasserfaraazkhan May 26, 2026
47fe037
fix(e2e): fix ESLint lines-around-comment and no-multiple-empty-lines…
yasserfaraazkhan May 26, 2026
2cb6e9c
fix(e2e): add blank line before comment in deeplink test (ESLint)
yasserfaraazkhan May 26, 2026
45c8a99
fix(ci): show ran/passed/failed in status checks, drop skipped count
yasserfaraazkhan May 26, 2026
2561cd3
fix(test): add missing on mock to MainWindow in popoutManager unit test
yasserfaraazkhan May 26, 2026
4d8521e
fix: address CodeRabbit inline review findings
yasserfaraazkhan May 26, 2026
8c410ed
revert: restore hardcoded S3 bucket name and URL in e2e workflow
yasserfaraazkhan May 26, 2026
8b865eb
test(popoutManager): add unit tests for registerMainWindowCloseHandle…
yasserfaraazkhan May 27, 2026
9d891fb
Desktop qa agent (#3834)
yasserfaraazkhan May 27, 2026
4d077d0
qa: fix intercom.test.js electron mock — app.once is not a function
cursoragent May 27, 2026
4bfe9d0
qa: add QA report for PR #3829
cursoragent May 27, 2026
912ee16
ci(e2e): scheduled CMT trigger + drop in-workflow cleanup call
yasserfaraazkhan Jun 1, 2026
52a3f0c
ci(e2e): harden Actions permissions + make electron install resilient
yasserfaraazkhan Jun 1, 2026
4b6764e
test: mock electron in unit suites that import it (fix flaky CI failure)
yasserfaraazkhan Jun 1, 2026
f46c763
chore: remove accidentally committed qa-report.md
yasserfaraazkhan Jun 2, 2026
cd735c8
revert(e2e): remove Cursor-automation PR server-URL feature
yasserfaraazkhan Jun 2, 2026
5cde967
revert(e2e): remove Cursor-automation logic (workflows, setup, helper…
yasserfaraazkhan Jun 2, 2026
4a44c88
docs(e2e): drop redundant AGENTS.md note; leave docs unchanged
yasserfaraazkhan Jun 2, 2026
40bbaaa
docs(cmt): correct stale cmt_run_id input description
yasserfaraazkhan Jun 2, 2026
1ddad60
Merge remote-tracking branch 'origin/master' into fix/cmt-direct-disp…
yasserfaraazkhan Jun 3, 2026
473fdf3
fix(e2e): address review — drop popout-close change, gate E2E readiness
yasserfaraazkhan Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 23 additions & 19 deletions .github/workflows/cmt-provisioner.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
name: CMT Provisioner

# This is a stub workflow. Its only purpose is to fire a workflow_run webhook
# to Matterwick, which provisions cloud servers for each server version and
# then dispatches compatibility-matrix-testing.yml with the CMT_MATRIX input.
# Lightweight trigger workflow for Compatibility Matrix Testing (CMT).
#
# Usage: Go to Actions → CMT Provisioner → Run workflow
# server_versions: comma-separated Mattermost server versions
# Example: "v11.1.0, v11.2.0, v12.0.0"
# Matterwick listens for this workflow's workflow_run:requested event, then provisions one
# Mattermost cloud instance per version in its hardcoded CMT version set (Matterwick's
# CMTServerVersions config / CMTVersions, e.g. the active ESR plus the current feature
# release) and dispatches compatibility-matrix-testing.yml with the CMT_MATRIX input.
# When compatibility-matrix-testing.yml completes, Matterwick destroys the provisioned
# instances (cleanup is keyed off the completed workflow_run, matched by commit SHA).
#
# The server-version set lives in Matterwick config (managed via gitops), so this workflow
# takes no inputs. Run it manually from the Actions tab, or let the monthly schedule fire it.

on:
workflow_dispatch:
inputs:
server_versions:
description: "Comma-separated Mattermost server versions (e.g. v11.1.0, v11.2.0)"
required: true
type: string
schedule:
- cron: "0 0 1 * *" # 00:00 UTC on the 1st of every month
workflow_dispatch: {}

# This workflow does not use GITHUB_TOKEN. Its only purpose is to emit a workflow_run event
# that Matterwick reacts to; it does not check out the repo or call the GitHub API. Drop all
# GITHUB_TOKEN scopes so the runner-issued token cannot modify the repo if a step is added later.
permissions: {}

jobs:
notify:
signal:
runs-on: ubuntu-22.04
steps:
- name: Log CMT request
env:
SERVER_VERSIONS: ${{ inputs.server_versions }}
- name: Signal Matterwick to provision CMT servers
run: |
echo "CMT Provisioner triggered"
echo "Server versions: ${SERVER_VERSIONS}"
echo "Matterwick will provision cloud instances and dispatch compatibility-matrix-testing.yml"
echo "CMT trigger started."
echo "Matterwick provisions one server per configured version and then"
echo "dispatches compatibility-matrix-testing.yml automatically."
29 changes: 4 additions & 25 deletions .github/workflows/compatibility-matrix-testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ on:
description: "The desktop version to test"
required: true
cmt_run_id:
description: "CMT provisioner run ID used for instance cleanup"
description: "CMT provisioner run ID, passed through for traceability. Instance teardown is keyed by commit SHA and handled by Matterwick when this workflow_run completes."
required: false
default: "0"
type: string
Expand Down Expand Up @@ -141,27 +141,6 @@ jobs:
description: "Compatibility Matrix Testing for ${{ inputs.DESKTOP_VERSION }} version"
status: success

cleanup-cmt-instances:
runs-on: ubuntu-22.04
if: always()
needs:
- e2e
steps:
- name: cmt/cleanup-instances
if: ${{ inputs.cmt_run_id != '0' && inputs.cmt_run_id != '' }}
env:
MATTERWICK_URL: ${{ vars.MATTERWICK_URL }}
CLEANUP_TOKEN: ${{ secrets.MATTERWICK_CLEANUP_SECRET }}
CMT_RUN_ID: ${{ inputs.cmt_run_id }}
run: |
if ! [[ "${CMT_RUN_ID}" =~ ^[0-9]+$ ]]; then
echo "ERROR: cmt_run_id '${CMT_RUN_ID}' is not a valid numeric ID"
exit 1
fi
curl -S -X POST "${MATTERWICK_URL}/cleanup_e2e" \
-H "Content-Type: application/json" \
-H "X-Cleanup-Token: ${CLEANUP_TOKEN}" \
-d "{\"repo\": \"desktop\", \"run_id\": ${CMT_RUN_ID}}" \
--fail-with-body \
--retry 3 --retry-delay 5 --retry-connrefused \
--connect-timeout 10 --max-time 30
# Instance cleanup is handled by Matterwick: when this workflow completes, GitHub sends a
# workflow_run "completed" event and Matterwick destroys the servers it provisioned for this
# run (matched by commit SHA). No in-workflow cleanup call is needed.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
110 changes: 100 additions & 10 deletions .github/workflows/e2e-functional-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,33 @@ on:
STATUS_MACOS:
description: "The status of the macOS test"
value: ${{ jobs.e2e.outputs.STATUS_MACOS }}
PASSED_LINUX:
description: "Number of passed tests on Linux"
value: ${{ jobs.e2e.outputs.PASSED_LINUX }}
PASSED_MACOS:
description: "Number of passed tests on macOS"
value: ${{ jobs.e2e.outputs.PASSED_MACOS }}
PASSED_WINDOWS:
description: "Number of passed tests on Windows"
value: ${{ jobs.e2e.outputs.PASSED_WINDOWS }}
TOTAL_LINUX:
description: "Total tests on Linux (passed + failed + skipped)"
value: ${{ jobs.e2e.outputs.TOTAL_LINUX }}
TOTAL_MACOS:
description: "Total tests on macOS (passed + failed + skipped)"
value: ${{ jobs.e2e.outputs.TOTAL_MACOS }}
TOTAL_WINDOWS:
description: "Total tests on Windows (passed + failed + skipped)"
value: ${{ jobs.e2e.outputs.TOTAL_WINDOWS }}
SKIPPED_LINUX:
description: "Number of skipped tests on Linux"
value: ${{ jobs.e2e.outputs.SKIPPED_LINUX }}
SKIPPED_MACOS:
description: "Number of skipped tests on macOS"
value: ${{ jobs.e2e.outputs.SKIPPED_MACOS }}
SKIPPED_WINDOWS:
description: "Number of skipped tests on Windows"
value: ${{ jobs.e2e.outputs.SKIPPED_WINDOWS }}
STATUS_WINDOWS:
description: "The status of the windows test"
value: ${{ jobs.e2e.outputs.STATUS_WINDOWS }}
Expand Down Expand Up @@ -130,6 +157,7 @@ jobs:
e2e:
name: e2e-on-${{ inputs.runs-on }}
runs-on: ${{ inputs.runs-on }}
# Runs untrusted PR code (npm ci / Playwright) with a read-only token.
permissions:
contents: read
defaults:
Expand All @@ -145,6 +173,15 @@ jobs:
STATUS_LINUX: ${{ steps.analyze-flaky-tests.outputs.STATUS_LINUX }}
STATUS_WINDOWS: ${{ steps.analyze-flaky-tests.outputs.STATUS_WINDOWS }}
STATUS_MACOS: ${{ steps.analyze-flaky-tests.outputs.STATUS_MACOS }}
PASSED_LINUX: ${{ steps.analyze-flaky-tests.outputs.PASSED_LINUX }}
PASSED_MACOS: ${{ steps.analyze-flaky-tests.outputs.PASSED_MACOS }}
PASSED_WINDOWS: ${{ steps.analyze-flaky-tests.outputs.PASSED_WINDOWS }}
TOTAL_LINUX: ${{ steps.analyze-flaky-tests.outputs.TOTAL_LINUX }}
TOTAL_MACOS: ${{ steps.analyze-flaky-tests.outputs.TOTAL_MACOS }}
TOTAL_WINDOWS: ${{ steps.analyze-flaky-tests.outputs.TOTAL_WINDOWS }}
SKIPPED_LINUX: ${{ steps.analyze-flaky-tests.outputs.SKIPPED_LINUX }}
SKIPPED_MACOS: ${{ steps.analyze-flaky-tests.outputs.SKIPPED_MACOS }}
SKIPPED_WINDOWS: ${{ steps.analyze-flaky-tests.outputs.SKIPPED_WINDOWS }}
steps:
- name: e2e/set-required-variables
id: variables
Expand Down Expand Up @@ -229,6 +266,18 @@ jobs:
npm ci
cd e2e && npm ci

- name: e2e/suppress-macos-dialogs
if: runner.os == 'macOS'
run: |
# Suppress the "Reopen windows" dialog that blocks Electron startup
# when a previous test instance was killed by SIGTERM/SIGKILL.
# The global-setup.ts also does this, but running it here as well ensures
# the setting is applied even if the Playwright globalSetup step is skipped.
defaults write com.github.Electron NSQuitAlwaysKeepsWindows -bool false || true
defaults write com.github.Electron ApplePersistenceIgnoreState -bool YES || true
defaults write com.apple.LaunchServices LSQuarantine -bool false || true
defaults write com.apple.CrashReporter DialogType none || true

- name: e2e/run-playwright-tests-linux
if: runner.os == 'Linux'
run: |
Expand Down Expand Up @@ -274,31 +323,72 @@ jobs:
DESKTOP_VERSION: ${{ inputs.DESKTOP_VERSION }}
CI_ENVIRONMENT_NAME: ${{ env.CI_ENVIRONMENT_NAME }}

- name: e2e/generate-html-report
id: generate-html-report
if: always()
run: |
cd e2e
if [ -d blob-report ] && find blob-report -type f | grep -q .; then
npx playwright merge-reports --reporter=html blob-report
echo "html_report_ready=true" >> "$GITHUB_OUTPUT"
else
echo "No blob report produced for this OS — skipping HTML generation."
echo "html_report_ready=false" >> "$GITHUB_OUTPUT"
fi

- name: e2e/upload-html-report-to-s3
id: upload-html-report-to-s3
if: always() && steps.generate-html-report.outputs.html_report_ready == 'true'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.MM_DESKTOP_E2E_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.MM_DESKTOP_E2E_AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-east-1
AWS_S3_BUCKET: mattermost-cypress-report
RUN_ID: ${{ github.run_id }}
RUN_ATTEMPT: ${{ github.run_attempt }}
run: |
# Per-OS report path so each platform's status check links to a clean,
# single-OS view — not an aggregated multi-OS report where counts and
# "skipped" totals are inflated by cross-OS tags.
S3_PREFIX="desktop-e2e/${RUN_ID}-${RUN_ATTEMPT}/${RUNNER_OS}"
aws s3 sync e2e/playwright-report/ "s3://${AWS_S3_BUCKET}/${S3_PREFIX}/" \
--acl public-read \
--cache-control "no-cache"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
REPORT_URL="https://${AWS_S3_BUCKET}.s3.amazonaws.com/${S3_PREFIX}/index.html"
echo "report_url=${REPORT_URL}" >> "$GITHUB_OUTPUT"
echo "Playwright report (${RUNNER_OS}) uploaded: ${REPORT_URL}" >> "$GITHUB_STEP_SUMMARY"

- name: e2e/analyze-flaky-tests
id: analyze-flaky-tests
if: always()
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
PER_OS_REPORT_URL: ${{ steps.upload-html-report-to-s3.outputs.report_url }}
with:
script: |
process.chdir('./e2e');
const { analyzeFlakyTests } = require('./utils/analyze-flaky-test.js');
const { failureCount, os } = analyzeFlakyTests();
const { failureCount, passCount, skipCount, totalCount, os } = analyzeFlakyTests();
const runUrl = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
const reportUrl = process.env.PER_OS_REPORT_URL || runUrl;
const testStatus = failureCount > 0 || Number(process.env.PLAYWRIGHT_EXIT_CODE || 0) !== 0 ? 'failure' : 'success';
const setOSOutputs = (suffix) => {
core.setOutput(`NEW_FAILURES_${suffix}`, String(failureCount));
core.setOutput(`REPORT_LINK_${suffix}`, reportUrl);
core.setOutput(`STATUS_${suffix}`, testStatus);
core.setOutput(`PASSED_${suffix}`, String(passCount));
core.setOutput(`SKIPPED_${suffix}`, String(skipCount));
core.setOutput(`TOTAL_${suffix}`, String(totalCount));
};
switch (os) {
case 'linux':
core.setOutput('NEW_FAILURES_LINUX', String(failureCount));
core.setOutput('REPORT_LINK_LINUX', runUrl);
core.setOutput('STATUS_LINUX', testStatus);
setOSOutputs('LINUX');
break;
case 'darwin':
core.setOutput('NEW_FAILURES_MACOS', String(failureCount));
core.setOutput('REPORT_LINK_MACOS', runUrl);
core.setOutput('STATUS_MACOS', testStatus);
setOSOutputs('MACOS');
break;
case 'win32':
core.setOutput('NEW_FAILURES_WINDOWS', String(failureCount));
core.setOutput('REPORT_LINK_WINDOWS', runUrl);
core.setOutput('STATUS_WINDOWS', testStatus);
setOSOutputs('WINDOWS');
break;
default:
throw new Error(`Unsupported OS: ${os}`);
Expand Down
Loading
Loading