* MM-70615: Update connection string formatting in configuration output and logs
Only the URL form of a PostgreSQL connection string is described with its
non-credential parameters preserved. Any other form is reported as a fully
redacted setting instead.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* MM-70615: Describe connection string parse failures on their own
The reason reported by url.Parse is kept; the connection string it was given
is not.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* MM-70615: Report connection string parse failures with a clearer prefix
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* MM-70615: Consolidate the connection string formatting tests
Fold the per-format functions into the table-driven tests that already cover
SanitizeDataSource and DatabaseStore.String, keeping every case as a row.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* MM-70615: Pin described postgresql URLs in DatabaseStore tests
Require accepted connection strings to produce a non-empty description
and record the expected postgresql URL form.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* MM-70615: Retrigger CI after a Docker Hub pull reset
Postgres shard 0 failed during dependency image pull before tests ran.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* MM-70639: Fix flaky TestGetMattermostLog under fully parallel tests
The test asserted that mattermost.log did not exist while the logger
was configured to write to that exact path. Enabling file logging
installs a live file target, so any record written before the read
recreated the file and the assertion failed. The earlier fix in #36927
flushed and removed the file first, which only helps if the target had
already opened its handle. A freshly installed target has not, so the
next record recreated it.
Unrelated records reached that logger because initLogging
unconditionally claimed the process wide logging globals, both the
logger backing package level mlog calls and the redirected standard
library logger. A test binary runs many PlatformService instances
concurrently, so whichever one configured itself last captured every
package level mlog call in the process, including those from unrelated
tests, and routed them into its own log targets. It only reproduces in
CI because fully parallel mode is off by default locally.
Changes:
- Pin LogSettings.FileLevel to "fatal" while the missing-file case is
exercised so the file target never opens mattermost.log. GetLogFile
does not consult FileLevel, so coverage is unchanged.
- Add a DisableGlobalLogger option and apply it in the shared test
helpers (platform, app, api4, slashcommands, web, jobs). The default
is unchanged, so every non test caller keeps the current behavior.
- Resolve symlinks on the logging root in ValidateLogFilePath the same
way the candidate path already was. Resolving only one side rejected
legitimate paths whenever an ancestor was a symlink, which is why
these tests have never passed on macOS (/var points at /private/var).
A path whose leaf does not exist now resolves back to its deepest
existing ancestor, which also stops a not yet created file under a
symlinked directory from validating as inside the root.
- Ignore server/tests/big_testplugin.tar.gz, a 111MB fixture generated
by TestPlugin that is only removed when the test passes.
* Add dot release docs for server v11.7.12 (ESR)
Split out of #39004, which covered v11.11.2, v11.10.3 and v11.7.12
together, so the ESR release can land on its own schedule.
Content is unchanged from that PR:
- deploy-rhel.mdx / deploy-tar.mdx: Current ESR -> 11.7.12
- mattermost-server-releases.mdx: v11.7 download and SBOM links
- mattermost-v11-changelog.mdx: new 11.7.12 entry
- version-archive.mdx: Enterprise and Team entries for v11.7
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nrmq4ezefYWqa9YkxtX3mR
* Update mattermost-v11-changelog.mdx
* Update version-archive.mdx
---------
Co-authored-by: Claude <noreply@anthropic.com>
* docs: add For Evaluators hub with 1-hour cloud preview CTA.
Introduce /for-evaluators pages (off-sidebar for now) and a TryMattermostCTA that starts the hosted preview via mattermost.com/sign-up.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: add For Evaluators persona card on the docs home page.
Match the existing /for/* landing pattern and surface evaluators in the starting-point CardGrid.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: move For Evaluators into the specialized personas row.
Keep the primary home grid as the four core personas and place Evaluators with the compact specialized chips.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: drop duplicate for-evaluators pages; link to existing guides.
Point the For Evaluators persona at the canonical Quick Start Evaluation page and the marketing sign-up for the 1-hour preview. Remove Marketo implementation detail from user-facing docs copy.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: nest 1-hour cloud preview under Quick Start Evaluation.
Move the existing Docker/Azure guide into a folder and add a plain-language 1-hour preview page beside it so both appear in the Deployment Guide sidebar.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: drop duplicate Try Mattermost CTA on For Evaluators.
The Start here card already links to the 1-hour cloud preview page.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: link Demo Library from the For Evaluators start grid.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: drop For from the Evaluators persona title.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: make Quick Start Evaluation an overview with child pages.
Keep the section index high-level and move the Docker/Azure instructions to a sibling page beside the 1-hour cloud preview.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: split Docker and Azure evaluation pages and mute the preview CTA.
Use brand sand instead of marigold for the 1-hour preview button, put Evaluators last among specialized personas, drop the redundant Important callout, and split Docker vs Azure like other deployment methods.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: list the three evaluator try-it options on the home chip.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* MM-70922: Download media gallery attachments as a single zip
* add a loading spinner to the download button
---------
Co-authored-by: Nevyana Angelova <nevyangelova@Nevy-Macbook-16-2025.local>
* Bump mattermost/pdf for content-stream array parsing fix
Co-authored-by: Cursor <cursoragent@cursor.com>
* Set MM-T622 webhook icon on the hook after enabling overrides
Payload icon_url does not always become the posted avatar even when
EnablePostIconOverride is already on. Store the same fixture URL on the
incoming hook after the flags are enabled, matching the path MM-T620 uses.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Stage session-attributes dirty-nav via Enable instead of TTL
The unsaved-changes guard only needs a dirty page. Staging TTL opened a
nested submenu that flakes under Playwright. Enable is a single click;
TTL presets stay covered by the persist test.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Make MM-T1773 expect FIPS range error when empty min length is saved
Empty Minimum password length is sent as 5. On FIPS that is below the
14-character minimum, so the save is rejected and the custom value remains.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Allow post-preview scroll tests to observe embed height growth
Permalink embeds can grow after first paint while remaining pinned to
the bottom. Assert distanceFromBottom stays 0 instead of requiring a
single observation.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Use production at-bottom threshold in post-preview scroll tests
Keep observation-count checks, then require scrollHeight > 0 and
distanceFromBottom <= 100 (BUFFER_TO_BE_CONSIDERED_BOTTOM) on every
observation.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Revert "Use production at-bottom threshold in post-preview scroll tests"
This reverts commit 7e3d926362.
* Revert "Allow post-preview scroll tests to observe embed height growth"
This reverts commit f44f7f3941.
* Revert "Stage session-attributes dirty-nav via Enable instead of TTL"
This reverts commit f1be0169b7.
* Revert "Set MM-T622 webhook icon on the hook after enabling overrides"
This reverts commit 9b9509d439.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
Drop the be catalogs from the server, webapp, and glossary, remove the locale
from the server's supported list and the webapp's language map, regenerate
imports.ts, and update the docs that enumerate available languages.
Users with Belarusian selected fall back to the default locale: the server
falls back when no catalog is loaded, and the webapp maps unavailable locales
to DefaultClientLocale.
docs/pdf was never linked, never CI'd, and is not part of the hosted site.
Remove the tree and the leftover gitignore/writer deny-list references.
Co-authored-by: Cursor <cursoragent@cursor.com>
moment-timezone 0.5.38 bundles IANA tzdata 2022e, so the webapp's
moment.tz offset math misses the 2026 rule changes. British Columbia,
Alberta and the Northwest Territories stop observing DST on
2026-11-01, and Morocco moved to permanent UTC on 2026-09-20.
0.6.4 bundles tzdata 2026d, the first release that covers all four.
The mattermost-redux range is bumped too, since ^0.5.38 excludes 0.6.x.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* MM-70640: Update EXIF metadata handling when reading image orientation
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* chore: match max login attempts e2e to current login error banner
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Address PR feedback: 0 answered, 2 resolved, 0 declined
- Add worst-case PNG/TIFF/WebP cases to TestGetImageOrientationLargeMetadata
exercising the most expensive input the tag-size limit still allows, under
the existing time bound; make the payload-size assertion per-payload.
- Revert max_login_attempts.spec.ts to master, restoring the exact
full-message lockout assertion.
* chore: retrigger CI after unrelated Cypress flake
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* chore: retrigger CI after unrelated Enterprise test flake
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* fix: set webhook username/icon override via API in Cypress helper
The Integration Management Save button often stays disabled after a
forced radio check, which flakes MM-T622 after in-run retest.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Apply EXIF orientation when setting a team icon
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Return an error when the team icon file cannot be rewound
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Add description for emoji too-large-to-process translation string
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* chore: retrigger CI after module proxy failure
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* chore: retrigger CI after FIPS module proxy failure
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Loosen time bound for worst-case EXIF orientation tests under -race
Co-authored-by: Cursor <cursoragent@cursor.com>
* Use the server SiteURL for permalinks in unread post list scroll spec
Co-authored-by: mattermost-code <matty-code@mattermost.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
Co-authored-by: David Krauser <david@krauser.org>
Co-authored-by: Mattermost Build <build@mattermost.com>
* When a bot authors the source PR, request docs-draft review from a human reviewer of that PR instead of the bot.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Keep the docs draft running if GitHub reviewer lookup fails.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs: resolve raw HTML link and image paths through useBaseUrl
Docusaurus prepends `baseUrl` to markdown-syntax links (`[text](/path)`) but
never to site-absolute paths written in raw HTML/JSX attributes. Those values
ship verbatim, which is correct only while `baseUrl` is `/`.
Convert the 221 raw `<a href="/...">` anchors across 22 files under docs/main
and the 3 raw `<img src="/img/...">` tags in docs/develop to
`useBaseUrl('/...')`, matching how images in the same table rows already
resolve their paths. Link targets, link text and table structure are unchanged.
Add scripts/check-base-url-attrs.mjs and run it as the first step of
`prebuild` so the build fails fast on any new occurrence.
* docs(site): match CommonMark fence closing in baseUrl attr check
Toggle on any fence-like line could exit a block early; track the
opening marker and only close with the same character of sufficient length.
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(site): also flag JSX string-literal href/src in baseUrl check
Quoted attributes alone miss href={"/path"} / src={'/path'}, which
bypass baseUrl the same way. Scan both forms through one validation path.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* playwright: allow ensureFeatureFlag to set multiple flags, remove skipIfFeatureFlagNotSet
ensureFeatureFlag now accepts either a single (flagName, value) pair or a
{flagName: value} map, so prerequisites like
'await pw.skipIfFeatureFlagNotSet("ChannelAttributes", true)' can be
combined with other flag prerequisites into a single server restart
instead of one restart per flag.
skipIfFeatureFlagNotSet is removed entirely (definition, export, and
fixture wiring): it only ever skipped a test when a flag was off rather
than turning it on, which silently left specs gated on a flag that
defaults off (e.g. DiscoverableChannels, ManagedChannelCategories)
permanently un-exercised in CI.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: migrate skipIfFeatureFlagNotSet call sites to ensureFeatureFlag
Mechanical rename of skipIfFeatureFlagNotSet(flag, true) to
ensureFeatureFlag(flag, true) across channel_attributes, global_attributes,
board_attributes, channel_perm_rules, and abac specs/helpers. Adjacent
single-flag calls within the same test are merged into one
ensureFeatureFlag({flagA: true, flagB: true}) call so the server restarts
once per test instead of once per flag.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: mark tests broken by real DiscoverableChannels/ManagedChannelCategories as known issues
Both DiscoverableChannels and ManagedChannelCategories default to off and
were never set in the testcontainers CI baseline, so every spec gated on
skipIfFeatureFlagNotSet(flag, true) for these flags silently self-skipped
and never actually ran. Migrating them to ensureFeatureFlag makes the
server restart with the flag genuinely on, which surfaces pre-existing
product bugs:
- discoverable_channels.spec.ts: Browse Channels' search results race the
typed-search fetch against the discoverable-only loadDiscoverableChannels()
fetch, intermittently dropping the 'Request to join' button. The sibling
Find Channels flow is unaffected and still passes.
- managed_categories.spec.ts: assigning a managed_category_name to a
channel has no effect on the sidebar in this server build - channels
stay under the regular CHANNELS group and no managed category header is
ever rendered, so every behavior that depends on being in a managed
category (grouping, sorting, real-time updates, disabled Favorite/Move
To/context-menu, and the System Console setting) fails.
Mark the affected tests with test.fixme and a @knownIssue comment so they
report as skipped rather than failing CI, while the two tests that don't
depend on the broken behavior keep running normally.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: force ChannelAttributes off in channel_classification.spec.ts
ChannelAttributes now defaults on (#38937), which hides the legacy
classification toggle this suite exercises (gated on
!channelAttributes.enabled in new_channel_modal.tsx and
channel_settings_configuration_tab.tsx). Force the flag off via
ensureFeatureFlag so the toggle renders again.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: force ChannelAttributes off in channel_banner.spec.ts
Same root cause as channel_classification.spec.ts: with ChannelAttributes
on by default, channel_settings_configuration_tab.tsx renders the
attribute-aware BannerTextEditor instead of the legacy AdvancedTextbox
(testid channel_banner_banner_text_textbox) this suite drives. Force the
flag off via ensureFeatureFlag so the legacy control renders again.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: give permalink preview wait more headroom in initial_scroll_read.spec.ts
The 'with multiple pages of post previews' case waits on a .post-preview
locator with Playwright's implicit 30s default timeout while 120
permalink previews resolve. Under full 30-way parallel CI load this
consistently took 39-44s (observed across two separate dispatch leases
in CI run 37112179268), timing out even though the behavior itself is
correct. Explicitly extend the wait to 60s and the per-test timeout to
90s for this case only.
Co-authored-by: saturnino <saturnino@mattermost.com>
* eslint-plugin: add playwright-ensure-feature-flag-top-level rule
Enforces that a Playwright spec file calls ensureFeatureFlag at most
once, and only from a top-level test.beforeAll(). This keeps the
intent of a spec's feature-flag combination explicit at the top of
the file instead of scattered through individual tests, and bounds
each spec file to at most one server restart.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: enable ensure-feature-flag-top-level rule, grandfather pre-existing files
Turns the new rule on as an error for the whole specs/ tree, and
carves out the 14 files that already called ensureFeatureFlag more
than once per file or outside a top-level beforeAll before this rule
existed. Those predate this change and are unrelated to it; each
needs its own migration pass to a single top-level beforeAll.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: hoist ensureFeatureFlag to a single top-level beforeAll in channel_attributes specs
Consolidates the per-test ensureFeatureFlag calls in
channel_attribute_assignment, channel_attribute_banner,
channel_attribute_banner_settings, channel_attribute_lifecycle, and
channel_attribute_settings_modal into one top-level beforeAll each,
per the new playwright-ensure-feature-flag-top-level rule.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: hoist ensureFeatureFlag to a single top-level beforeAll in channel_attribute_display/editing specs
Consolidates per-test ensureFeatureFlag calls into one top-level
beforeAll per file. The flag-off scenario in channel_attribute_display
needs the opposite ChannelAttributes value from every other test in
that file, so it moves to its own channel_attribute_display_flag_off.spec.ts.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: add channel_attribute_display_flag_off.spec.ts
Split out of channel_attribute_display.spec.ts: the flag-off scenario
needs the opposite ChannelAttributes value from every other test in
that file.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: mark 3 channel attribute chip-overflow tests as known issues
These three tests fail on master independent of this PR (reproduced
against the committed baseline via git stash, and live against a
Testcontainers server), each from a distinct bug in the
ChannelAttributeLabels/useLabelsOverflow chip-collapse feature:
- 'collapses the thread header chips into +N without moving the
thread controls': availableWidthForLabels only measures the chip
row's own flex ancestor, which in the thread pane has no visibility
into how much room the separate Follow/popout/menu controls need.
- 'collapses overflowing chips into +N without moving header
controls': channel-header__icons' deliberate min-width:0 lets it
shrink below what its own non-shrinking icon buttons need, and the
chip row is forced to show one chip even with zero room left,
spilling ~12px past the header.
- 'adds and removes a multiselect option, and the header chips
follow': removing one of two multiselect values leaves the chip
container permanently visibility:hidden -- useLabelsOverflow's
debounced recalculation after the ids change never completes.
Each is documented with a @knownIssue explaining the root cause found
via live reproduction, matching the convention already used for the
managed categories known issues.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: split managed_categories.spec.ts flag-off test into its own file
ManagedChannelCategories true/false needs two separate server
restarts, so the one test needing the flag off moves to
managed_categories_flag_off.spec.ts, leaving a single top-level
beforeAll(true) in managed_categories.spec.ts per the new
playwright-ensure-feature-flag-top-level rule.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: hoist ensureFeatureFlag to a single top-level beforeAll in misc specs
Consolidates per-test ensureFeatureFlag calls into one top-level
beforeAll each in channel_perm_rules_v0_4, discoverable_channels,
abac/policies/graph_operators, abac/resource_attributes/graph_sync,
and abac/resource_attributes/masking, per the new
playwright-ensure-feature-flag-top-level rule.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: split channel_attributes_required_kill_switch.spec.ts by flag value
ChannelAttributesRequired true/false needs two separate server
restarts, so the file splits into
channel_attributes_required_kill_switch_on.spec.ts and
channel_attributes_required_kill_switch_off.spec.ts, each with a
single top-level beforeAll, per the new
playwright-ensure-feature-flag-top-level rule.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: hoist ensureFeatureFlag to a single top-level beforeAll in global_attributes_form.spec.ts
Consolidates the per-test flag combinations (ChannelAttributes,
PostAttributes, PropertyFieldGraph) into one superset beforeAll: all
three are purely additive, so the superset covers every test here
with a single restart. Also stops requireHierarchicalAttributesEnabled
in global_attributes_helpers.ts from hiding an indirect
ensureFeatureFlag call of its own.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: hoist ensureFeatureFlag and split classification markings test
Adds a single top-level beforeAll(PropertyFieldGraph: true) to
global_attributes_listing.spec.ts, needed after
requireHierarchicalAttributesEnabled stopped setting the flag itself.
Splits the Classification Markings row test, which needs
ClassificationMarkings on, into its own
global_attributes_listing_classification_markings.spec.ts, per the
new playwright-ensure-feature-flag-top-level rule.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: hoist ensureFeatureFlag to a single top-level beforeAll in remaining global_attributes specs
Consolidates per-test ensureFeatureFlag calls into one top-level
beforeAll each in channel_resource_configuration.spec.ts and
classification_attribute.spec.ts, per the new
playwright-ensure-feature-flag-top-level rule.
Co-authored-by: saturnino <saturnino@mattermost.com>
* eslint-plugin: revert playwright-ensure-feature-flag-top-level rule
Drop the custom rule enforcing ensureFeatureFlag at the top level of a
spec file. A guideline in AGENTS.md and the function's own doc comment
is enough; tooling to enforce it is unnecessary overhead. Also reverts
eslint.config.mjs's enablement of the rule and its grandfather list.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: support multiple flags in ensureFeatureFlag, refresh client after restart
ensureFeatureFlag now also accepts a {flagName: value} map so a test
can combine several prerequisite flags into a single restart instead
of one per flag.
Also fixes a stale-client bug in its own post-restart verification:
restartMattermostContainer() points the server at a new container and
clears the cached client, so the pre-restart adminClient was stale by
the time it was used to verify the flags took effect. Fetch a fresh
client instead.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: call ensureFeatureFlag per test, remove skipIfNoEnterpriseLicense, fix stale adminClient reuse
Revert the top-level beforeAll/bare-import ensureFeatureFlag calls back
to per-test pw.ensureFeatureFlag() calls, since pw is a test-scoped
fixture and unavailable in beforeAll. Every test in a given spec file
passes the same parameters, so the Testcontainers server still restarts
at most once per file.
Replace the local skipIfNoEnterpriseLicense helper with
pw.skipIfNoLicense().
Fix several places where an adminClient obtained before
ensureFeatureFlag's restart was reused afterward: the restart points the
server at a new container, leaving that client stale. Reorder calls so
ensureFeatureFlag runs first, or refresh the client afterward when
reordering is not possible.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: restore ChannelAttributes=false override in channel_classification.spec.ts
Lost during the top-level-to-per-test ensureFeatureFlag revert. Without
it, ChannelAttributes defaulting on hides the legacy classification
toggle this suite exercises (gated on !channelAttributes.enabled in
new_channel_modal.tsx and channel_settings_configuration_tab.tsx),
failing every test with a timeout waiting for
channelClassificationToggle-button.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: give permalink preview wait more headroom in initial_scroll_read.spec.ts
120 permalink previews each resolve their own lookup, which can exceed
the default test timeout under loaded CI. Extend the timeout for that
case to leave headroom on top of the one-minute postPreview.waitFor.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: document ensureFeatureFlag convention and PW_WORKERS in AGENTS.md
Add e2e-tests/playwright/AGENTS.md covering the single-worker-per-server
parallelism model, the ensureFeatureFlag one-restart-per-file convention,
and pw.skipIfNoLicense(). Import it from the root AGENTS.md.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: stop custom profile attribute fields leaking across spec files
attribute_settings_behavior.spec.ts's MM-T5749 test created a custom
profile attribute field named "Cancel Test <id>" and never deleted it,
unlike its sibling spec files. Since CI runs many spec files against
one shared server per job, the field persisted and leaked into every
later test's Profile modal in that job.
Its Edit button's computed accessible name becomes "Cancel Test <id>
Edit" (title + button text via aria-labelledby), which
getByRole('button', {name: 'Cancel'})'s substring match also picked up
alongside the real Cancel button, causing a strict-mode violation in
locked_profile_fields.spec.ts whenever both specs ran in the same job
(reproduced locally by running them back-to-back on one server).
Fixes it two ways:
- Track and delete the fields attribute_settings_behavior.spec.ts owns,
matching the deleteCustomProfileAttributes cleanup convention already
used by its sibling spec files.
- Switch profile_modal.ts's cancelButton to getByTestId('cancelButton')
instead of a substring role-name match, so this class of bug can't
recur from any other attribute name.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: give long post-preview show-more check more headroom
The permalink preview needs a second render pass once the linked
post's content arrives before it knows whether to show the collapsed
'Show more' treatment. The default 10s expect timeout left no margin
for that extra round trip under loaded CI, causing this case alone
(out of 26 in the same file) to fail intermittently. Extend to 20s,
mirroring the same permalink-preview timing fix already applied to
initial_scroll_read.spec.ts.
Co-authored-by: saturnino <saturnino@mattermost.com>
* playwright: fix prettier formatting in attribute_settings_behavior.spec.ts
Co-authored-by: saturnino <saturnino@mattermost.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: saturnino <saturnino@mattermost.com>
* Fix flaky autotranslation 'unsupported language' e2e tests
Avoid changing the test user's locale to 'fr', which also switches
the webapp UI language and broke literal English text assertions
once fr.json gained a translation. Exclude 'en' from TargetLanguages
instead, and re-apply config across reloads to guard against
concurrent initSetup() resets.
Co-authored-by: sabril <saturninoabril@users.noreply.github.com>
* Fix duplicate 'AI Actions' accessible button in AI Actions menu
Co-authored-by: sabril <saturninoabril@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: sabril <saturninoabril@users.noreply.github.com>
* [MM-70822] Explain the blocked section switch while editing a channel permission rule
The Channel Settings modal refuses to switch sections while a tab reports
unsaved changes, and the Permissions Policy tab reports unsaved changes for as
long as its rule editor is open. The SaveChangesPanel that explains the refusal
only renders in that tab's list view, so clicking Info, Membership Policy or
Configuration while editing a rule did nothing at all: no section change, no
message, even though the items still looked clickable.
Route the modal's existing showTabSwitchError signal into the rule editor's
error slot so the refusal is explained where the user is looking, and mark that
slot role='alert' so it is announced rather than only seen.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* [MM-70822] Scroll the blocked section-switch warning into view
When the rule editor is taller than the modal, the alert that explains a
refused section switch sat below the fold. Scroll it into view when the
error appears so the message is actually visible.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Align max-login-attempts Playwright locators with current login copy
The full Playwright suite failed on max_login_attempts.spec.ts: exact
matches for the old invalid-credentials banner and lockout sentence no
longer hold. Use the shared invalidCredentialsError locator and the
stable lock-message prefix.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Pick future dates in the demo plugin date dialog e2e spec
Days 20 and 22 of the current month are in the past after mid-month, and
the plugin rejects those submissions. Advance to next month in that case.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Retrigger CI for Enterprise docker image and E2E
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* [MM-70822] Report the blocked section switch through the modal's floating footer
Per review, the rule editor now raises the same SaveChangesPanel the rest of
the Channel Settings modal uses, in its built-in error state, instead of a
bespoke inline message — matching the Team Settings membership policy editor.
The footer is position: fixed at the bottom of the modal, so it is visible
whatever the editor is scrolled to; the scroll-into-view workaround the inline
message needed goes away with it. Saving from the footer stays disabled (the
rule is committed from the editor's own button) and its Cancel leaves the
editor, so the two ways out of the block are the ones the message names.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* [MM-70822] Cover the blocked-switch footer's way out in the E2E spec
The footer's Cancel is now the exit the message points at, so assert it drops
the draft and returns to the rules list.
Co-authored-by: mattermost-code <matty-code@mattermost.com>
* Revert unrelated e2e test fixes
Restore demo_dialog_date.spec.ts and max_login_attempts.spec.ts to their
upstream state. These e2e changes are unrelated to the MM-70822 channel
permission-rule fix and were flagged for removal in review.
Address PR feedback: 0 answered, 1 resolved, 0 declined
* Retrigger CI after an unrelated Playwright flake on HEAD
Co-authored-by: mattermost-code <matty-code@mattermost.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: mattermost-code <matty-code@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Restore eight dropped locales as (Experimental) languages
Brings back the webapp and server catalogs for Danish, Czech, Croatian,
Lithuanian, Norwegian Bokmål, Portuguese (Portugal), Finnish and Belarusian
exactly as they stood before e9379690d5 removed them, and wires them in as
ordinary supported locales: the webapp languages map, the generated
imports.ts, and the server's supportedLocales list.
These were the catalogs with a real human-translated foundation (60-93% of
the user-facing strings for the first five, 20-31% for hr/fi/pt). Danish is
offered without a tag; the rest are labelled (Experimental) in the picker.
The EnableExperimentalLocales setting is not reinstated.
The catalogs are restored verbatim here; syncing them to today's en.json and
filling the remaining strings follow in separate commits.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Sync the restored catalogs to en.json and clear strings that fail the checkers
Runs the translate-i18n sync (apply_translations.mjs with no payload) over the
eight restored catalogs: every id en.json no longer has is pruned, and every
id they lack is seeded as "" so the gap is a value the worklists can read.
The strings that fail check_icu.mjs or mmgotool i18n verify -- 209 webapp
strings that drop or invent a variable, demote a plural, or do not parse, and
11 server strings with a stale template token or an empty or unused plural
category -- are reset to "" so the translation pass rewrites them rather than
shipping a string that throws at runtime.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Describe the 17 webapp strings that had no translator description
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Fill the Danish catalogs and add the Danish glossary
Translates the 1,155 webapp and 358 server strings the restored da catalogs
lacked, following the translate-i18n skill: a Danish glossary derived from
the majority renderings already in the catalog, per-chunk validation with
the skill's validator (ICU parse, variable and tag parity, plural
categories, the apostrophe trap), then apply_translations.mjs.
Both catalogs are now complete and pass check_icu.mjs and
mmgotool i18n verify.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Add glossaries for the seven experimental locales and translate their first 700 strings each
Each locale's glossary carries the 122 shared terms with targets derived from
the majority rendering already in that catalog, and notes recording the
inconsistent alternates and known mistranslations that a translation pass
must not propagate.
The webapp translations are the first two validated chunks per locale
(admin console strings, which sort first in en.json); the rest follow.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,050 more Croatian webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 2,100 more Finnish webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Czech webapp catalog (1,716 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 350 Czech server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,050 more Norwegian Bokmål webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 2,185 more Lithuanian webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Belarusian webapp catalog and translate 700 server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 4,200 more European Portuguese webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Czech server catalog (650 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Belarusian server catalog (175 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 2,100 more Finnish webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 2,100 more Croatian webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 700 more Lithuanian webapp strings and 1,050 server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Lithuanian webapp catalog and translate 350 more server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Norwegian Bokmål webapp catalog and translate 700 server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the European Portuguese webapp catalog and translate 700 server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,400 more Finnish webapp strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 350 more Lithuanian server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 700 more European Portuguese server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 350 more Finnish webapp strings and 287 server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Finnish webapp catalog and translate 700 more server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 2,095 more Norwegian Bokmål server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,320 more Lithuanian server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,373 more Croatian webapp strings and 1,400 server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Norwegian Bokmål server catalog (700 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the European Portuguese server catalog (2,007 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Lithuanian server catalog (350 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Croatian webapp catalog (350 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,050 more Finnish server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Finnish server catalog (350 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Translate 1,750 more Croatian server strings
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Finish the Croatian server catalog (225 strings)
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Retranslate 24 restored Finnish server strings that had dropped their template tokens
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Retranslate 8 restored Belarusian server strings that lacked required plural branches or tokens
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Retranslate 10 restored Czech server strings that lacked required plural branches or tokens
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Use a genuinely unsupported locale in the display settings fallback test
The test used 'cs' as its example of an unsupported locale; Czech is
supported again now that the experimental locales are restored, so the
fallback assertions failed. Use a junk locale code instead, matching
the server-side TestFixInvalidLocales.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Prune stale i18n key from restored locales and document new languages
* Treat extra locale keys as warnings in i18n verification
* Label alpha and beta languages in display options docs
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
A browser thread popout boots a fresh store, and ThreadPopout only read
the team from state without ever fetching it. With no team, the effects
that load the thread's posts never ran, so the popout showed only the
thread header and the message box.
Co-authored-by: Mattermost Build <build@mattermost.com>
* Align channel attribute chips and stop header label flicker.
Make hierarchical and select/rank chips share AttributeChip chrome in channel info, and stabilize header overflow measurement so squeezed channel names do not re-expand chips.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Hide channel attribute chip dismiss until the value menu is open.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Collapse hidden chip dismiss so resting chips do not reserve trailing space.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Keep text attribute edit size aligned with the resting value.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix stylelint property order in channel attribute SCSS.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Cache chip widths before collapsing on zero available space.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix multiselect outside-click close and chip-remove keyboard activation.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix stylelint property order on AttributeChip remove control.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix graph picker disabled assertions and label activation.
Div Menu triggers use aria-disabled (jest-dom toBeDisabled only covers form controls), and label htmlFor cannot activate a non-labelable div, so forward the field-name click.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Align select attribute triggers with inline chips and clear via chip X.
Select/rank fields were still using the boxed input+chevron trigger and a Clear menu item, while Channel Info graph/multiselect chrome is borderless chips with in-chip remove.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove unused channel_attributes.info.clear i18n string.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Unify channel attribute chip size so classification matches other chips.
Channel Info had been forcing AttributeChip to 24px with zero vertical padding (a leftover graph-picker metric), and medium chips still uppercased non-dismissible values — solid TOP SECRET / UNCLASSIFIED pills read taller than severity and multiselect chips sharing the same component.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove stale channel_attributes.info.clear keys from locale files.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Clamp channel attribute chips to 148px and lock medium height.
Long multiselect values were overflowing Channel Info because medium chips only had max-width 100%, and the 14px remove control’s flex auto-minimum still pushed dismissible classification chips past 22px.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Cap attribute value dropdown items at 320px with ellipsis truncation.
Long hierarchical and Channel Info select option labels were stretching the popover; clamp the menu/paper and keep checkbox/chevron usable.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix stylelint property order and empty comment in attribute chip styles.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Revert non-English locale edits; keep clear-string removal in en.json only.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Remove orphan channel_attributes.info.clear keys from non-en locales.
i18n CI rejects keys absent from en.json; the Clear control was removed so the English string is gone and translations of it must go too.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Point Learn More / help links at mattermost.com without www.
www.mattermost.com returns HTTP 401 to the external-links CI crawler; the apex host resolves normally and matches the pl/ permalink used elsewhere.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* [MM-70909] Rename health rule Summary to Title
RuleText.SummaryID becomes TitleID (json "title_id") and
HealthFinding.Summary becomes Title (json "title"); the registry now
requires health.rule.<code>.title. Nothing stores rendered prose, so
no migration is needed.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* [MM-70909] Add healthcheck.TranslationId
A no-op marker so the i18n extractor can find the rule catalog's
translation ids without the healthcheck package importing
public/shared/i18n.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* [MM-70909] Add English strings for health rules and reasons
Wraps the health reason ids in TranslationId so the extractor sees
them, adds health.reason.config_unavailable for rules that cannot read
their config, and adds en.json text for the push notification and
SiteURL rules.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* [MM-70909] Add push notification and SiteURL health rules
PUSH_EMPTY_URL, PUSH_BAD_SCHEME and PUSH_TEST_PROXY share the
PushNotificationServer subject and differ by code so each condition
can be muted on its own. SITE_URL_EMPTY and SITE_URL_HTTP cover
ServiceSettings.SiteURL. Every code emits a result each cycle.
The rules package aggregates the catalog and is imported by the health
check service so Builtin() is populated in production.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* [MM-70909] Align renamed RuleText field in Render test
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: match the push test proxy by parsed hostname
A substring check fired on URLs that only mention the test proxy in a
query string or a lookalike domain.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* [MM-70909] Add translator descriptions for health rule strings
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* [MM-70903] Run the health check hourly on the cluster leader
Add the HealthDashboard feature flag (off by default) and a leader-only
recurring task that builds a health snapshot, evaluates it, reconciles
findings and garbage-collects expired ones. The cycle is a no-op unless
the flag is on and the license is at least Enterprise.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* Build the health check service on first use
NewChannels also runs over mock stores that do not stub HealthFinding(), which
panicked every server started from them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Trim HealthDashboard feature flag comment
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Add HealthDashboard to the sanitized config golden
The new feature flag is part of every support packet's sanitized config.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Let a health check panic crash the server like other tasks
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Drop the concurrent health check test
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Drop the health check Stop test
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Cover the health check task with the leader task tests
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* MM-69567: Document what does and doesn't migrate from Slack.
Co-authored-by: Cursor <cursoragent@cursor.com>
* MM-69567: Clarify Slack migration coverage from review feedback.
Co-authored-by: Cursor <cursoragent@cursor.com>
* MM-69562–MM-69570: Restructure Slack migration guide end to end.
Rewrite migrate-from-slack into a prepare → export → transform → import flow with coverage, Grid, emails, guests, and large-import guidance.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Fix mmctl channel-move link to use extensionless docs URL.
Co-authored-by: Cursor <cursoragent@cursor.com>
* MM-69562: Document org-wide DM handling in grid-transform.
Add a FAQ entry explaining that grid-transform has no special handling
for org-wide conversations: root-level dms.json and mpims.json entries
are assigned to the workspace named on the first post carrying a team
field, so a cross-workspace DM lands in exactly one Mattermost team.
Cover the two practical consequences: participants from the other
workspace import as deactivated <USERID>@local placeholder accounts,
and conversations that cannot be assigned are logged to
grid-transform-slack.log and dropped from every per-workspace zip.
Also replace the Enterprise Grid section's pointer to the multi-party
DM section, which never covered org-wide DMs, with a summary and a link
to the new FAQ entry.
* Address Slack migration documentation review feedback
* Document mmetl dry-run validation for migrations
* Simplify Slack migration overview
* Group Slack export formats with export step
* Put Slack migration feature mapping first
* Number Slack migration action sections
* Nest multiple Slack exports under transform
* Add final Slack migration validation step
* Clarify what migrates from Slack and move reference detail into appendices.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Eric Sethna <14333569+esethna@users.noreply.github.com>