* [MM-68231] Tighten post info authorization
Align post info channel access with the standard read path while preserving expected public-channel discoverability. Add regression coverage for guest and compliance-mode access checks.
Made-with: Cursor
* [MM-68231] Strengthen post info test coverage
Tighten the new post info regression coverage so the guest denial case proves its setup and the compliance case asserts the expected non-compliance behavior first.
Made-with: Cursor
* [MM-68231] Expand post info authorization coverage
Add focused regression coverage for invite-team access, compliance behavior on open teams, private-channel permission boundaries, and outsider denial for DM and GM post info.
Made-with: Cursor
* Adds version to the property group model
* Ensures that the REST API rejects v1 group calls
* Ensures field version and group version match
* Simplify property groups on app layer tests
* Add GetByID to PropertyGroupStore and enforce field/group version match on update
* Simplify bits of the code
* Fix i18n and add generic errors
* Fix PropertyGroupStore mock to return stable IDs and default zero version to V1
* Fix tests that were using nonexistent group IDs
* Fix rigidness on valid group names
* Update group not found slug
* Temporary allow to use tempaltes with v1
* Explicitly including tempaltes in the IsPSAv1 check for conflict check
* Return 404 on group not found and template explicit inclusion on patch API endpoint
* Fix CPA test that would use fields from unregistered groups
---------
Co-authored-by: Miguel de la Cruz <miguel@ctrlz.es>
sqlstore's TestMain calls sqlstore.InitTest (which opens postgres and
drops tables) before mainHelper.Main, so the -test.list bailout added
in #36222 never fired and shard-split discovery failed on the GitHub
host. Bail out at the top of TestMain instead, and restore HEAVY_MS
so sqlstore can still be treated as whole.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Fix invite modal input text clipping and modal width overflow
Root cause: react-select v5 auto-sizes the input container using a CSS
grid with data-value attribute, which grows the grid columns based on
input text width. This caused the control, modal-content, and the
dropdown menu to exceed the modal-dialog's 600px width.
Changes:
1. invitation_modal.scss: Add max-width:100% and overflow:hidden on
.modal-content to prevent it from overflowing the 600px modal-dialog.
2. users_emails_input.tsx: Override react-select's styles:
- input.gridTemplateColumns: '0 minmax(0, 1fr)' prevents the sizer
column from auto-expanding based on typed text width.
- valueContainer.gridTemplateColumns: 'minmax(0, 1fr)' prevents the
value-container grid from auto-sizing columns beyond the container.
- Remove old display:flex and width:100% overrides that fought with
react-select v5's inline-grid layout.
3. users_emails_input.scss:
- Remove legacy width:1px on react-select input wrapper.
- Add min-width:0 and max-width:100% on value-container and
input-container for proper flex/grid containment.
- Constrain dropdown menu to max-width:100%.
- Allow no-match text and menu notices to wrap with overflow-wrap
and word-break. Use min-height instead of fixed height so wrapped
text fits.
Fixes: MM-68461
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* Fix stylelint property order in invitation_modal.scss
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* Update snapshot for react-select style changes
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* Add min-width: 0 to input-container to prevent shrink/overflow regressions
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Introduce model.SanitizeFilename and model.IsValidFilename, and
apply them in genFileInfoFromReader and FileInfo.IsValid. The
sanitizer uses filepath.Base, NFC-normalizes Unicode, strips ASCII
control characters, collapses backslashes to forward slashes, and
truncates to the VARCHAR(256) fileinfo.name column width.
The react-select input uses classNamePrefix ManagedCategory, so it did not
inherit the global react-select__input theme color. Set color to
var(--center-channel-color) on the input and input-container to match
placeholder and single-value styling.
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Devin Binnie <devinbinnie@users.noreply.github.com>
* MM-66082: Fix invite modal paste by reading text/plain from clipboard
UsersEmailsInput always called preventDefault on paste but read clipboard
data with the legacy 'Text' type, which is empty in modern browsers.
That blocked default paste while adding nothing. Read text/plain first,
fall back to Text, skip custom handling when there is no meaningful
content, and only preventDefault when handling pasted text.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* Fix ESLint no-void in UsersEmailsInput paste handler
Replace void promise with .catch(() => undefined) so async paste
processing satisfies the no-void rule.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* MM-66082: Keep arbitrary pasted invite text as draft
Only treat obvious list pastes (comma, semicolon, newline) as bulk
invite input. Let arbitrary pasted text remain in the input so the
existing search and no-match UX can handle it, and keep space-delimited
text as draft rather than splitting it into invite tokens.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* MM-66082: Restore space-delimited email paste handling
Treat space-separated paste as bulk invite input only when every token
is a valid email. Keep mixed or free-form space-separated paste as draft
text so the existing no-match search UX still applies.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* MM-66082: Fix invite paste parsing in modal input
Treat pasted input as bulk invite tokens only when it is a single valid
email, an obvious comma/semicolon/newline list, or a space-separated list
of valid emails. Leave mixed or arbitrary pasted text as draft so the
existing no-match search UX still applies. Add focused widget and invite
view regression coverage for the affected paste paths.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* tests: use example invite paste fixtures
Replace product-specific test data with example.com values, restore the
space-paste length assertion, rename the invalid-word fixture, and remove
extra clipboard MIME lookups that were not needed for the supported paste
path.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
* MM-66082: Fix invite input typing regressions
Fix premature chip creation while typing valid emails by using the paste
classifier only when it returns bulk mode, keep the valid address default
message wired correctly, and add regression coverage for typing and blur
behavior in both UsersEmailsInput and InviteView.
Co-authored-by: Maria A Nunez <maria.nunez@mattermost.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
* MM-67352 Prevent composer scroll jumps on formatting click
Keep formatting controls from stealing textarea focus on mousedown so long drafts stay in place when markdown buttons are clicked. Add a regression test for the formatting bar interaction.
Made-with: Cursor
* Update webapp/channels/src/components/advanced_text_editor/formatting_bar/formatting_icon.tsx
Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com>
---------
Co-authored-by: Harrison Healey <harrisonmhealey@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* fix(mmctl): prevent nil pointer panic in websocket command on connection failure
When the WebSocket connection fails immediately, Listen() closes EventChannel
via defer. Reading from a closed channel with a plain receive returns nil,
causing a panic in ToJSON(). Switch to range so the loop exits cleanly,
add a nil guard, and surface ListenError to the caller.
Fixes MM-68351
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(mmctl): add unit tests for websocket nil event and ListenError handling
Extracts the event-processing loop into processWebSocketEvents to enable
unit testing, and adds tests covering the nil-event skip and error surfacing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(mmctl): add happy-path subtest for processWebSocketEvents
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* MM-67975: Add container CPU and memory limits to support packet diagnostics
Add two new optional fields to SupportPacketDiagnostics.Server:
- container_cpu_limit (float64): effective CPU limit in CPUs (e.g. 0.5, 2.0)
- container_memory_limit_mb (uint64): memory limit in MB
Both fields are populated from cgroups v2 (/sys/fs/cgroup/memory.max and
/sys/fs/cgroup/cpu.max) on Linux. Fields use omitempty so they are absent
from the output on bare metal or when no container limits are configured,
preserving backwards compatibility.
Non-Linux builds compile and produce no output for these fields via a
container_limits_other.go stub, following the existing memory_linux.go /
memory_other.go pattern.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* Fix golangci-lint errors: govet shadow and gofmt formatting
- Fix govet shadow: use var memBytes uint64 + err = instead of memBytes, err :=
to avoid shadowing the outer err variable (which is reused after this block)
- Fix gofmt: add extra space before // 512 MB comment to align with
the longer v2CPUMax line in the same assignment block
* fix(platform): ceil memory MB conversion and return zero-values for missing cgroup files
- Use ceiling division for MemoryLimitMB so sub-1MB limits map to 1 instead
of 0 (which omitempty would silently drop)
- Absorb os.ErrNotExist in getContainerLimits so non-v2/bare-metal hosts
return ContainerLimits{}, nil as the function comment promises
- Update test: missing cgroup file now asserts zero-values, not an error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(platform): add subtest locking ceil-to-MB behavior for sub-MB memory limits
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test(platform): add subtest for missing cpu.max returning zero values
Locks in the os.ErrNotExist branch for cpu.max (lines 57-60 in
container_limits_linux.go), which was previously unreachable via the
existing missing-memory test since that test returns early before
reading cpu.max.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* Default template property field permissions to sysadmin
Templates define the schema that linked fields inherit, so their
permission levels should default to sysadmin rather than member. This
aligns the create handler with TestLinkedProperties expectations.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Require sysadmin for template property field creation
The target_type-based scope check lets team admins create template
fields with target_type=team, which would then inherit sysadmin-level
permission defaults and lock the creator out. Enforce manage_system for
any template creation so the permission gate matches the intent of the
"create template field as non-admin fails" test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Surface ws_event type in oversized cluster publish message logs
When a best-effort UDP gossip send fails with "message too long", the log
only shows event: publish with no further context. Tag the ClusterMessage
with the originating WebSocket event type so it appears in the error log.
* Update enterprise.pin to latest after enterprise PR #2133 merged
https://claude.ai/code/session_01Y1Abg1eDjKQBJvy7XhCtG6
* Bump
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Claude <noreply@anthropic.com>
The Coverage job ran the same tests as Postgres with only ENABLE_COVERAGE=true
and a Codecov upload as differences. Enable coverage directly on the Postgres
job under the same release-branch skip condition, eliminating 4x 8-core runner
hours per PR.
* gather plugin metrics and serve on /metrics
* tests
* fix recent conflicts from master
* fix linting
* address review feedback: feature flag, route guard, and unit tests for plugin metrics
- Add PluginMetricsCollection feature flag (default true) to allow disabling plugin metric collection without a deploy
- Only wrap the /metrics handler with plugin metric collection (not arbitrary plugin routes, which would cause double-listing)
- Extract wrapping logic into wrapMetricsHandler for clarity
- Add unit tests for addPluginLabelToMetrics covering no-label, existing-label, comments, empty lines, and multiple metrics cases
* fix integration tests to use /metrics route so wrapMetricsHandler runs
* switch addPluginLabelToMetrics to use expfmt for correct label injection
Replace string manipulation with expfmt parse→mutate→re-encode, which
correctly handles all metric types, timestamps, and malformed input.
Output is normalized: blank lines are dropped and TYPE headers are
injected for undeclared metrics. Update unit tests accordingly.
* refine addPluginLabelToMetrics: log warnings, drop sort, use assert.Contains
- Log a warning (instead of silently discarding) on parse or encode errors,
returning empty string in both cases
- Remove name sorting — metric family order is irrelevant to Prometheus scrapers
- Switch unit test assertions to assert.Contains per line so tests are
order-independent
* replace strPtr helper with model.NewPointer
* fix gofmt: remove extra blank line
* replace existing plugin_id label instead of appending a duplicate
If a plugin already exports a plugin_id label, overwrite it rather than
appending a second one, which would produce invalid Prometheus output.
Add test coverage for the replace path.
* add missing test coverage per mattermost-build feedback
- Unit test: malformed input returns empty string without panicking
- Integration: PluginMetricsCollection=false excludes plugin metrics
- Integration: plugin returning non-200 status excluded from response
- Integration: plugin returning empty body excluded from response
* rename PluginMetricsCollection to AggregatePluginMetrics, default false
---------
Co-authored-by: Jesse Hallam <jesse@mattermost.com>
* Fix bot import panic when user exists without bot record
The original importBot error handler re-declared `var appErr *model.AppError`
inside the CreateBot failure block, shadowing the outer appErr with a typed nil
pointer. When errors.As received this (*model.AppError)(nil), it was a non-nil
interface — so instead of returning false, it called AppError.Unwrap() on the
nil receiver, causing a panic.
This commit:
- Fixes the variable shadowing that caused the panic
- Adds recovery logic: when CreateBot fails because the username is taken,
look up the existing user and create/update just the bot record
- Fixes pre-existing silent error swallowing in Bot().GetByUsername — now
distinguishes store.ErrNotFound from real database errors
- Fixes pre-existing bug where DisplayName changes on re-import were lost
because DisplayName is stored in Users.FirstName, not the Bots table
- Adds logging at every step of the recovery path (Info for normal flow,
Warn for fallback/error paths)
- Uses distinct variable names (saveErr/updateErr) in the Save→Update
fallback to avoid the same class of variable-reuse hazard
- Adds comprehensive test suite (11 subtests) covering dry-run, apply,
re-import, recovery, regression/panic guard, idempotency, DisplayName
update, and plugin-owner edge cases
* Address review findings: tighten assertions, fix error ID, add coverage
- Use require.ErrorAs for store.ErrNotFound instead of generic require.Error
in the dry-run test, so it catches only not-found rather than any store error
- Add time.Sleep before idempotent re-import to ensure any real write would
produce a different UpdateAt timestamp at millisecond resolution
- Fix misleading error ID "app.bot.createbot.internal_error" to
"app.bot.update.internal_error" in the Update fallback path
- Add test for non-username CreateBot failure (email conflict) to cover
the error passthrough at line 907-908
* Add missing i18n translations for bot import error strings
Add translation entries for app.bot.update.internal_error,
app.import.import_bot.lookup_error, and
app.import.import_bot.user_not_found.error to fix enterprise CI
i18n check failure.
* ci: fix startup_failure in nightly race and weekly workflows
Add id-token: write permission to both server-ci-nightly-race.yml and
server-ci-weekly.yml. The reusable server-test-template.yml declares
id-token: write in its permissions block (needed for FIPS Docker Hub
login via OIDC). GitHub requires that caller workflows grant at least
the permissions declared by any reusable workflow they invoke —
regardless of whether the steps using those permissions are skipped at
runtime. Both new workflows only declared contents: read, causing
immediate startup_failure with zero jobs created.
Release Note
```release-note
NONE
```
Co-authored-by: Claude <claude@anthropic.com>
* ci: remove unused id-token: write from server-test-template
The template declared id-token: write but nothing in the workflow uses
OIDC token exchange — the FIPS Docker Hub login uses plain secrets
(DOCKERHUB_USERNAME/DOCKERHUB_TOKEN), not an OIDC identity token.
Removing it from the template means caller workflows (nightly race,
weekly, and the main server-ci) no longer need to grant id-token: write
either, following the principle of least privilege.
This is the actual root cause fix: the previous commit added id-token
to the callers as a workaround, but the real issue was the template
requesting a permission it never uses.
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
* MM-68160: Show post reminder ack in RHS for reply reminders
Set the reminder confirmation ephemeral post root_id to the thread root
when the reminder is set on a reply, matching how thread views key posts.
Re-enable websocket integration tests for reminders and add coverage for
reply vs root behavior.
Made-with: Cursor
* SetPostReminder: validate post before persisting reminder
Read the post and reminder metadata before inserting into PostReminders so
a failed GetSinglePost or metadata lookup cannot leave an orphaned row.
Made-with: Cursor
- Register per-item OnFailure callback to log each rejected document
with its error type and reason
- Restructure DoJob to close the bulk processor before marking a job
successful; check Stats().NumFailed after close and fail the job
when any documents were not indexed
- Use a sync.Once-guarded doClose helper so the processor is flushed
exactly once across all exit paths; non-success paths return and let
the defer handle the close
- Close function owns all its logging: warn with error on failure, info
on success; callers no longer need to log close errors themselves
- Fix ResponseBodyEnabled() hardcoded false → return l.trace so
per-item error JSON is visible when Trace=all is set
- Set job to error (rather than silently return) when createBulkProcessor
fails after the job has been claimed
- Add integration tests for both backends that apply a write block to
verify bulk failures are surfaced as job errors
- Add i18n strings for the two new error codes
The group member popover relied entirely on InfiniteLoader to trigger the
initial getProfilesInGroup fetch, which fails under certain conditions
(slow DOM layout, stale member_count, AutoSizer timing). Dispatch the
fetch explicitly when the popover opens via onOpenChange.
Made-with: Cursor
* MM-68047: Hide update status button in RHS post header
In the RHS (and smaller screens), the "Update your status" button
was consuming space that caused the username to be truncated or
hidden. Hide the button in the RHS context so the name remains
visible.
Made-with: Cursor
* Update permission_system_scheme_settings snapshots
Snapshots were stale after manage_own_agent and manage_others_agent
permissions were added in d4d65c8cfb without a snapshot update.
Made-with: Cursor
* Revert "Update permission_system_scheme_settings snapshots"
This reverts commit b408de78f6.
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* MM-67976: Add server uptime to support packet
Add process start time (started_at) and approximate host start time
(host_started_at, Linux only, derived from /proc/uptime) to the support
packet diagnostics. This helps diagnose restart loops and distinguish
process restarts from full machine/container reboots.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* Add HostStartedAt assertions to support packet happy-path test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Revert unrelated changes
* Add unit tests for getHostUptimeSeconds and fix cross-platform portability
- Extract parseUptimeFile helper in uptime_linux.go to enable unit testing
with synthetic file paths without touching the real /proc/uptime
- Add uptime_linux_test.go covering all error paths (file read error,
empty file, non-numeric value) and happy-path parsing
- Add uptime_other_test.go asserting the non-Linux stub returns
ErrHostUptimeUnsupportedPlatform and zero seconds
- Guard HostStartedAt assertions in support_packet_test.go with
runtime.GOOS so the test correctly asserts zero-time on non-Linux
platforms instead of failing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* test: use t.TempDir() for guaranteed-missing path in uptime test
Replace the hard-coded /nonexistent/proc/uptime path with a path
constructed from t.TempDir() to guarantee the file is absent without
relying on filesystem layout assumptions. Also remove the misleading
comment about swapping implementations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Reorder Server struct fields and assignments to group process identity fields together
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add macOS support for host uptime in support packet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* MM-67978: Add open file descriptor count to support packet diagnostics
Add OpenFileDescriptors and MaxFileDescriptors fields to
SupportPacketDiagnostics.Server. On Linux the open count is read from
/proc/self/fd; on macOS from /dev/fd. Both platforms use
syscall.Getrlimit(RLIMIT_NOFILE) for the soft limit. Unsupported
platforms (e.g. Windows) return -1 for both fields.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* MM-67978: Move OpenFileDescriptors/MaxFileDescriptors after TotalMemoryMB
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* fix: guard int64 overflow in getMaxFileDescriptors and update tests for unsupported platforms
Add overflow check before casting rlimit.Cur (uint64) to int64 in
getMaxFileDescriptors on Linux. Update fd_test.go and
support_packet_test.go assertions to accept -1 as a valid sentinel for
unsupported platforms instead of requiring a strictly positive value.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* revert: remove unrelated test refactoring from support_packet_test.go
Restore the three unrelated changes that crept into this branch:
- SetLogRootPathOverride instead of t.Setenv("MM_LOG_PATH", ...)
- installTypeOverride field instead of t.Setenv(envVarInstallType, ...)
- Restore explanatory comment in TestGetSanitizedConfigFile
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add a GoVersion field to SupportPacketDiagnostics.Server populated via
runtime.Version(), so support engineers can determine which Go version
a server was compiled with from the support packet alone.
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Populate server.process_id in diagnostics.yaml using os.Getpid(), making it easier to correlate support packet data with OS-level logs and confirm whether the server was restarted between an incident and packet generation.
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* Fixing text and emojis being clipped in channel banners
- Added E2E tests that confirm that emojis respect the correct size and aren't clipping through container
* Applying PR feedback
* Running prettier on playwright tests
* Fixing E2E Tests
* Added test case for descending characters
* Fixing linter issues
* Resolving issue with e2e test failing
* ci: add yamllint workflow to detect duplicate YAML keys
Add a yamllint check for workflow files to catch duplicate keys that
YAML parsers silently accept but GitHub Actions rejects on the default
branch.
Release Note
NONE
Co-authored-by: Claude <claude@anthropic.com>
* ci: address review feedback on yamllint workflow
- Add permissions: contents: read (least privilege)
- Bump checkout to v6.0.2 with persist-credentials: false
- Remove pip install step (yamllint is pre-installed on ubuntu-22.04)
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): widen ChannelMemberHistory time windows (MM-67041, MM-67037)
The 100ms query window (GetMillis()-100 to GetMillis()+100) is too
tight under CI load — DB writes can lag >100ms, causing the history
record to fall outside the window. Widen to ±10s and capture start
time before the operation.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): use require.Eventually for DND status restore (MM-63533)
Replace time.Sleep(3s) + instant assert with require.Eventually polling
(15s timeout, 500ms interval). The recurring task runs every 1s but can
lag under CI load, making the fixed sleep unreliable.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): fix PostReminder timing and increase WS timeout (MM-60329)
Set target time 1s in the future instead of now, giving the reminder
processor a clear tick to pick it up. Increase WebSocket wait from 5s
to 15s for CI load tolerance.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): add error checks and poll for file infos (MM-46902)
File info association with posts can be async. Replace instant
assertion with require.Eventually polling. Also add proper error
checking on UploadFile and CreatePost calls.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): fix thread membership race and WS timeout (MM-41285)
Replace instant GetUserThread assertion with require.Eventually polling
(10s timeout) since mention counts may not propagate immediately after
AddChannelMemberWithRootId. Increase WebSocket timeout from 2s to 15s.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): use far-future timestamps in GetUptoNSizeFileTime (MM-53905)
PermanentDeleteBatch only cleans up to current time, and parallel tests
can create file infos that interfere with the cumulative size calc.
Extend the delete window and use timestamps 1 hour in the future to
ensure these test files are always 'most recent'.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): use far-future timestamps in GetNthRecentPostTime (MM-64438)
GetNthRecentPostTime queries by global position across all posts.
Parallel tests creating posts shift the Nth position. Using timestamps
1 hour in the future ensures these test posts are always most recent.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): space reply timestamps for unread count test (MM-41797)
makeSomePosts creates all posts without explicit CreateAt, so they can
share the same millisecond. MarkAsRead(rootPost.CreateAt) then marks
replies as read too, returning 0 instead of 2. Fix by overwriting
reply timestamps to be 1s after the root post.
Co-authored-by: Claude <claude@anthropic.com>
* test: re-enable MM-62895 and MM-61041 to probe for failures
Remove t.Skip for two long-dormant flaky tests to collect actual
failure data over 1-2 weeks of rebasing. Based on fullyparallel
branch so these run with every CI pass.
- MM-62895: TestUpdateOAuthApp (14mo, empty Jira, unknown root cause)
- MM-61041: TestAutocompleteUsersInChannel (17mo, fragile integration test)
Co-authored-by: Claude <claude@anthropic.com>
* test: add MM-64687 shared channel tests to probe
Remove t.Skip("MM-64687") from 5 shared channel sync tests to collect
failure data. The underlying sync mechanism was completely rewritten in
#35619 (ChannelMemberHistory cursor-based sync), so the original race
condition may no longer exist. Probing for 1-2 weeks before deciding
whether to permanently re-enable in #35762.
Tests:
- api4/shared_channel_metadata_test.go (4 subtests)
- app/shared_channel_membership_sync_self_referential_test.go (1 subtest)
Co-authored-by: Claude <claude@anthropic.com>
* test: re-enable TestResetPassword (stale skip from old build server)
The skip comment says 'should be investigated' — the test uses the same
inbucket mail pattern as other working tests (e.g. TestInviteUsersToTeam).
The 'old build server changes' it references are long resolved.
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): clean up far-future posts in GetNthRecentPostTime
Per review feedback from mgdelacroix: defer PermanentDelete for all
far-future posts so they don't leak into other tests that query
GetNthRecentPostTime. The file_info_store test (GetUptoNSizeFileTime)
already had cleanup via defer PermanentDelete.
Co-authored-by: Claude <claude@anthropic.com>
* ci: TEMPORARY enable race detector for PR testing (revert after)
Co-authored-by: Claude <claude@anthropic.com>
* fix(tests): add mutex to fix data race in shared channel sync test
The -race detector caught a data race in Test_4 (Sync failure and
recovery): the OnBatchSync/OnIndividualSync callbacks write to
successfulSyncs from the HTTP handler goroutine while assert.Eventually
reads it from the test goroutine. Add sync.Mutex to protect all
accesses to the shared slice.
Co-authored-by: Claude <claude@anthropic.com>
* fix(test): add mutex to TestSharedChannelPostMetadataSync for race safety
The syncedPosts/syncedPostsServerA/syncedPostsServerB slices are
written by OnPostSync callbacks running on HTTP server goroutines
and read by require.Eventually + assertions on the test goroutine.
Without synchronization, the race detector flags concurrent access.
Add sync.Mutex per subtest to protect all slice reads and writes,
matching the pattern used in TestSharedChannelMembershipSyncSelfReferential.
Co-authored-by: Claude <claude@anthropic.com>
* Revert "ci: TEMPORARY enable race detector for PR testing (revert after)"
This reverts commit b9af0e9003.
* fix: address review feedback from wiggin77
- Remove eager-evaluated len(infos) from require.Eventually message
(was always 0 since infos is nil at call time)
- Log errors from PermanentDelete in test cleanup
Co-authored-by: Claude <claude@anthropic.com>
* fix: rename shadowed err variable in test cleanup
Use delErr to avoid shadowing the outer err variable, which
triggers govet's shadow checker in CI.
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
* ci: move FIPS and binary params tests to weekly schedule
Move low-regression-risk test suites out of the per-push/PR Server CI
workflow into a new weekly scheduled workflow (Monday 1am EST / 5am UTC):
- Postgres with binary parameters (1x 8-core runner)
- Postgres FIPS sharded tests (4x 8-core runners + merge job)
- mmctl FIPS tests (1x 8-core runner)
This reduces the per-push 8-core runner demand from 14 concurrent jobs
to 5 (4 Postgres shards + 1 ES), which should significantly reduce
queue times that currently reach 90+ minutes during peak hours.
The weekly workflow also supports workflow_dispatch for manual triggering
when urgent FIPS or binary parameter verification is needed.
#### Release Note
```release-note
NONE
```
Co-authored-by: Claude <claude@anthropic.com>
* ci: move coverage shards to 2-core runners
Add a 'runner' input to server-test-template.yml (defaults to
ubuntu-latest-8-cores for backward compatibility) and set coverage
shards to ubuntu-22.04 (2-core).
Coverage is non-blocking (allow-failure: true) so longer runtime
doesn't impact PR feedback. Estimated ~20-30 min per shard on 2-core
vs ~7-9 min on 8-core, but frees 4 more 8-core slots per push.
Combined with the FIPS/binary-params weekly move, per-push 8-core
demand drops from 14 → 4 (just the Postgres test shards + ES v8).
Co-authored-by: Claude <claude@anthropic.com>
* ci: decouple race detector from binary params, add nightly race job
The race detector was accidentally bundled with binary params via
the fullyparallel=false → RACE_MODE coupling in the test template.
These test different things:
- Binary params: Postgres driver binary encoding mode
- Race detector: Go data race detection
Changes:
- Add explicit 'race-enabled' input to server-test-template.yml
- Remove implicit fullyparallel→race coupling from template
- Binary params now runs with fullyparallel: true (default)
- New server-ci-nightly-race.yml runs -race nightly at 2am EST
on ubuntu-22.04 (2-core) to avoid 8-core contention
Co-authored-by: Claude <claude@anthropic.com>
* ci: add push trigger for release-* branches to weekly workflow
FIPS and binary params validation must run automatically on release
branch pushes, not just on the weekly schedule. Without this trigger,
release branches would lose FIPS/binary coverage entirely.
Co-authored-by: Claude <claude@anthropic.com>
* ci: use ET instead of EST in schedule comments
Cron runs at fixed UTC times regardless of DST. Use ~ET to avoid
implying exact EST/EDT correspondence.
Co-authored-by: Claude <claude@anthropic.com>
* ci: restore conditional FIPS on per-push, unshard weekly FIPS
Per review feedback from @lieut-data:
1. Restore FIPS jobs in server-ci.yml with conditional execution:
run on all pushes (master/release) and on PRs when go.mod changed
or branch name contains 'fips'. This ensures Go upgrades and
explicit FIPS work get immediate feedback.
2. Remove sharding from weekly FIPS — no speed pressure on a weekly
schedule, so a single unsharded job is simpler (eliminates the
4-shard matrix + merge job).
3. Restore gomod-changed detection step in the go job.
Both per-push (conditional, unsharded) and weekly (unconditional,
unsharded) FIPS runs use single jobs now, reducing complexity.
Co-authored-by: Claude <claude@anthropic.com>
* ci: restore FIPS sharding for PR runs, remove from push events
FIPS tests in server-ci.yml now only trigger on PRs where the branch
name contains 'fips' or go.mod changed. Sharding (4 shards + merge)
restored for fast iteration on FIPS-related PRs. Regular FIPS coverage
provided by the weekly workflow (unsharded).
This addresses lieut-data's review feedback to restore sharding where
it matters most: during active PR iteration.
Co-authored-by: Claude <claude@anthropic.com>
* ci: add explicit permissions to weekly and nightly workflows
Set minimum required permissions (contents: read) on both new workflow
files per review feedback. Reusable workflows called via 'uses' inherit
the caller's permissions.
Co-authored-by: Claude <claude@anthropic.com>
* ci: keep coverage shards on 8-core runners
Comment out the 2-core runner override for coverage shards per
Eva's feedback. Coverage stays on the default 8-core runners.
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
Adds a warning banner to the Enable Cluster Sniffing setting that
appears when sniffing is turned on, advising against use with
cloud-hosted providers such as Elastic Cloud or Amazon OpenSearch
Service.
* [MM-67880] Add /mobile-logs slash command with E2E tests
Add a new /mobile-logs slash command that allows users to manage the
attach_app_logs preference for themselves or other users (admin-only).
Includes unit tests for all code paths and Playwright E2E tests covering
self-management, admin cross-user management, permission denial, and
error handling.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix i18n error key suffixes and format E2E tests
Rename error i18n keys to use .app_error suffix matching upstream
convention (no_permission, update_error, user_not_found). Run prettier
on the E2E test file to fix formatting.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix E2E test type error: use getUserPreferences instead of getMyPreferences
The getAttachLogsPreference helper was using getMyPreferences() which returns
PreferenceType (not an array), causing TS2345 errors. Switch to
getUserPreferences(userId) which returns the expected array type.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* [MM-67880] Move unreachable usage fallback into switch default case
The return after the switch was unreachable because action is validated
earlier to be "on", "off", or "status". Move it into an explicit default
case with a defensive comment.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* allow up to 2 arguments
* Add audit logging for mobile logs slash command actions
Implement a new function to log audit records when users enable or disable the attach_app_logs preference via the /mobile-logs command. This includes capturing relevant metadata such as user IDs, session information, and the action taken. The logging occurs in both the enable and disable command paths, enhancing traceability and accountability for user preference changes.
* Enhance mobile logs command to handle cross-user permission checks
Add a new response function for cases where a regular user attempts to access mobile log settings for another user, ensuring they receive a neutral error message instead of specific user information. Update the command logic to incorporate this response for both nonexistent users and deactivated accounts. Additionally, modify related tests and internationalization keys to reflect these changes, improving security and user experience.
* Update E2E test for /mobile-logs command to verify permission denial for nonexistent users
Enhance the existing E2E test for the /mobile-logs command by adding assertions to check that users receive a permission denial message when attempting to change mobile log settings for a nonexistent user. This improves test coverage and ensures proper error handling in the application.
* update i18n strings
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* Add Playwright E2E tests for demo plugin server-side slash commands
Adds 7 new spec files covering the remaining demo plugin slash commands:
/ephemeral, /ephemeral_override, /dialog (submit, cancel, validation,
error, error-no-elements), /dialog date, /dialog field-refresh,
/interactive, /show_mentions, and /list_files.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
* The 2 CodeRabbit changes seem a bit over cautious in the direction of guarding against false assertions but I did implement them.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>