Skip to content

chore(e2e): Trigger server creating using matterwick for e2e tests#3691

Merged
yasserfaraazkhan merged 22 commits intomasterfrom
create-e2e-instance-from-matterwick
Mar 18, 2026
Merged

chore(e2e): Trigger server creating using matterwick for e2e tests#3691
yasserfaraazkhan merged 22 commits intomasterfrom
create-e2e-instance-from-matterwick

Conversation

@yasserfaraazkhan
Copy link
Copy Markdown
Contributor

@yasserfaraazkhan yasserfaraazkhan commented Feb 9, 2026

Summary

Integrates Matterwick as the E2E test orchestrator for the desktop app. When Matterwick adds the E2E/Run label to a PR, it provisions cloud Mattermost instances and dispatches the e2e-functional.yml workflow with instance details and credentials. After tests complete, the label is automatically removed.

This PR also adds support for:

  • Compatibility Matrix Testing (CMT): Matterwick dispatches compatibility-matrix-testing.yml with a cmt_run_id and calls back to Matterwick for instance cleanup on completion.
  • Nightly E2E trigger: A dedicated workflow that Matterwick dispatches nightly to run E2E tests against the latest server version.
  • Commit status updates: Reports per-platform (linux/macos/windows) E2E status back to the PR via GitHub commit statuses.

The MASTER run type has been removed — nightly runs provide sufficient master branch coverage.

Ticket Link

SEC-9872

Checklist

  • Added or updated unit tests (required for all new features)
  • read and understood our Contributing Guidelines
  • Run E2E tests by adding label E2E/Run

Screenshots

N/A — CI/workflow changes only.

NONE

Change Impact: 🟡 Medium

Reasoning: The PR shifts E2E orchestration to an external service (Matterwick) and removes the MASTER run type across CI workflows and e2e utilities. Changes are concentrated in CI/workflows and test utilities (no production app logic), but they add external dependencies and new untested control paths, presenting moderate risk.

Regression Risk: The modifications span multiple CI workflows and shared test utility modules (notably e2e/utils/github-actions.js, e2e/utils/report.js, e2e/utils/test_cases.js, and several workflow files). New behaviors include label removal, CMT cleanup callbacks, nightly orchestration, and commit-status updates back to PRs. These introduce untested interactions with GitHub APIs and Matterwick, and removing MASTER alters title/folder mapping logic—risk is moderate given the breadth and external dependencies.

QA Recommendation: Perform focused manual QA covering: (1) Matterwick-triggered flows — provisioning, workflow dispatch, and teardown; (2) removeE2ELabel behavior across PRs (including permission and missing-label cases); (3) CMT cleanup job execution when cmt_run_id is provided and its error handling; (4) nightly runs produce expected TYPE/Zephyr folder mapping and commit status updates per platform; and (5) graceful failure modes when Matterwick is unreachable. Skipping manual QA is not recommended due to new external integrations and lack of unit tests for the added paths.

Generated by CodeRabbitAI

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a cleanup job to the e2e workflow to remove the E2E/Run label from PRs after the workflow completes, intended for runs triggered via Matterwick.

Changes:

  • Adds a new remove-e2e-label job that runs after update-final-status
  • Uses actions/github-script to find an associated PR for the workflow run and remove the E2E/Run label

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/e2e-functional.yml Outdated
Comment thread .github/workflows/e2e-functional.yml Outdated
Comment thread .github/workflows/e2e-functional.yml
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/e2e-functional.yml
Comment thread .github/workflows/e2e-functional.yml Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/e2e-functional.yml
Comment thread .github/workflows/e2e-functional.yml Outdated
Comment thread .github/workflows/e2e-functional.yml Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/e2e-functional.yml Outdated
Comment thread .github/workflows/e2e-functional.yml Outdated
yasserfaraazkhan and others added 2 commits February 10, 2026 09:37
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/e2e-functional.yml Outdated
Comment thread .github/workflows/e2e-functional.yml Outdated
yasserfaraazkhan and others added 3 commits February 10, 2026 09:39
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/e2e-functional.yml Outdated
Comment thread e2e/utils/github-actions.js Outdated
Comment thread e2e/utils/github-actions.js
yasserfaraazkhan and others added 6 commits February 10, 2026 09:54
- Add run_type input to allow callers to specify PR/RELEASE/MASTER
- Add pr_number input for automatic E2E label removal after tests
- Add remove-e2e-label job that removes E2E/Run label on completion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The /cleanup_e2e endpoint no longer requires X-Cleanup-Token auth.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

This comment was marked as spam.

@yasserfaraazkhan yasserfaraazkhan added the E2E/Run Run Desktop E2E Tests label Mar 13, 2026
@mm-cloud-bot
Copy link
Copy Markdown

