* ci: shard server Postgres tests into 4 parallel runners (#35739)
* ci: add test sharding plumbing to server CI
Add infrastructure for upcoming test sharding without changing behavior:
- Add shard-index and shard-total inputs to server-test-template.yml
(defaults preserve existing single-runner behavior)
- Add timing cache restore step (activates only when shard-total > 1)
- Add merge-postgres-test-results job to server-ci.yml that:
- Merges JUnit XML reports from shard artifacts
- Saves timing data cache for future shard balancing
- Handles both single-artifact and multi-shard scenarios
- Add .gitignore entries for timing cache and shard work files
Co-authored-by: Claude <claude@anthropic.com>
* ci: shard server Postgres tests into 4 parallel runners
Extract sharding logic into standalone, tested scripts and enable
4-shard parallel test execution for server Postgres CI:
Scripts:
- server/scripts/shard-split.js: Node.js bin-packing solver that
assigns test packages to shards using timing data from previous runs.
Two-tier strategy: light packages (<2min) whole, heavy packages
(api4, app) split at individual test level.
- server/scripts/run-shard-tests.sh: Multi-run wrapper that calls
gotestsum directly for each package group with -run regex filters.
- server/scripts/shard-split.test.js: 8 test cases covering round-robin
fallback, timing-based balancing, heavy package splitting, JUnit XML
fallback, and enterprise package separation.
Workflow changes:
- server-test-template.yml: Add shard splitting step that discovers test
packages and runs the solver. Modified Run Tests step to use wrapper
script when sharding is active.
- server-ci.yml: Add 4-shard matrix to test-postgres-normal. Update
merge job artifact patterns for shard-specific names.
Performance: 7.2 min with timing cache vs 62.5 min baseline = 88%
wall-time improvement. First run without cache uses JUnit XML fallback
or round-robin, then populates the cache for subsequent runs.
Co-authored-by: Claude <claude@anthropic.com>
* fix: raise heavy package threshold to 5 min to preserve test isolation
sqlstore integrity tests scan the entire database and fail when other
packages' test data is present. At 182s, sqlstore was just over the
120s threshold and getting split at test level. Raising to 300s keeps
only api4 (~38 min) and app (~15 min) as heavy — where the real
sharding gains are — while sqlstore, elasticsearch, etc. stay whole
and maintain their test isolation guarantees.
Co-authored-by: Claude <claude@anthropic.com>
* ci: only save test timing cache on default branch
PR branches always restore from master's timing cache via restore-keys
prefix matching. Timing data is stable day-to-day so this eliminates
cache misses on first PR runs and reduces cache storage.
Co-authored-by: Claude <claude@anthropic.com>
* ci: skip FIPS tests on PRs (enterprise CI handles compile check)
Per review feedback: the enterprise CI already runs a FIPS compile
check on every PR. Running the full FIPS test suite on PRs is redundant
since it uses the identical test suite as non-FIPS — the only
FIPS-specific failure mode is a build failure from non-approved crypto
imports, which the enterprise compile check catches.
Full FIPS tests continue to run on every push to master.
Co-authored-by: Claude <claude@anthropic.com>
* fix: address review feedback on run-shard-tests.sh
- Remove set -e so all test runs execute even if earlier ones fail;
track failures and exit with error at the end (wiggin77)
- Remove unused top-level COVERAGE_FLAG variable (wiggin77)
- Fix RUN_IDX increment position so report, json, and coverage files
share the same index (wiggin77)
- Update workflow comment: heavy threshold is 5 min, not 2 min (wiggin77)
Co-authored-by: Claude <claude@anthropic.com>
* style: use node: prefix for built-in fs module in shard-split.js
Co-authored-by: Claude <claude@anthropic.com>
* fix: avoid interpolating file paths into generated shell script
Read shard package lists from files at runtime instead of interpolating
them into the generated script via printf. This prevents theoretical
shell metacharacter injection from directory names, as flagged by
DryRun Security.
Co-authored-by: Claude <claude@anthropic.com>
* fix(ci): rename merged artifact to match server-ci-report glob
The merged artifact was named postgres-server-test-logs-merged which
does not match the *-test-logs pattern in server-ci-report.yml,
causing Postgres test results to be missing from PR/commit reports.
Also pins junit-report-merger to exact version 7.0.0 for supply chain
safety.
Co-authored-by: Claude <claude@anthropic.com>
* fix(ci): pass RACE_MODE env into Docker container
RACE_MODE was set on the host runner but never included in the docker
run --env list. The light-package path worked because the heredoc
expanded on the host, but run-shard-tests.sh reads RACE_MODE at
runtime inside the container where it was unset. This caused heavy
packages (api4, app) to silently lose -race detection.
Co-authored-by: Claude <claude@anthropic.com>
* fix(ci): discover new tests in heavy packages not in timing cache
Tests not present in the timing cache (newly added or renamed) would
not appear in any shard -run regex, causing them to silently skip.
After building items from the cache, run go test -list to discover
current test names and assign any cache-missing tests to shards via
the normal bin-packing algorithm with a small default duration.
Co-authored-by: Claude <claude@anthropic.com>
* fix(ci): add missing line continuation backslash in docker run
The previous --env FIPS_ENABLED line was missing a trailing backslash
after adding --env RACE_MODE, causing docker run to see a truncated
command and fail with "requires at least 1 argument".
Co-authored-by: Claude <claude@anthropic.com>
* fix(ci): add setup-go step for shard test discovery
go test -list in shard-split.js runs on the host runner via execSync,
but Go is only available inside the Docker container. Without this
step, every invocation fails silently and new-test discovery is a
no-op. Adding actions/setup-go before the shard split step ensures
the Go toolchain is available on the host.
Co-authored-by: Claude <claude@anthropic.com>
---------
Co-authored-by: Claude <claude@anthropic.com>
* updated go to version 1.25.8 (#35817)
* updated go to version 1.25.8
* updated gotestsum version to work with go 1.25.8
go 1.25 does not work with indirect tools 0.11 dependency pulled by
gotestsum.
* Use sync.WaitGroup.Go to simplify goroutine creation
Replace the wg.Add(1) + go func() { defer wg.Done() }() pattern with
wg.Go(), which was introduced in Go 1.25.
* pushes fips image on workflow dispatch to allow fips test to run on go version update
* fix new requirements for FIPS compliance imposed on updating to go 1.25.8
* updates openssl symbol check for library shipped with FIPS new versions
go-openssl v2 shipped with FIPS versions starting from 1.25 uses mkcgo to generate
bindings causing symbol names to be different.
* removes temp workflow-dispatch condition
* keep versions out of agents md file
* upgrade golangci-lint (#35845)
* test: clean up channel store data after TestChannelStore (#36066)
TestChannelStore sub-tests create channels, members, and team members
using fake TeamIds and UserIds (model.NewId() for non-existent rows).
These records are left in the database and cause integrity tests
(TestCheck*) running in the same binary to fail their full-table scans.
Register a t.Cleanup on TestChannelStore that purges the affected
tables entirely. A blanket purge is safe: the schema enforces no FK
constraints, and every test suite creates its own data independently.
* Fix command injection in server-test-template workflow (#36080)
Replace the unquoted heredoc (which embedded GITHUB_HEAD_REF into a
generated script) with a cp of the existing run-shard-tests.sh, which
already handles the light-only case. Pass BUILD_NUMBER and TEST_TARGET
as explicit docker env vars instead of interpolating them into script
content.
* fix(ci): restore testname format in sharded gotestsum runs (#36078)
run-shard-tests.sh called gotestsum directly without --format, so it
fell back to gotestsum's default (pkgname) instead of the testname
format set by the Makefile. Pass --format "${GOTESTSUM_FORMAT:-testname}"
to match the Makefile default.
Co-authored-by: Mattermost Build <build@mattermost.com>
* fix(lint): fix pre-existing golangci-lint v2.11.4 issues
Fix misspelling in comment and redundant nil check flagged by the
upgraded linter.
* ci: use golang image for test runner on release-10.11
mattermost-build-server images are not built for release branches.
Use the official golang image which is always available for any Go version.
* ci: use mattermost/mattermost-build-server for release-10.11
The mattermostdevelopment/ images are only built for master.
The production mattermost/ images are built for release branches.
* ci: use mattermost/mattermost-build-server in mmctl test template
The mattermostdevelopment/ images are only built for master.
The production mattermost/ images are built for release branches.
---------
Co-authored-by: Pavel Zeman <pavel.zeman@mattermost.com>
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Carlos Garcia <carlos.garcia@mattermost.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* adds team member data sanitizing (#35562)
* adds team member data sanitizing
* assert using require
* adds data sanitizing to team members for user endpoint
* team admin data visibility now tests with different user
(cherry picked from commit 2be57a7ec0c67004b77c76386f20a630920196e3)
* removes wrong argument in test helper calls
* fix: add explicit permission grant in team members test (#36007)
* fix: add explicit permission grant in team members test
TestGetTeamMembersForUserRoleDataSanitization was relying on a permission
side-effect leaked from concurrent tests. Under fullyparallel, another test
temporarily adds PermissionReadOtherUsersTeams to system_user role, which
the team admin subtest accidentally benefits from. Under sequential execution
(binary parameters mode), no concurrent test leaks this permission, so the
team admin correctly gets 403.
Fix by explicitly granting ReadOtherUsersTeams in the subtest setup, matching
the pattern used in adjacent subtests.
Release Note
NONE
Co-authored-by: Claude <claude@anthropic.com>
* fix: remove explanatory comment per review feedback
---------
Co-authored-by: Claude <claude@anthropic.com>
* removes extra arg from test helper call
---------
Co-authored-by: Carlos Garcia <carlos.garcia@mattermost.com>
Co-authored-by: Pavel Zeman <pavel.zeman@mattermost.com>
Co-authored-by: Claude <claude@anthropic.com>
* improves time limit checks
* consistently check for presence of patch fields
* fix variable shadowing in test
* allow idempotent pinning operations with time limit expired
* new utility function for post limit time check
* fix style issue
* Add missing E2E CI files and delivery-platform migration for release-10.11
- Add calculate-playwright-results and calculate-cypress-results GitHub Actions
(referenced by e2e-tests-playwright-template.yml and e2e-tests-cypress-template.yml
but never backported to release-10.11)
- Add e2e-tests/playwright/merge.config.mjs (required by merge-reports step)
- Add run-specs Makefile target and server.run_specs.sh (required by run-failed-tests job)
- Fix merge-shard-results step: pin @playwright/test version and add fallback
for when no blob reports exist (json reporter output used directly)
- Remove pull_request trigger from e2e-tests-ci.yml (delivery-platform migration)
- Remove dead e2e-fulltests-ci.yml and e2e-tests-ci-template.yml
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: yasserfaraazkhan <attitude3cena.yf@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* reproduce panic with test
* allow bots in the profile map
* explicitly prevent sending notifications to bots
* persistent notifications: handle senders not in the channel
Create a new config setting, and migrate the old values to new.
https://mattermost.atlassian.net/browse/MM-63652
Skip-Enterprise-PR: true
```release-note
NONE
```
* fix i18n
also fix unit tests
```release-note
NONE
```
* For fresh installations, default to true
```release-note
NONE
```
* gofmt files
```release-note
NONE
```
* Fixing some more strings
```release-note
NONE
```
* Update e2e tests
```release-note
NONE
```
* MM-64669 Fix keyboard navigation of settings sidebar and add Playwright test
* MM-64669 Revert changes to Cypress test which masked keyboard bug
The changes that were previously made caused Cypress to refocus the
sidebar repeatedly which stopped the test from failing without fixing
the bug.
* Ensure focus highlight is always visible on sidebar tabs
This may not have been broken by the changes that caused MM-64669, but I
noticed it while I was in there and wanted to fix it.
* Fix settings modal scrolling while changing sections using arrow keys
* Remove accidentally-added field
This commit exposes audit logging functionality to plugins via the plugin API, allowing plugins to create and log audit records. Additionally, it addresses a gob encoding issue that could cause plugin crashes when audit data contains nil pointers or unregistered types.
* add mmctl compliance export download command and tests
- Introduced `ComplianceExportDownloadCmd` to facilitate downloading compliance export files.
- Implemented the `DownloadComplianceExport` method in the Client interface for handling file downloads.
- Added unit tests for the download command, covering successful downloads, error handling for non-existent jobs, and retries on failure.
- Included end-to-end tests to validate the command's functionality.
- Updated documentation to include usage examples and options for the new command.
* don't know why this was left out
* PR comments
* adjust test for new retry logic
* refactored download fn for compliance_export and export
* fix test due to fixed logic
* docs
* MM-64330 - filter abac users in channel invite
* implement cursor functionality for abac user filtering
* remove unnecessary comments
* refactor the backend implementation simplifying the functions
* refactor api to use opts as parameters, rename function
* add missing translation
* remove unnecesary test code
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
* feat: Replace 5% grace period with configurable ExtraUsers field
- Rename ExtraSeats to ExtraUsers in license Features struct
- Remove fixed 5% grace period and minimum 1 extra user logic
- Add configurable ExtraUsers field that allows exact control over additional seats
- Update calculateGraceLimit() to use extraUsers parameter directly
- When ExtraUsers is nil, defaults to 0 (hard cap with no overage)
- Special case maintained: zero user licenses always return 0 grace limit
- Update all tests to use new ExtraUsers functionality
Closes#31628
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* feat: eliminate calculateGraceLimit function, use inline baseLimit + extraUsers
- Remove calculateGraceLimit function and replace with inline calculation
- Allow extraUsers even when baseLimit is 0 (behavioral change)
- Update tests to reflect new behavior
- Remove TestCalculateGraceLimit since function no longer exists
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* feat: move ExtraUsers field to top level License struct
Move ExtraUsers field from Features struct to the top level License struct
for better organization and direct access. Update all references in limits.go
and limits_test.go to use the new field location.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* feat: use model.NewPointer for creating integer pointers in tests
Replace inline function declarations with model.NewPointer calls for cleaner code.
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* feat: reorder ExtraUsers field to be after IsSeatCountEnforced
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* fix: format Go files with gofmt
- Remove extra blank line in limits.go
- Align struct fields in limits_test.go table test
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
* Fix user limits tests and document ExtraUsers field
- Fix TestCreateUserOrGuestSeatCountEnforcement to use ExtraUsers instead of old grace period
- Add documentation to ExtraUsers field explaining it as a grace mechanism
- Update test comments to reflect hard limit terminology
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
* [MM-63717] LDAP Wizard skeleton (#31029)
* add ldap_wizard component to render its admin components
* i18n
* test adjustment
* keys and props fixes
* title fix
* fix placeholders
* fix value initialization
* linting
* remove all ...props (except custom component); any->unknown
* fix i18n (temp, will be changed in later PR)
* better return; simplify function checking/calling
* [MM-64259] Sections sidebar and navigation (#31059)
* initial sections list sidebar
* sidebar highlighting and scroll on click
* some tidying up
* add custom section titles for section sidebar
* i18n
* updating border on sections
* scss style lint
* color -> border-color
* simplify activeSectionKey initialization; remove trailing newline
* add useSectionNavigation; clean up ldap_wizard and scss; PR comments
* extract section of code into renderSidebar()
---------
Co-authored-by: Asaad Mahmood <asaadmahmood@users.noreply.github.com>
* [MM-64296] Add test connection for connection settings panel (#31190)
* button -> ldap test connect api
* fix console error by sanitizing value in text component
* return detailed error as error; adjust button -> primary, flushLeft
* middle of redesigning how we do hover text, first button
* add hover text to bools and file uploads
* i18n
* add LdapSettings as api type; add new endpoint to api yaml
* allow testing without first enabling LDAP and saving config
* i18n id changes
* improve TestLdapConnection to current standards
* PR comments
* safeDereference; cleaner returns
* remove hover markdown; formatting and typing simplification
* use button for "More Info"; i18n
* finish renaming help_text_hover -> help_text_more_info
* fix error output
* only send bindpassword if it has been changed
* fix: don't send blank bindPassword when it is still *****
* merge conflict
* [MM-64480] Refactor Admin Definition (#31280)
* move ldap definition to its own file for simplicity & context
* refactor admin_definition to eliminate circular dependencies
* merge conflicts
* before: buggy userHasReadPermissinOnSomeResources; after: fix incorrect snapshot
* merge conflict: new bindPasssword definition was left behind; fixed.
* merge conflict
* [MM-63765] LDAP Wizard: User filter expandable section (#31286)
* add "more info" hover to user filter help texts; make wider
* add expandable_setting type and component
* use Dislosure show/hide pattern for accessibility
* fix tooltip scss selectors
* fix hover -> more_info; make sure translation files are correct
* use join('\n\n') instead of the eslint disable line
* Revert "use join('\n\n') instead of the eslint disable line"
This reverts commit 274667e875b34703f14fee0706cd28b0125cefc9.
* [MM-64482] LDAP Wizard - Test User filters (#31312)
* initial cut at UI and backend for test filters
* api definitions; mocks
* clean up to current standards
* [MM-64512] - Test user filters UI (#31355)
* result_count -> total_count
* json cannot marshal error, returning error as string as god intended
* render errors with icon, hover text, and better feedback texts
* gather the settings that may be in expandable sections
* remove success, use error == "" to indicate success
* [MM-64536] LDAP Wizard: Test user attributes (#31373)
* LdapFilterTestResult -> LdapDiagnosticResult; FilterName -> TestName
* implement test_attributes endpoint and limited frontend (first step)
* adding EntriesWithValue
* [MM-64550] LDAP Wizard: Test user attributes UI (#31374)
* [MM-64551] LDAP Wizard: Test group attributes (#31375)
* remove Test LDAP button (not needed); reused helptext for other btn
* implement test_group_attributes endpoint; button/client-side paths
* [MM-64552] LDAP Wizard: Test group attributes UI (#31376)
* implement Test Group Attributes button
* simplify helper functions (improves useCallback dependencies)
* show the default filter that was used on the backend in the tooltip
* show the icon when there's an error (e.g. required filter/attribute)
* fix infinite rerendering
* fix error after failed save; fix navigation unlocked after save
* empty
* Adjust message feedback given we don't test the schema anymore
* improve css; don't use inline styles
* removed unneccesary pointer indirection
* improved i18n strings and logic
* combining filters/attributes/group attributes endpoints
improve types
* improve help text for User Filter (it's tricky)
* AvailableAttrs -> AvailableAttributes
* fix for e2e tests (renamed title)
* more e2e fixes
* skip broken e2e test
---------
Co-authored-by: Asaad Mahmood <asaadmahmood@users.noreply.github.com>
* enforce License.IsSeatCountEnforced if set
If a license sets `IsSeatCountEnforced`, enforce the user limit therein
as a hard cap.
Fixes: https://mattermost.atlassian.net/browse/CLD-9260
* remove duplicate tests
* Improve user limit error messages and display
- Add separate error messages for licensed vs unlicensed servers
- Licensed servers: "Server exceeds maximum licensed users. ERROR_LICENSED_USERS_LIMITS"
- Unlicensed servers: "Server exceeds safe user limit. ERROR_SAFETY_LIMITS_EXCEEDED"
- Remove redundant "Contact administrator" text from activation errors shown to admins
- Fix system console to display actual server error messages instead of generic "Failed to activate user"
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Add license nil check and test coverage
- Add license != nil check in GetServerLimits to prevent panic
- Add test case to verify graceful handling of license being set to nil
- Ensures fallback to hard-coded limits when license becomes nil
Co-authored-by: lieut-data <lieut-data@users.noreply.github.com>
* Fix user limits tests to expect license-specific error IDs
Update test expectations to use the new license-specific error IDs:
- app.user.update_active.license_user_limit.exceeded for licensed server user activation
- api.user.create_user.license_user_limits.exceeded for licensed server user creation
Also update frontend to show actual server error messages instead of generic ones in system console.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Remove redundant license nil test
The test couldn't meaningfully verify nil license behavior since it relied on
hard-coded constants that can't be modified in the test.
Co-authored-by: lieut-data <lieut-data@users.noreply.github.com>
* Fix whitespace issue in limits_test.go
Remove unnecessary trailing newline to pass style checks.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* updated i18n
* s/ERROR_LICENSED_USERS_LIMITS/ERROR_LICENSED_USERS_LIMIT_EXCEEDED/, expand warning log
* Add 5% grace period for licensed user limits
- Add calculateGraceLimit() function with 5% or +1 minimum grace
- Apply grace period only to licensed servers with seat count enforcement
- Handle zero user licenses by returning zero grace limit
- Add comprehensive test coverage for grace period scenarios
- Unlicensed servers maintain existing hard-coded limits without grace
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix TestCreateUserOrGuestSeatCountEnforcement to account for 5% grace period
The test was failing because it expected user creation to fail at exactly
the license limit, but the implementation now includes a 5% grace period
before enforcement kicks in.
Changes:
- Update test cases to create users up to the grace limit (6 for a 5-user license)
- Add comments explaining the grace period calculation
- Both regular user and guest user creation tests now properly validate
enforcement at the grace limit rather than the base license limit
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Fix TestUpdateActiveWithUserLimits to account for 5% grace period
Update test expectations to match the new grace period behavior:
- At base limit (100) but below grace limit (105): should succeed
- At grace limit (105): should fail
- Above grace limit (106): should fail
This aligns the tests with the license enforcement implementation
that includes a 5% grace period above the licensed user count.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: lieut-data <lieut-data@users.noreply.github.com>
Co-authored-by: Mattermost Build <build@mattermost.com>