Files
mattermost/.github/workflows
fe9a36e80e E2E/Playwright: rolling upgrade tests (#38367)
* E2E/Playwright: keep server state across a container swap

`/mattermost/config` and `/mattermost/data` are Dockerfile VOLUMEs, so
replacing the container factory-reset the config and dropped uploads. Store
the config in Postgres and bind-mount the data directory to
`.mattermost_data/` instead.

The server writes there as UID 2000 into 0750 dirs, so on Linux the host
user cannot delete them: resetting on a fresh boot threw EACCES and failed
global setup on every second boot, and so on every retest. Clear from a
container when the host cannot.

Adds the library pieces the upgrade projects need — image swapping, phase
log capture with boot env redacted — and fixes the specs this exposed.

* E2E/Playwright: add the upgrade-path harness

The suite only ever ran against a server booted fresh on the new image, so
an upgrade-only regression would surface first in a customer's upgrade.

Three projects perform an in-place upgrade: `upgrade-from` seeds an older
image and records a baseline, `upgrade-swap-to` replaces only the server
container, `upgrade-to` re-verifies the baseline. API-first, since older
images ship older web apps.

From-versions come from the published support policy at run time — the last
three minors plus any active ESR, strictly older than the version under test.

* E2E/Playwright: run rolling upgrades in CI, one status per from-version

An entry workflow resolves the from-version matrix and calls a template once
per version, in parallel. Each run posts its own commit status, so a failure
names the version it came from; an empty matrix posts `upgrade-from-none`.

Every worker upgrades its own server, then draws from the full suite against
it with no re-preparation in between — an upgrade needing the suite's setup
re-run is not a passing upgrade.

Runs on release cut and on demand. Not on merge: it costs `matrix x workers`
runners. On PRs, only when the diff touches the harness or these workflows.

* E2E/Playwright: address review findings

- Keep the to-phase loader read-only. It patched EmailSettings, FileSettings,
  SiteURL, AccessControlSettings and PluginSettings on the upgraded server
  before any assertion, so config the upgrade dropped was repaired instead of
  reported — the opposite of what this harness is for.
- Return the raw post ID for a combined post. `<postId>:<timestamp>` has the
  same shape as a pending_post_id, so `getId` retried and then threw on
  posts that were already permanent.
- Point `npm run clean` at `.mattermost_data`; it still removed the old
  `local_storage` name.
- Trigger rolling upgrades on `package-lock.json` too, and document the
  full path set.
- Quote the license placeholder in the local run instructions: bare
  `<key>` is a shell redirection, not a value.
- Quote `$GITHUB_OUTPUT` in the two rolling-upgrade workflows.

* E2E/Playwright: retarget the rolling-upgrade auto-trigger

Every file under `lib/` matched, so any page-object edit fired the pipeline
— `matrix size x workers` runners, each performing its own upgrade. Narrow
the harness side to what actually defines an upgrade run: `upgrade-specs/`,
the matrix resolver, and the rolling-upgrade workflows.

Add the server surfaces an upgrade has to survive, which had no trigger at
all: schema and config migrations, the app-layer data migrations, and the
version list the from-version matrix is derived from. A new numbered
migration is exactly what `upgrade-to`'s "schema migrations match baseline"
check exists to catch.

* E2E/Playwright: use repo-root paths in the trigger table

`model/version.go` and `app/migrations.go` were ambiguous; spell them from
the repo root so a contributor can match them against a diff.

* E2E/Playwright: align rolling-upgrade trigger docs with the implemented matcher

The trigger prose and table in e2e-tests-workflows.md still listed
e2e-tests/playwright/lib/ and playwright.config.ts as auto-trigger paths,
and marked merge-to-master/release-* as an auto-trigger. Neither matches
e2e-tests-ci.yml's check-changes step: those two paths are unmatched and
require the manual opt-in checkbox, and check-changes is never even
called with run_rolling_upgrades=true on a merge (e2e-tests-on-merge.yml
never passes it). Align both descriptions with the implemented matcher
and with README.md's already-correct table.

Co-authored-by: sabril <saturninoabril@users.noreply.github.com>

* E2E/Playwright: fix write-after-end crash in collectLogs() teardown

container.logs() follows a running container, so a stack left running
(PW_TESTCONTAINERS_REUSE=true) never emits 'end' on its own. The 10s
stall timeout then called outFile.end() while the source was still
piping into it, so the next chunk landed on the closed destination and
crashed the process with an unhandled ERR_STREAM_WRITE_AFTER_END. This
intermittently killed rolling-upgrade worker jobs (seen failing the
upgrade-from-release-11.10 lane on this PR).

Unpipe and destroy the source before ending outFile, and add an error
handler on outFile, so no write can land after it closes.

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>
2026-09-09 10:14:57 +08:00
..