- Add apiServerCleanup call to supervisor Shutdown method
- Cleanup happens AFTER Python process terminates for graceful disconnect
- Fix test assertion to check for relative executable path
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add startAPIServer function to start gRPC server on random port
- Add APIServerRegistrar type to break import cycle with apiserver package
- Modify WithCommandFromManifest to accept apiImpl and registrar
- Update configurePythonCommand to start API server and set MATTERMOST_PLUGIN_API_TARGET env var
- Add apiServerCleanup field to supervisor struct for cleanup on shutdown
- Add SetAPIServerRegistrar method to Environment for dependency injection
- Wire up API server registrar in app/plugin.go
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove Phase 5 limitation that skipped hook dispensing for Python plugins.
Now Python plugins use hooksGRPCClient to receive hook invocations through
the same infrastructure as Go plugins.
Changes:
- Extract gRPC connection from go-plugin's GRPCClient
- Create hooksGRPCClient adapter using the connection
- Wrap in hooksTimerLayer for metrics collection
- Populate implemented hooks array from gRPC client
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Detect Python plugins in newSupervisor via isPythonPlugin helper
- Configure AllowedProtocols to include ProtocolGRPC for Python plugins
- Increase StartTimeout to 10s for Python interpreter startup
- Skip Dispense("hooks") for Python plugins (Phase 5 supervision only)
- Leave sup.hooks nil - hook dispatch deferred to Phase 7
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously, we relied on the plugin to close the DB connections
on shutdown. While this keeps the code simple, there is no guarantee
that the plugin author will remember to close the DB.
In that case, it's better to track the connections from the server side
and close them in case they weren't closed already. This complicates
the API slightly, but it's a price we need to pay.
https://mattermost.atlassian.net/browse/MM-56402
```release-note
We close any remaining unclosed DB RPC connections
after a plugin shuts down.
```
Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
* ProfileImageBytes for EnsureBotOptions
* leverage plugintest.NewAPI
* fix linting
* add UpdateUserRoles to plugin api
* MM-57018: support reattaching plugins
Expose a local-only API for reattaching plugins: instead of the server starting and managing the process itself, allow the plugin to be launched externally (eg within a unit test) and reattach to an existing server instance to provide the unit test with a fully functional RPC API, sidestepping the need for mocking the plugin API in most cases.
In the future, this may become the basis for running plugins in a sidecar container.
Fixes: https://mattermost.atlassian.net/browse/MM-57018
* drop unused supervisor.pid
* factor out checkMinServerVersion
* factor out startPluginServer
* restore missing setPluginState on successful reattach
* avoid passing around a stale registeredPlugin
* inline initializePluginImplementation
* have IsValid return an error
* explicitly close rpcClient
In the case of reattached plugins, the Unix socket won't necessarily disappear leaving the muxBrokers blocked indefinitely. And `Kill()` doesn't do anything if there's no process being managed.
* explicitly detachPlugin
* emphasize gRPC not being supported
---------
Co-authored-by: Mattermost Build <build@mattermost.com>
It was a good decision in hindsight to keep the public module as 0.x
because this would have been a breaking change again.
https://mattermost.atlassian.net/browse/MM-53032
```release-note
Changed the Go module path from github.com/mattermost/mattermost-server/server/v8 to github.com/mattermost/mattermost/server/v8.
For the public facing module, it's path is also changed from github.com/mattermost/mattermost-server/server/public to github.com/mattermost/mattermost/server/public
```