E2E Test Servers Created

The following test servers have been created and are ready for E2E testing:

Tests will run against these servers. Please monitor the workflow run for progress.

@github-actions github-actions Bot removed the E2E/Run Run Desktop E2E Tests label Mar 13, 2026
All 6 entries in the darwin and linux lists were dead: the popup suite is
already CI-skipped via shouldTest(!isCI()), and every linux entry tested
a test that is already guarded with `if (process.platform !== 'linux')`.

Fix the two legitimately flaky win32 tests instead:
- MM-T1304/MM-T1306: raise mocha timeout 30s → 120s (getApp() alone can
  take up to 120s on Windows runners)
- MM-T816: replace asyncSleep(2000) with waitForFunction(isFullScreen)
  so the assertion is deterministic regardless of runner speed

With nothing left to filter, remove known_flaky_tests.json and strip the
filtering logic from analyze-flaky-test.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@yasserfaraazkhan yasserfaraazkhan added the E2E/Run Run Desktop E2E Tests label Mar 13, 2026
@mattermost mattermost deleted a comment from mm-cloud-bot Mar 13, 2026
yasserfaraazkhan and others added 2 commits March 16, 2026 11:54
Master push E2E triggers are being removed from Matterwick, so
the desktop repo no longer needs MASTER as a run type. Nightly
runs provide sufficient coverage for the master branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add permissions: issues: write to remove-e2e-label job
- Use SHA matching when selecting from multiple PRs
- Improve error messages to not assume 404 means label-only
- Add context to eslint-disable directive
@yasserfaraazkhan yasserfaraazkhan marked this pull request as ready for review March 16, 2026 07:32
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
e2e/utils/analyze-flaky-test.js (1)

12-22: Simplification looks good; consider renaming for clarity.

The removal of flaky test filtering aligns with the PR objectives. However, since the function no longer filters against known flaky tests:

  1. The variable newFailedTests is now misleading—it contains all failed tests, not just "new" ones.
  2. The function name analyzeFlakyTests no longer reflects its purpose (it just collects failures).
  3. The error return {} doesn't match the success return shape {newFailedTests, os}, which could cause downstream issues if callers expect those properties.
