Commit Graph
5 Commits
Author SHA1 Message Date
mattermost-docs-ai[bot]andmattermost-docs-ai[bot] 1ac3eb8c28 docs: AI draft for MM-71344 Plugin API: expose cluster node identity (#39401)
Co-authored-by: mattermost-docs-ai[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-10-26 07:55:39 +01:00
e97df5b6e1 [MM-70687] Expose host JSX runtimes to web app plugins (#38489)
* chore(webapp): upgrade to React 19

Bump react, react-dom and react-is to 19.2.8 across the webapp
workspaces along with their @types packages, and upgrade the React
ecosystem packages that needed newer releases to support React 19:

- @mui/material, @mui/base and @mui/styled-engine-sc
- @floating-ui/react
- react-day-picker
- @types/react-transition-group, @types/styled-components

Replace the unmaintained react-beautiful-dnd with its actively
maintained fork @hello-pangea/dnd, which is API compatible, ships its
own types and supports React 19. This drops both the
@types/react-beautiful-dnd dependency and the local patch that forced
react-redux 9 compatibility.

React 19 removes the legacy ReactDOM.render entry point, so the app now
always mounts through createRoot and the webapp side of the
EnableConcurrentReact feature flag is gone.

Apply the types-react-codemod scoped-jsx and
react-element-default-any-props presets to account for React 19 removing
the global JSX namespace and defaulting ReactElement props to unknown,
plus the manual type fixes those changes surfaced.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* chore(webapp): pin react at the workspace root so a single copy resolves

With react bumped to 19 only inside the workspaces, npm kept an older
react at the hoisted root to satisfy the peer requirements of packages
such as react-intl, leaving the app with two React copies. Declare react,
react-dom and their types at the webapp root the same way react-intl is
already declared, which is the existing pattern for singleton packages
shared across workspaces, and regenerate the lockfile.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* fix(webapp): read a tooltip child's ref from its props

React 19 moved ref into props and made element.ref throw a deprecation error on
access. Read children.props.ref instead, and apply the merged ref after spreading
the child's props so the child's own ref no longer overwrites it.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* chore(webapp): resolve a single react-is that matches React 19

react-is 18 does not recognize React 19's react.transitional.element symbol,
so every consumer that inspects elements through it - pretty-format's snapshot
serializer and styled-components among them - silently failed its checks.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* test(webapp): expect no legacy context argument on component calls

React 19 drops legacy context, so it now hands function components undefined
as the second argument instead of an empty context object.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* test(webapp): re-record snapshots for React 19 and dependency updates

The recorded output changes because React 19 keeps ref in props and omits an
empty value attribute, @hello-pangea/dnd uses data-rfd-* in place of
data-rbd-*, styled-components and MUI generate different class hashes, and the
image asset mock no longer resolves to an empty string.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* fix(webapp): keep createRoot available to plugins on window.ReactDOM

React 19 serves createRoot and hydrateRoot only from react-dom/client. Plugins
are built against React 18 and reach them through react-dom's root entry, which
react-dom 18's client.js re-exports from, so every plugin that mounts its own
root got undefined instead of a function. Because a plugin's initialize call is
not guarded, the throw took the whole web app down with it: with plugins enabled
nothing rendered at all, which failed essentially the entire e2e suite.

Exposing react-dom and react-dom/client as one object keeps both surfaces
available to plugins built against either version.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* test(e2e): wait for lazy views to mount instead of racing them

React 19 throttles revealing a Suspense boundary's content for ~300ms once a
fallback has been shown, so the first navigation to a lazily-loaded chunk
commits later than it did on React 18. Two specs sampled state within that
window:

- last_viewed_spec asserted on the team's last viewed type immediately after
  clicking Threads, but that is recorded when GlobalThreads mounts. Wait for
  the view instead, which is the condition the assertion depends on.
- channel_name_tooltips_spec reached the direct message search box via
  cy.focused(), which resolved to the button that opened the modal before
  focus moved into it. Select the input directly, as every other spec does.

Both specs pass on React 18 and React 19 with these changes.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* fix(threads): guard clear() so it cannot undo a later navigation

useThreadRouting's clear() unconditionally replaced the URL with the threads
route of the team captured when the callback was created. GlobalThreads calls it
from an effect that fires once its threads finish loading, so a navigation that
landed between the render and that effect flush was silently undone.

React 19 makes this reachable in practice: its Suspense fallback-reveal throttle
delays the lazily loaded threads view by ~300ms, widening the window enough that
switching teams right after opening Threads bounced back to the previous team.

The test file moves to .tsx so it can render the hook inside a route match.

Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>

* fix(webapp): preserve live history and React 18 plugin compatibility

* DO NOT MERGE: run React 19 StrictMode E2E discovery

Port Jesse Hallam's discovery tooling from #38235 onto the React 19
upgrade, adapting the development runtime loader and warning detector.
Force StrictMode and E2E exception detection on for this experiment.
Keep NODE_ENV=production outside React and preserve component names.

Both E2E self-tests require instrumentation in discovery mode and use a
React 19 warning. Local Playwright and Cypress self-tests, 13 diagnostic
unit tests, the production build, webapp style/types, and Playwright
checks pass. Cypress lint passes; its typecheck reports errors in
unchanged bot-account and collapsed-thread specs.

Revert this entire commit after collecting the full CI/E2E results.

* Revert "DO NOT MERGE: run React 19 StrictMode E2E discovery"

This reverts commit 564757d380.

* fix(webapp): cover upstream React 19 types and stabilize ranked policy tests

* test(webapp): increase convert GM modal test timeout

* MM-70612 Log plugin React DOM root calls

* MM-70612 Use real script elements in plugin lifecycle tests

* guard against plugin failures (sync and async); don't hang webapp

* MM-70678 Sample plugin startup failure reports at 5%

* export jsx-runtime; tests; docs

* MM-70687 Simplify JSX runtime docs to require Mattermost 12.0

* fix(webapp): deactivate superseded plugin scripts

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Jesse Hallam <lieut-data@users.noreply.github.com>
2026-09-14 16:23:30 +00:00
Christopher PoileandMattermost Build afc8def801 [MM-70573] Propagate context through plugin HTTP (#38354)
* add context-aware plugin requests; tests

* improve comments

* fix PluginHTTP stream cleanup

* close unexpected PluginHTTP test response

* synchronize plugin response writer shutdown

* linting

* address context-aware plugin HTTP review feedback

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2026-09-11 17:26:26 -04:00
Eva SarafianouandCursor b9c2bd733f docs: restore generated plugin SDK reference pages (#37788)
* docs: restore generated plugin SDK reference pages

Reimplements the Hugo-era plugingodocs/pluginjsdocs/pluginmanifestdocs
shortcode pipeline natively in Docusaurus, so the server plugin SDK,
web app plugin SDK, and manifest reference pages render full generated
content again instead of "Generated content (migrating)" placeholders.

Two new Go generators (gen-plugin-godocs, gen-plugin-manifest-docs) and
one Node generator (gen-plugin-jsdocs.mjs) read server/public/plugin,
server/public/model, and webapp/channels/src/plugins/registry.ts
directly from this monorepo and emit gitignored JSON consumed by new
PluginGoDocs/PluginGoExample/PluginJsDocs/PluginManifestDocs React
components, wired into prestart/prebuild alongside the existing
sidebar/OpenAPI generators.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: remove migration plan doc from this PR

Was a handoff/status doc for the implementing agent, not meant to ship
as part of the change itself.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: make plugin-godocs/manifest-docs builds atomic

build:plugin-godocs and build:plugin-manifest-docs redirected straight
into data/plugin-*.json, which doesn't exist on a clean checkout (the
redirection itself would fail before the generator ever ran) and, on a
subsequent failed run, would truncate a previously-good JSON file
before failing. Create data/ up front, write to a .tmp file, and only
mv it into place once the generator exits successfully.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: fix review findings in plugin doc generators

gen-plugin-manifest-docs:
- jsonFieldName now excludes unexported fields (matching encoding/json)
  and falls back to the Go field name when there's no tag or the tag's
  name component is empty (e.g. json:",omitempty"), instead of
  dropping the field entirely.
- exprTypeDocs's SelectorExpr case now resolves a qualified type only
  when its package qualifier actually points at the model package
  (checked against the declaring file's imports), instead of matching
  any x.Sel identifier by name alone regardless of which package it
  qualifies.

gen-plugin-godocs:
- The example-code loop now falls back to example.Code when
  example.Play is nil (go/doc leaves Play nil when it can't synthesize
  a whole runnable program), and propagates printer.Fprint errors
  instead of discarding them.

No output change for the current server/public/plugin or
server/public/model content — verified via a full regen.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: drop legacy-repo comment references, align jsdocs generator parser

Remove "port of the old mattermost-developer-documentation Hugo
shortcode" comments from the plugin doc generators/components now that
they're fully native to this monorepo, and switch gen-plugin-jsdocs.mjs
from the TypeScript compiler API to @typescript-eslint/typescript-estree
to match the old script's parser/shape, while keeping the more robust
reArg-declared-parameter-name and node-scoped comment-attachment logic.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: bump plugin doc generators' go.mod to go 1.26

go 1.23 was arbitrarily low; align with a current Go version. go run
auto-downloads a matching toolchain on older local installs, so this
doesn't reintroduce a dependency on server/public/go.mod's version.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: handle RestElement in gen-plugin-jsdocs parameter extraction

paramNamesFromPattern silently dropped rest parameters/destructured rest
members (e.g. (a, ...rest) or {a, ...rest}), since RestElement matched
none of its type checks. No effect on today's registry.ts output (no
rest patterns currently used there), but keeps the extraction correct if
one is ever introduced.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: simplify plugin doc generators README note

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: check stdout write errors in plugin doc generators

os.Stdout.Write's return errors were discarded, so a failed/partial
write (e.g. broken pipe, disk full) would still exit 0. Combined with
the npm scripts' > file.tmp && mv pattern, a truncated write could be
treated as a successful generation. Fatal on either write failing.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: flatten Server/Webapp plugin SDK reference sidebar nesting

server/server-reference.md and webapp/webapp-reference.md were the only
file in their respective folders, so the sidebar generator (which only
collapses a folder into a single entry when it has an index.md) rendered
them as a "Server" > "Server plugin SDK reference" category with one
child instead of one flat entry, unlike every sibling reference folder
(rest-api/index.md, bot-accounts/index.md, etc.).

Rename both to index.md to match that convention, and update the ~20
cross-referencing links (many with #anchor fragments) that pointed at
the old /reference/server/server-reference and /reference/webapp/webapp-
reference paths.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-21 15:21:21 +03:00
Eva SarafianouandCursor 1d3bbc638b feat(docs): move docs-experimental content into monorepo docs/ (#37330)
* feat(docs): move docs-experimental content into monorepo docs/

Co-authored-by: Cursor <cursoragent@cursor.com>

* Remove plan related files and comments

* Cleanup comments, remove generated files

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-02 18:42:57 +03:00