♻️ Optional: Improve naming and error handling consistency
-function analyzeFlakyTests() {
+function getFailedTests() {
     const os = process.platform;
     try {
         const jsonReport = readJsonFromFile(path.join(MOCHAWESOME_REPORT_DIR, 'mochawesome.json'));
         const {failedFullTitles} = generateShortSummary(jsonReport);
-        return {newFailedTests: failedFullTitles, os};
+        return {failedTests: failedFullTitles, os};
     } catch (error) {
         console.error('Error analyzing failures:', error);
-        return {};
+        return {failedTests: [], os};
     }
 }

Note: If you rename the function or return property, ensure callers are updated accordingly.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/utils/analyze-flaky-test.js` around lines 12 - 22, The function
analyzeFlakyTests no longer filters flaky tests and the name/return shape are
misleading: rename the function (e.g., collectFailedTests or getFailedTests) and
rename the returned property newFailedTests to something accurate like
failedTests; update references to generateShortSummary and the call sites
accordingly. Also make the error path return the same shape (e.g., {failedTests:
[], os}) instead of {} so callers always receive the same properties; keep use
of MOCHAWESOME_REPORT_DIR and readJsonFromFile unchanged. Ensure callers that
used analyzeFlakyTests/newFailedTests are updated to the new names.
.github/workflows/e2e-functional.yml (1)

111-135: Please keep a single label-removal implementation.

This job reimplements removeE2ELabel from e2e/utils/github-actions.js, and the two paths already diverge on PR discovery and error handling. Either call the shared helper here after checking out the repo, or remove the helper so future fixes only have one place to land.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/e2e-functional.yml around lines 111 - 135, The workflow
duplicates PR label removal logic in the remove-e2e-label job instead of reusing
the shared removeE2ELabel helper from e2e/utils/github-actions.js; update the
job to use the single shared implementation by either (A) invoking the existing
helper after checking out the repo (add an actions/checkout step and run a small
Node/JS step that imports and calls removeE2ELabel with the PR number and github
token), or (B) delete the helper and keep this job’s implementation so there is
only one place to maintain; reference the job name remove-e2e-label and the
helper function removeE2ELabel in e2e/utils/github-actions.js when making the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/e2e-functional-template.yml:
- Around line 187-189: The push case only sets BUILD_SUFFIX which leaves TYPE
and ZEPHYR_ENABLE unset and breaks report/Zephyr logic; update the "push" branch
to also set TYPE (e.g., TYPE=build or the same value used by other non-nightly
branches) and set ZEPHYR_ENABLE (e.g., ZEPHYR_ENABLE=false for non-nightly
pushes) so e2e/utils/report.js and e2e/save_report.js receive the expected
values; mirror the pattern used in the other branches for setting TYPE and
ZEPHYR_ENABLE alongside BUILD_SUFFIX to restore correct classification and
Zephyr uploads.
- Around line 37-41: The workflow declares an unused public input named TYPE;
remove the TYPE input declaration (the "TYPE:" block) from the workflow inputs
to avoid confusion, or alternatively modify the e2e/set-required-variables step
to read and honor inputs.TYPE (falling back to the existing event-derived logic)
so callers like e2e-functional.yml can actually control report classification;
specifically target the inputs block where "TYPE" is defined and either delete
that entry or add logic in the e2e/set-required-variables step to use
inputs.TYPE when present.

---

Nitpick comments:
In @.github/workflows/e2e-functional.yml:
- Around line 111-135: The workflow duplicates PR label removal logic in the
remove-e2e-label job instead of reusing the shared removeE2ELabel helper from
e2e/utils/github-actions.js; update the job to use the single shared
implementation by either (A) invoking the existing helper after checking out the
repo (add an actions/checkout step and run a small Node/JS step that imports and
calls removeE2ELabel with the PR number and github token), or (B) delete the
helper and keep this job’s implementation so there is only one place to
maintain; reference the job name remove-e2e-label and the helper function
removeE2ELabel in e2e/utils/github-actions.js when making the change.

In `@e2e/utils/analyze-flaky-test.js`:
- Around line 12-22: The function analyzeFlakyTests no longer filters flaky
tests and the name/return shape are misleading: rename the function (e.g.,
collectFailedTests or getFailedTests) and rename the returned property
newFailedTests to something accurate like failedTests; update references to
generateShortSummary and the call sites accordingly. Also make the error path
return the same shape (e.g., {failedTests: [], os}) instead of {} so callers
always receive the same properties; keep use of MOCHAWESOME_REPORT_DIR and
readJsonFromFile unchanged. Ensure callers that used
analyzeFlakyTests/newFailedTests are updated to the new names.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: edd44003-cde2-48c5-8851-2887aa334f0d

📥 Commits

Reviewing files that changed from the base of the PR and between 3a3aa0a and 69f4c87.

📒 Files selected for processing (11)
  • .github/workflows/compatibility-matrix-testing.yml
  • .github/workflows/e2e-functional-template.yml
  • .github/workflows/e2e-functional.yml
  • e2e/save_report.js
  • e2e/specs/deep_linking/deeplink.test.js
  • e2e/specs/menu_bar/full_screen.test.js
  • e2e/utils/analyze-flaky-test.js
  • e2e/utils/github-actions.js
  • e2e/utils/known_flaky_tests.json
  • e2e/utils/report.js
  • e2e/utils/test_cases.js
💤 Files with no reviewable changes (3)
  • e2e/utils/test_cases.js
  • e2e/utils/known_flaky_tests.json
  • e2e/utils/report.js

Comment thread .github/workflows/e2e-functional-template.yml
Comment thread .github/workflows/e2e-functional-template.yml
cursor Bot pushed a commit that referenced this pull request Mar 18, 2026
Address CodeRabbit review comments on PR #3691:

1. The inputs.TYPE declaration was unused — the e2e/set-required-variables
   step derived TYPE from event/flag logic and never read the input. Now
   the push case honors inputs.TYPE (default: 'PR'), making the input
   actually functional.

2. The push case only set BUILD_SUFFIX, leaving TYPE and ZEPHYR_ENABLE
   unset. This caused report.js to fall back to a generic title and
   save_report.js to skip Zephyr uploads. Now TYPE is set from
   inputs.TYPE and ZEPHYR_ENABLE is explicitly set to false for push
   events (the nightly override still correctly sets ZEPHYR_ENABLE=true
   when applicable).

Co-authored-by: yasser khan <attitude3cena.yf@gmail.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (5)
src/common/servers/serverManager.ts (1)

55-57: Consider defensive handling for missing server entries.

The non-null assertion ! assumes all IDs in serverOrder have corresponding entries in servers. While this should be true under normal operation, a defensive check would prevent crashes if the state becomes inconsistent.

💡 Optional: Add defensive filter
     getOrderedServers = () => {
-        return this.serverOrder.map((id) => this.servers.get(id)!);
+        return this.serverOrder.map((id) => this.servers.get(id)).filter((server): server is MattermostServer => server !== undefined);
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/common/servers/serverManager.ts` around lines 55 - 57, The
getOrderedServers method uses a non-null assertion when mapping serverOrder to
servers which can throw if an ID is missing; update getOrderedServers to
defensively handle missing entries by filtering out undefined lookups from
this.servers.get(id) (or substituting a placeholder) before returning the array
so that serverOrder and servers inconsistencies don’t crash the process—refer to
getOrderedServers, serverOrder and servers to locate and fix the mapping logic.
src/common/config/index.ts (1)

119-119: Verify the viewLimit logic handles edge cases correctly.

The ternary expression this.localConfigData?.viewLimit ? Math.max(...) : undefined will evaluate to undefined when viewLimit is 0 (falsy), though 0 would be an unusual but technically valid value. If viewLimit: 0 should be treated as a valid setting, consider using an explicit !== undefined check instead.

💡 Optional: More explicit undefined check
-            viewLimit: this.localConfigData?.viewLimit ? Math.max(this.localConfigData.viewLimit, servers.length) : undefined,
+            viewLimit: this.localConfigData?.viewLimit !== undefined ? Math.max(this.localConfigData.viewLimit, servers.length) : undefined,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/common/config/index.ts` at line 119, The viewLimit assignment uses a
falsy check that treats 0 as undefined; update the logic in the config
construction (the viewLimit expression referencing
this.localConfigData?.viewLimit and servers.length) to explicitly test for
undefined (e.g., this.localConfigData?.viewLimit !== undefined) before applying
Math.max so that a configured 0 is preserved as a valid value rather than being
coerced to undefined.
src/app/views/webContentEvents.test.js (1)

57-59: Add a direct mattermost:// regression case.

Lines 57-59 stub the app protocol, but the expanded matrix still only asserts third-party schemes. A refactor that accidentally sends first-party deep links through allowProtocolDialog or shell.openExternal would currently slip through this suite.

Based on learnings, WebContentsEventManager centralizes navigation guards for security and UX control.

e2e/specs/mattermost/external_links.test.js (1)

45-141: Use skipped tests here instead of making Linux a silent no-op.

The runtime if drops both cases from the suite on Linux, so the Linux job goes green with zero coverage rather than reporting an explicit skip. For a cross-platform E2E signal, that’s easy to misread.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/specs/mattermost/external_links.test.js` around lines 45 - 141, The tests
are being silently dropped on Linux due to the runtime "if (process.platform !==
'linux')" which makes the suite show zero tests instead of an explicit skip;
change the control so the two tests with titles MM-T_EL_1 and MM-T_EL_2 are
explicitly skipped on Linux (e.g., use conditional test skipping like
(process.platform === 'linux' ? it.skip : it)(...) or wrap them with
describe.skip when process.platform === 'linux') rather than omitting them,
keeping the existing test bodies and the shell.openExternal spy and assertions
intact so Linux runs report an explicit skipped status.
e2e/specs/policy/policy.test.js (1)

78-84: Consider additional escaping for PowerShell metacharacters in server names.

The escaping only handles single quotes ('''), but server names or URLs containing backticks, dollar signs, or other PowerShell metacharacters could still cause issues when interpolated into the script string before encoding. Since psEncode receives the already-interpolated script, malicious or unusual input could still break the command.

However, this is a low-risk concern for controlled E2E test data.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/specs/policy/policy.test.js` around lines 78 - 84, The current JS-only
escaping for single quotes (safeName/safeUrl) is insufficient for some
PowerShell metacharacters; update the sanitization before embedding into the
PowerShell script so names/URLs also escape backticks and dollar signs (and any
other problematic metacharacters you observe) — e.g., extend the replace calls
that produce safeName and safeUrl to also replace ` with `` or with the
PowerShell-safe escape sequence and to escape $ (e.g., '`$' or doubling strategy
consistent with your quoting), or alternatively avoid interpolation by passing
the data into PowerShell via ConvertTo-Json / stdin and reconstructing registry
entries inside the PS script; modify the code around safeName/safeUrl and the
run(...) invocation (and consider psEncode usage) so the final PowerShell
command cannot be broken by backticks or $ in input.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/e2e-functional.yml:
- Around line 111-118: The cleanup job remove-e2e-label currently only needs
e2e-tests and uses always(), which lets it run before e2e-policy-tests finishes
or even when the matrix preparation skipped E2E; update the job to depend on
both e2e-tests and e2e-policy-tests by adding e2e-policy-tests to needs and
remove the always() condition so remove-e2e-label will wait for both E2E jobs to
complete and won’t run when prepare-matrix causes the E2E jobs to be skipped
(keep the inputs.pr_number != '' check).

In `@CLAUDE.md`:
- Around line 25-56: Add the appropriate language identifiers to the fenced code
blocks in CLAUDE.md (the block shown around lines 25-56 and the other block
around 150-153) so markdownlint MD040 warnings are resolved; locate the
triple-backtick fences in those sections and change them from ``` to ```text or
```txt (or a more specific language if applicable) ensuring both opening fences
include the language tag.

In `@i18n/de.json`:
- Line 304: Update the translation for the key
renderer.components.settingsPage.checkSpelling.specifyURL to correct the casing
of "URL" and improve the German phrasing; replace the current string with a
clearer sentence such as: "Geben Sie die URL an, von der die
Wörterbuchdefinitionen geladen/abgerufen werden." Ensure the change only updates
the value for that key.

In `@i18n/ru.json`:
- Around line 190-192: The three translation entries
(renderer.components.configureServer.error.basicAuthRequired,
renderer.components.configureServer.error.clientCertRequired,
renderer.components.configureServer.error.preAuthRequired) use informal
"ты/тебе" and must be changed to the formal second person ("Вы/Вам") to match
the rest of the Russian locale; update the phrasing accordingly (e.g., "Вам
будет предложено…" and adjust verb forms/capitalization) and apply the same
normalization to the other affected ranges referenced (lines 208-222, 287-348)
so all server/configuration messages consistently use the formal form.
- Line 69: The translation for the key main.menus.app.edit.pasteAndMatchStyle
currently reads as preserving source formatting but should indicate matching the
destination/style of the surrounding content; update the value for
"main.menus.app.edit.pasteAndMatchStyle" to a Russian phrase that conveys "paste
and match destination style" (for example: "Вставить с оформлением по месту
(соответствует стилю окружения)" or a similarly concise wording that clearly
means matching the destination style).
- Line 404: The translation for the i18n key
renderer.modals.certificate.certificateModal.subject uses "Тема" (meaning
topic); change it to a certificate-appropriate term such as "Субъект" or
"Субъект сертификата" so the X.509 dialog correctly denotes the certificate
subject; update the value for
renderer.modals.certificate.certificateModal.subject accordingly.

In `@src/app/views/webContentEventsCommon.test.ts`:
- Around line 12-15: Update the misleading test comment so it reflects what is
actually being mocked: change the description that mentions
"electron-builder.json protocols" to something like "mock common/constants
MATTERMOST_PROTOCOL" near the jest.mock('common/constants') call; ensure the
comment references MATTERMOST_PROTOCOL so future readers understand the mock
target and purpose in webContentEventsCommon.test.ts.

In `@src/common/views/MattermostView.ts`:
- Around line 57-63: The concatenation logic for building the URL in
MattermostView incorrectly removes only a leading slash when the server path is
root, causing subpath servers to produce URLs like
"https://host/subpathchannels/..."; update the normalization to ensure exactly
one separator between server.url.pathname and this.initialPath by trimming any
trailing slash from server.url.pathname and any leading slash from initialPath
before joining, then pass the joined string into parseURL; update the code that
references initialPath, server.url.pathname, and parseURL in the MattermostView
constructor (or where the URL is built) and add a regression test that
constructs a MattermostView with a server that has a subpath and an initialPath
without a leading slash (e.g., 'channels/town-square') to assert the resulting
URL includes '/subpath/channels/town-square'.

In `@src/renderer/CLAUDE.md`:
- Around line 22-28: The fenced code block in src/renderer/CLAUDE.md is missing
a language tag which triggers markdownlint MD040; update the backticks for the
snippet that starts with "components/" to include a language tag (e.g., change
``` to ```text) so the block is explicitly marked as plain text and the linter
will accept it.

---

Nitpick comments:
In `@e2e/specs/mattermost/external_links.test.js`:
- Around line 45-141: The tests are being silently dropped on Linux due to the
runtime "if (process.platform !== 'linux')" which makes the suite show zero
tests instead of an explicit skip; change the control so the two tests with
titles MM-T_EL_1 and MM-T_EL_2 are explicitly skipped on Linux (e.g., use
conditional test skipping like (process.platform === 'linux' ? it.skip :
it)(...) or wrap them with describe.skip when process.platform === 'linux')
rather than omitting them, keeping the existing test bodies and the
shell.openExternal spy and assertions intact so Linux runs report an explicit
skipped status.

In `@e2e/specs/policy/policy.test.js`:
- Around line 78-84: The current JS-only escaping for single quotes
(safeName/safeUrl) is insufficient for some PowerShell metacharacters; update
the sanitization before embedding into the PowerShell script so names/URLs also
escape backticks and dollar signs (and any other problematic metacharacters you
observe) — e.g., extend the replace calls that produce safeName and safeUrl to
also replace ` with `` or with the PowerShell-safe escape sequence and to escape
$ (e.g., '`$' or doubling strategy consistent with your quoting), or
alternatively avoid interpolation by passing the data into PowerShell via
ConvertTo-Json / stdin and reconstructing registry entries inside the PS script;
modify the code around safeName/safeUrl and the run(...) invocation (and
consider psEncode usage) so the final PowerShell command cannot be broken by
backticks or $ in input.

In `@src/common/config/index.ts`:
- Line 119: The viewLimit assignment uses a falsy check that treats 0 as
undefined; update the logic in the config construction (the viewLimit expression
referencing this.localConfigData?.viewLimit and servers.length) to explicitly
test for undefined (e.g., this.localConfigData?.viewLimit !== undefined) before
applying Math.max so that a configured 0 is preserved as a valid value rather
than being coerced to undefined.

In `@src/common/servers/serverManager.ts`:
- Around line 55-57: The getOrderedServers method uses a non-null assertion when
mapping serverOrder to servers which can throw if an ID is missing; update
getOrderedServers to defensively handle missing entries by filtering out
undefined lookups from this.servers.get(id) (or substituting a placeholder)
before returning the array so that serverOrder and servers inconsistencies don’t
crash the process—refer to getOrderedServers, serverOrder and servers to locate
and fix the mapping logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 501f6f0b-ba1f-4aa3-a437-8e42e3654d73

📥 Commits

Reviewing files that changed from the base of the PR and between 69f4c87 and a7353b5.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (75)
  • .eslintrc.json
  • .github/actions/install-os-dependencies/action.yaml
  • .github/workflows/build-for-pr.yml
  • .github/workflows/ci.yaml
  • .github/workflows/compatibility-matrix-testing.yml
  • .github/workflows/e2e-functional-template.yml
  • .github/workflows/e2e-functional.yml
  • .github/workflows/nightly-main.yml
  • .github/workflows/nightly-rainforest.yml
  • .github/workflows/release-mas.yaml
  • .github/workflows/release.yaml
  • .github/workflows/scorecards-analysis.yml
  • CLAUDE.md
  • NOTICE.txt
  • e2e/modules/environment.js
  • e2e/package.json
  • e2e/specs/mattermost/external_links.test.js
  • e2e/specs/policy/policy.test.js
  • electron-builder.json
  • electron-builder.ts
  • i18n/de.json
  • i18n/en.json
  • i18n/nb_NO.json
  • i18n/nl.json
  • i18n/pl.json
  • i18n/ru.json
  • i18n/sv.json
  • package.json
  • scripts/patch_mas_version.sh
  • src/app/CLAUDE.md
  • src/app/mainWindow/serverDropdownView.ts
  • src/app/navigationManager.test.js
  • src/app/navigationManager.ts
  • src/app/preload/CLAUDE.md
  • src/app/preload/internalAPI.js
  • src/app/serverHub.test.js
  • src/app/serverHub.ts
  • src/app/views/CLAUDE.md
  • src/app/views/loadingScreen.test.js
  • src/app/views/loadingScreen.ts
  • src/app/views/pluginsPopUps.test.js
  • src/app/views/pluginsPopUps.ts
  • src/app/views/webContentEvents.test.js
  • src/app/views/webContentEvents.ts
  • src/app/views/webContentEventsCommon.test.ts
  • src/app/views/webContentEventsCommon.ts
  • src/common/CLAUDE.md
  • src/common/Validator.ts
  • src/common/config/CLAUDE.md
  • src/common/config/index.test.js
  • src/common/config/index.ts
  • src/common/constants.ts
  • src/common/servers/serverManager.test.js
  • src/common/servers/serverManager.ts
  • src/common/utils/url.test.js
  • src/common/utils/url.ts
  • src/common/views/MattermostView.test.js
  • src/common/views/MattermostView.ts
  • src/main/CLAUDE.md
  • src/main/ParseArgs.ts
  • src/main/app/initialize.test.js
  • src/main/app/initialize.ts
  • src/main/app/utils.ts
  • src/main/diagnostics/CLAUDE.md
  • src/main/notifications/CLAUDE.md
  • src/main/security/CLAUDE.md
  • src/main/security/allowProtocolDialog.test.js
  • src/main/security/allowProtocolDialog.ts
  • src/main/security/preAuthManager.test.js
  • src/main/security/preAuthManager.ts
  • src/renderer/CLAUDE.md
  • src/renderer/dropdown.tsx
  • src/renderer/utils.ts
  • src/types/config.ts
  • src/types/window.ts
💤 Files with no reviewable changes (7)
  • src/app/preload/internalAPI.js
  • .github/actions/install-os-dependencies/action.yaml
  • src/main/security/preAuthManager.ts
  • electron-builder.json
  • src/app/mainWindow/serverDropdownView.ts
  • scripts/patch_mas_version.sh
  • src/types/window.ts
✅ Files skipped from review due to trivial changes (7)
  • src/main/notifications/CLAUDE.md
  • src/common/config/CLAUDE.md
  • src/app/CLAUDE.md
  • src/main/security/CLAUDE.md
  • src/main/diagnostics/CLAUDE.md
  • src/app/preload/CLAUDE.md
  • src/common/CLAUDE.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/compatibility-matrix-testing.yml

Comment thread .github/workflows/e2e-functional.yml
Comment thread CLAUDE.md
Comment thread i18n/de.json
Comment thread i18n/ru.json
Comment thread i18n/ru.json
Comment thread i18n/ru.json
Comment thread src/app/views/webContentEventsCommon.test.ts
Comment thread src/common/views/MattermostView.ts
Comment thread src/renderer/CLAUDE.md
@yasserfaraazkhan yasserfaraazkhan force-pushed the create-e2e-instance-from-matterwick branch from 3116c1f to 69f4c87 Compare March 18, 2026 07:06
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
.github/workflows/e2e-functional.yml (1)

111-118: ⚠️ Potential issue | 🟠 Major

Wait for the whole E2E workflow before clearing E2E/Run.

Line 118 can remove the label while e2e-policy-tests or update-final-status are still running, and always() also lets this fire when e2e-tests was skipped after matrix prep failed. That makes the PR look done before this workflow actually is.

Suggested fix
   remove-e2e-label:
     name: Remove E2E label from PR
     runs-on: ubuntu-22.04
     permissions:
       issues: write
     needs:
       - e2e-tests
-    if: always() && inputs.pr_number != ''
+      - e2e-policy-tests
+      - update-final-status
+    if: |
+      always() &&
+      inputs.pr_number != '' &&
+      needs.e2e-tests.result != 'skipped' &&
+      needs.e2e-tests.result != 'cancelled'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/e2e-functional.yml around lines 111 - 118, The
remove-e2e-label job runs too early; update its needs to wait for the entire E2E
workflow before removing the label by adding the remaining end-of-workflow jobs
(e.g., e2e-policy-tests and update-final-status) to its needs list so
remove-e2e-label depends on e2e-tests, e2e-policy-tests, and update-final-status
(keep the existing if condition for inputs.pr_number as appropriate).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/compatibility-matrix-testing.yml:
- Around line 13-17: Validate and sanitize the cmt_run_id workflow input before
embedding it into the JSON payload in the Matterwick cleanup callback: ensure
cmt_run_id contains only digits (or convert/normalize it) and escape/quote it so
the generated JSON is always valid; remove the silent failure pattern that uses
"|| echo" and instead propagate or explicitly log and fail on errors from the
cleanup command so the workflow can surface and handle failures; update the
cleanup step to reject non-numeric cmt_run_id values (or fail fast with a clear
error message) and to return a non-zero exit code when the cleanup request
fails.

In @.github/workflows/e2e-functional.yml:
- Around line 31-35: The workflow currently determines TYPE from github.ref_name
which reflects the dispatching branch, so change the logic that sets TYPE (and
any related env assignment that inspects github.ref_name) to use the workflow
input inputs.version_name (DESKTOP_VERSION) instead; update any conditional that
maps PR/RELEASE (the code referencing github.ref_name and TYPE) to examine
inputs.version_name (or DESKTOP_VERSION) and set TYPE accordingly, and apply the
same replacement for the other occurrence noted in the file.

---

Duplicate comments:
In @.github/workflows/e2e-functional.yml:
- Around line 111-118: The remove-e2e-label job runs too early; update its needs
to wait for the entire E2E workflow before removing the label by adding the
remaining end-of-workflow jobs (e.g., e2e-policy-tests and update-final-status)
to its needs list so remove-e2e-label depends on e2e-tests, e2e-policy-tests,
and update-final-status (keep the existing if condition for inputs.pr_number as
appropriate).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: aa77a663-9a76-456c-81b8-c2446daa2698

📥 Commits

Reviewing files that changed from the base of the PR and between a7353b5 and 72fb418.

📒 Files selected for processing (3)
  • .github/workflows/compatibility-matrix-testing.yml
  • .github/workflows/e2e-functional-template.yml
  • .github/workflows/e2e-functional.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/e2e-functional-template.yml

Comment thread .github/workflows/compatibility-matrix-testing.yml
Comment thread .github/workflows/e2e-functional.yml
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/compatibility-matrix-testing.yml (1)

144-165: Validation properly addresses the input injection concern.

The numeric regex check at lines 157-160 ensures CMT_RUN_ID is safe before interpolation, and the --fail-with-body flag surfaces HTTP errors.

Optional improvement for network resilience.

The -s flag silences both progress and error output, which could hide debugging information on failure. Adding timeouts and retries would improve reliability for transient network issues.

♻️ Optional: Add error visibility and retry handling
-          curl -s -X POST "${MATTERWICK_URL}/cleanup_e2e" \
+          curl --silent --show-error \
+            --connect-timeout 10 \
+            --max-time 60 \
+            --retry 2 \
+            --retry-all-errors \
+            -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
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/compatibility-matrix-testing.yml around lines 144 - 165,
The curl invocation in the cleanup-cmt-instances step currently uses -s which
silences error output and lacks retries/timeouts; update the curl command (the
one that posts to "${MATTERWICK_URL}/cleanup_e2e" using CMT_RUN_ID and
CLEANUP_TOKEN) to make failures visible and resilient by removing -s (or replace
with -S), and add sensible curl options like --retry 3 --retry-delay 5
--retry-connrefused --connect-timeout 10 --max-time 30 so transient network
errors are retried and timeouts are bounded while still preserving
--fail-with-body to surface HTTP error bodies.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/compatibility-matrix-testing.yml:
- Around line 144-165: The curl invocation in the cleanup-cmt-instances step
currently uses -s which silences error output and lacks retries/timeouts; update
the curl command (the one that posts to "${MATTERWICK_URL}/cleanup_e2e" using
CMT_RUN_ID and CLEANUP_TOKEN) to make failures visible and resilient by removing
-s (or replace with -S), and add sensible curl options like --retry 3
--retry-delay 5 --retry-connrefused --connect-timeout 10 --max-time 30 so
transient network errors are retried and timeouts are bounded while still
preserving --fail-with-body to surface HTTP error bodies.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 61eb9ae6-8316-4e6b-8d58-39af7d53a29b

📥 Commits

Reviewing files that changed from the base of the PR and between 72fb418 and 85f7fed.

📒 Files selected for processing (4)
  • .github/workflows/cmt-provisioner.yml
  • .github/workflows/compatibility-matrix-testing.yml
  • .github/workflows/e2e-functional.yml
  • .github/workflows/e2e-nightly-trigger.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/e2e-functional.yml

@yasserfaraazkhan yasserfaraazkhan enabled auto-merge (squash) March 18, 2026 14:41
@yasserfaraazkhan yasserfaraazkhan removed the E2E/Run Run Desktop E2E Tests label Mar 18, 2026
@dryrunsecurity
Copy link
Copy Markdown

DryRun Security

This pull request introduces a critical shell injection risk: the workflow .github/workflows/e2e-functional-template.yml directly interpolates the workflow input ${{ inputs.TYPE }} into a bash script (in the e2e/set-required-variables step), allowing shell metacharacter injection if a malicious value is supplied via workflow_dispatch or another triggering workflow. Although workflow_dispatch limits who can run it, the input is treated as trusted and should be sanitized or safely quoted to prevent command injection.

🔴 Shell Injection in .github/workflows/e2e-functional-template.yml (drs_3282471b)
Vulnerability Shell Injection
Description The workflow e2e-functional-template.yml uses ${{ inputs.TYPE }} within a bash script in a way that allows shell metacharacter injection. While inputs.TYPE is technically a workflow input that requires workflow_dispatch trigger (which typically limits who can run it, often to repository maintainers or authorized users), it is treated as trusted input and directly interpolated into a bash script in the e2e/set-required-variables step. Because it is possible for a user to trigger e2e-functional.yml (and thus e2e-functional-template.yml) with arbitrary values for TYPE through workflow_dispatch or via other workflows, this allows a malicious actor to inject shell commands.

INPUT_TYPE="${{ inputs.TYPE }}"
case "${{ github.event_name }}" in
"pull_request")
echo "BUILD_SUFFIX=desktop-pr-${RUNNER_OS}" >> $GITHUB_OUTPUT


Comment to provide feedback on these findings.

Report false positive: @dryrunsecurity fp [FINDING ID] [FEEDBACK]
Report low-impact: @dryrunsecurity nit [FINDING ID] [FEEDBACK]

Example: @dryrunsecurity fp drs_90eda195 This code is not user-facing

All finding details can be found in the DryRun Security Dashboard.

@yasserfaraazkhan yasserfaraazkhan merged commit e151631 into master Mar 18, 2026
20 checks passed
@yasserfaraazkhan yasserfaraazkhan deleted the create-e2e-instance-from-matterwick branch March 18, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants