diff --git a/api/v4/source/system.yaml b/api/v4/source/system.yaml
index d0e7d71eca..335aa08c36 100644
--- a/api/v4/source/system.yaml
+++ b/api/v4/source/system.yaml
@@ -1125,6 +1125,25 @@
##### License
Requires either a E10 or E20 license.
operationId: GenerateSupportPacket
+ parameters:
+ - name: basic_server_logs
+ in: query
+ description: |
+ Specifies whether the server should include or exclude log files. Default value is true.
+
+ __Minimum server version__: 9.8.0
+ required: false
+ schema:
+ type: boolean
+ - name: plugin_packets
+ in: query
+ description: |
+ Specifies plugin identifiers whose content should be included in the support packet.
+
+ __Minimum server version__: 9.8.0
+ required: false
+ schema:
+ type: string
responses:
"400":
$ref: "#/components/responses/BadRequest"
diff --git a/server/channels/api4/system.go b/server/channels/api4/system.go
index 6396d1963a..860086a86c 100644
--- a/server/channels/api4/system.go
+++ b/server/channels/api4/system.go
@@ -89,15 +89,28 @@ func generateSupportPacket(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
+ // We support the existing API hence the logs are always included
+ // if nothing specified.
+ includeLogs := true
+ if r.FormValue("basic_server_logs") == "false" {
+ includeLogs = false
+ }
+ supportPacketOptions := &model.SupportPacketOptions{
+ IncludeLogs: includeLogs,
+ PluginPackets: r.Form["plugin_packets"],
+ }
+
// Checking to see if the server has a e10 or e20 license (this feature is only permitted for servers with licenses)
if c.App.Channels().License() == nil {
c.Err = model.NewAppError("Api4.generateSupportPacket", "api.no_license", nil, "", http.StatusForbidden)
return
}
- fileDatas := c.App.GenerateSupportPacket(c.AppContext)
+ fileDatas := c.App.GenerateSupportPacket(c.AppContext, supportPacketOptions)
// Constructing the ZIP file name as per spec (mattermost_support_packet_YYYY-MM-DD-HH-MM.zip)
+ // Note that this filename is also being checked at the webapp, please update the
+ // regex within the commercial_support_modal.tsx file if the naming convention ever changes.
now := time.Now()
outputZipFilename := fmt.Sprintf("mattermost_support_packet_%s.zip", now.Format("2006-01-02-03-04"))
diff --git a/server/channels/app/app_iface.go b/server/channels/app/app_iface.go
index edd7252027..45352fdff7 100644
--- a/server/channels/app/app_iface.go
+++ b/server/channels/app/app_iface.go
@@ -618,7 +618,7 @@ type AppIface interface {
GenerateMfaSecret(userID string) (*model.MfaSecret, *model.AppError)
GeneratePresignURLForExport(name string) (*model.PresignURLResponse, *model.AppError)
GeneratePublicLink(siteURL string, info *model.FileInfo) string
- GenerateSupportPacket(c request.CTX) []model.FileData
+ GenerateSupportPacket(c request.CTX, options *model.SupportPacketOptions) []model.FileData
GetAcknowledgementsForPost(postID string) ([]*model.PostAcknowledgement, *model.AppError)
GetAcknowledgementsForPostList(postList *model.PostList) (map[string][]*model.PostAcknowledgement, *model.AppError)
GetActivePluginManifests() ([]*model.Manifest, *model.AppError)
diff --git a/server/channels/app/opentracing/opentracing_layer.go b/server/channels/app/opentracing/opentracing_layer.go
index 9cf5e7a149..f7dab9b31f 100644
--- a/server/channels/app/opentracing/opentracing_layer.go
+++ b/server/channels/app/opentracing/opentracing_layer.go
@@ -4786,7 +4786,7 @@ func (a *OpenTracingAppLayer) GeneratePublicLink(siteURL string, info *model.Fil
return resultVar0
}
-func (a *OpenTracingAppLayer) GenerateSupportPacket(c request.CTX) []model.FileData {
+func (a *OpenTracingAppLayer) GenerateSupportPacket(c request.CTX, options *model.SupportPacketOptions) []model.FileData {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GenerateSupportPacket")
@@ -4798,7 +4798,7 @@ func (a *OpenTracingAppLayer) GenerateSupportPacket(c request.CTX) []model.FileD
}()
defer span.Finish()
- resultVar0 := a.app.GenerateSupportPacket(c)
+ resultVar0 := a.app.GenerateSupportPacket(c, options)
return resultVar0
}
diff --git a/server/channels/app/support_packet.go b/server/channels/app/support_packet.go
index dcc8dbab22..1e15d49819 100644
--- a/server/channels/app/support_packet.go
+++ b/server/channels/app/support_packet.go
@@ -26,7 +26,7 @@ const (
cpuProfileDuration = 5 * time.Second
)
-func (a *App) GenerateSupportPacket(c request.CTX) []model.FileData {
+func (a *App) GenerateSupportPacket(c request.CTX, options *model.SupportPacketOptions) []model.FileData {
// If any errors we come across within this function, we will log it in a warning.txt file so that we know why certain files did not get produced if any
var warnings []string
@@ -35,14 +35,17 @@ func (a *App) GenerateSupportPacket(c request.CTX) []model.FileData {
// A array of the functions that we can iterate through since they all have the same return value
functions := map[string]func(c request.CTX) (*model.FileData, error){
- "support package": a.generateSupportPacketYaml,
- "plugins": a.createPluginsFile,
- "config": a.createSanitizedConfigFile,
- "mattermost log": a.getMattermostLog,
- "notification log": a.getNotificationsLog,
- "cpu profile": a.createCPUProfile,
- "heap profile": a.createHeapProfile,
- "goroutines": a.createGoroutineProfile,
+ "support package": a.generateSupportPacketYaml,
+ "plugins": a.createPluginsFile,
+ "config": a.createSanitizedConfigFile,
+ "cpu profile": a.createCPUProfile,
+ "heap profile": a.createHeapProfile,
+ "goroutines": a.createGoroutineProfile,
+ }
+
+ if options.IncludeLogs {
+ functions["mattermost log"] = a.getMattermostLog
+ functions["notification log"] = a.getNotificationsLog
}
for name, fn := range functions {
@@ -57,6 +60,27 @@ func (a *App) GenerateSupportPacket(c request.CTX) []model.FileData {
}
}
+ if pluginsEnvironment := a.GetPluginsEnvironment(); pluginsEnvironment != nil {
+ pluginContext := pluginContext(c)
+ for _, id := range options.PluginPackets {
+ hooks, err := pluginsEnvironment.HooksForPlugin(id)
+ if err != nil {
+ c.Logger().Error("Failed to call hooks for plugin", mlog.Err(err), mlog.String("plugin", id))
+ warnings = append(warnings, err.Error())
+ continue
+ }
+ pluginData, err := hooks.GenerateSupportData(pluginContext)
+ if err != nil {
+ c.Logger().Warn("Failed to generate plugin file for support package", mlog.Err(err), mlog.String("plugin", id))
+ warnings = append(warnings, err.Error())
+ continue
+ }
+ for _, data := range pluginData {
+ fileDatas = append(fileDatas, *data)
+ }
+ }
+ }
+
// Adding a warning.txt file to the fileDatas if any warning
if len(warnings) > 0 {
finalWarning := strings.Join(warnings, "\n")
diff --git a/server/channels/app/support_packet_test.go b/server/channels/app/support_packet_test.go
index 97fe7b173d..f3c534d58e 100644
--- a/server/channels/app/support_packet_test.go
+++ b/server/channels/app/support_packet_test.go
@@ -168,55 +168,91 @@ func TestGenerateSupportPacket(t *testing.T) {
logLocation := config.GetLogFileLocation(dir)
notificationsLogLocation := config.GetNotificationsLogFileLocation(dir)
- d1 := []byte("hello\ngo\n")
- err = os.WriteFile(logLocation, d1, 0777)
- require.NoError(t, err)
- err = os.WriteFile(notificationsLogLocation, d1, 0777)
- require.NoError(t, err)
-
- fileDatas := th.App.GenerateSupportPacket(th.Context)
- var rFileNames []string
- testFiles := []string{
- "support_packet.yaml",
- "plugins.json",
- "sanitized_config.json",
- "mattermost.log",
- "notifications.log",
- "cpu.prof",
- "heap.prof",
- "goroutines",
+ genMockLogFiles := func() {
+ d1 := []byte("hello\ngo\n")
+ genErr := os.WriteFile(logLocation, d1, 0777)
+ require.NoError(t, genErr)
+ genErr = os.WriteFile(notificationsLogLocation, d1, 0777)
+ require.NoError(t, genErr)
}
- for _, fileData := range fileDatas {
- require.NotNil(t, fileData)
- assert.Positive(t, len(fileData.Body))
+ genMockLogFiles()
- rFileNames = append(rFileNames, fileData.Filename)
- }
- assert.ElementsMatch(t, testFiles, rFileNames)
+ t.Run("generate support packet with logs", func(t *testing.T) {
+ fileDatas := th.App.GenerateSupportPacket(th.Context, &model.SupportPacketOptions{
+ IncludeLogs: true,
+ })
+ var rFileNames []string
+ testFiles := []string{
+ "support_packet.yaml",
+ "plugins.json",
+ "sanitized_config.json",
+ "mattermost.log",
+ "notifications.log",
+ "cpu.prof",
+ "heap.prof",
+ "goroutines",
+ }
+ for _, fileData := range fileDatas {
+ require.NotNil(t, fileData)
+ assert.Positive(t, len(fileData.Body))
- // Remove these two files and ensure that warning.txt file is generated
- err = os.Remove(logLocation)
- require.NoError(t, err)
- err = os.Remove(notificationsLogLocation)
- require.NoError(t, err)
- fileDatas = th.App.GenerateSupportPacket(th.Context)
- testFiles = []string{
- "support_packet.yaml",
- "plugins.json",
- "sanitized_config.json",
- "cpu.prof",
- "heap.prof",
- "warning.txt",
- "goroutines",
- }
- rFileNames = nil
- for _, fileData := range fileDatas {
- require.NotNil(t, fileData)
- assert.Positive(t, len(fileData.Body))
+ rFileNames = append(rFileNames, fileData.Filename)
+ }
+ assert.ElementsMatch(t, testFiles, rFileNames)
+ })
- rFileNames = append(rFileNames, fileData.Filename)
- }
- assert.ElementsMatch(t, testFiles, rFileNames)
+ t.Run("generate support packet without logs", func(t *testing.T) {
+ fileDatas := th.App.GenerateSupportPacket(th.Context, &model.SupportPacketOptions{
+ IncludeLogs: false,
+ })
+
+ testFiles := []string{
+ "support_packet.yaml",
+ "plugins.json",
+ "sanitized_config.json",
+ "cpu.prof",
+ "heap.prof",
+ "goroutines",
+ }
+ var rFileNames []string
+ for _, fileData := range fileDatas {
+ require.NotNil(t, fileData)
+ assert.Positive(t, len(fileData.Body))
+
+ rFileNames = append(rFileNames, fileData.Filename)
+ }
+ assert.ElementsMatch(t, testFiles, rFileNames)
+ })
+
+ t.Run("remove the log files and ensure that warning.txt file is generated", func(t *testing.T) {
+ // Remove these two files and ensure that warning.txt file is generated
+ err = os.Remove(logLocation)
+ require.NoError(t, err)
+ err = os.Remove(notificationsLogLocation)
+ require.NoError(t, err)
+ t.Cleanup(genMockLogFiles)
+
+ fileDatas := th.App.GenerateSupportPacket(th.Context, &model.SupportPacketOptions{
+ IncludeLogs: true,
+ })
+ testFiles := []string{
+ "support_packet.yaml",
+ "plugins.json",
+ "sanitized_config.json",
+ "cpu.prof",
+ "heap.prof",
+ "warning.txt",
+ "goroutines",
+ }
+ var rFileNames []string
+ for _, fileData := range fileDatas {
+ require.NotNil(t, fileData)
+ assert.Positive(t, len(fileData.Body))
+
+ rFileNames = append(rFileNames, fileData.Filename)
+ }
+ assert.ElementsMatch(t, testFiles, rFileNames)
+ })
t.Run("steps that generated an error should still return file data", func(t *testing.T) {
mockStore := smocks.Store{}
@@ -241,7 +277,9 @@ func TestGenerateSupportPacket(t *testing.T) {
mockStore.On("GetDbVersion", false).Return("1.0.0", nil)
th.App.Srv().SetStore(&mockStore)
- fileDatas := th.App.GenerateSupportPacket(th.Context)
+ fileDatas := th.App.GenerateSupportPacket(th.Context, &model.SupportPacketOptions{
+ IncludeLogs: false,
+ })
var rFileNames []string
for _, fileData := range fileDatas {
diff --git a/server/public/model/support_packet.go b/server/public/model/support_packet.go
new file mode 100644
index 0000000000..8ec8e523d9
--- /dev/null
+++ b/server/public/model/support_packet.go
@@ -0,0 +1,93 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+package model
+
+import (
+ "encoding/json"
+ "io"
+)
+
+type SupportPacket struct {
+ /* Build information */
+
+ ServerOS string `yaml:"server_os"`
+ ServerArchitecture string `yaml:"server_architecture"`
+ ServerVersion string `yaml:"server_version"`
+ BuildHash string `yaml:"build_hash"`
+
+ /* DB */
+
+ DatabaseType string `yaml:"database_type"`
+ DatabaseVersion string `yaml:"database_version"`
+ DatabaseSchemaVersion string `yaml:"database_schema_version"`
+ WebsocketConnections int `yaml:"websocket_connections"`
+ MasterDbConnections int `yaml:"master_db_connections"`
+ ReplicaDbConnections int `yaml:"read_db_connections"`
+
+ /* Cluster */
+
+ ClusterID string `yaml:"cluster_id"`
+
+ /* File store */
+
+ FileDriver string `yaml:"file_driver"`
+ FileStatus string `yaml:"file_status"`
+
+ /* LDAP */
+
+ LdapVendorName string `yaml:"ldap_vendor_name,omitempty"`
+ LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"`
+
+ /* Elastic Search */
+
+ ElasticServerVersion string `yaml:"elastic_server_version,omitempty"`
+ ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"`
+
+ /* License */
+
+ LicenseTo string `yaml:"license_to"`
+ LicenseSupportedUsers int `yaml:"license_supported_users"`
+ LicenseIsTrial bool `yaml:"license_is_trial,omitempty"`
+
+ /* Server stats */
+
+ ActiveUsers int `yaml:"active_users"`
+ DailyActiveUsers int `yaml:"daily_active_users"`
+ MonthlyActiveUsers int `yaml:"monthly_active_users"`
+ InactiveUserCount int `yaml:"inactive_user_count"`
+ TotalPosts int `yaml:"total_posts"`
+ TotalChannels int `yaml:"total_channels"`
+ TotalTeams int `yaml:"total_teams"`
+
+ /* Jobs */
+
+ DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
+ MessageExportJobs []*Job `yaml:"message_export_jobs"`
+ ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
+ ElasticPostAggregationJobs []*Job `yaml:"elastic_post_aggregation_jobs"`
+ BlevePostIndexingJobs []*Job `yaml:"bleve_post_indexin_jobs"`
+ LdapSyncJobs []*Job `yaml:"ldap_sync_jobs"`
+ MigrationJobs []*Job `yaml:"migration_jobs"`
+}
+
+type FileData struct {
+ Filename string
+ Body []byte
+}
+
+type SupportPacketOptions struct {
+ IncludeLogs bool `json:"include_logs"` // IncludeLogs is the option to include server logs
+ PluginPackets []string `json:"plugin_packets"` // PluginPackets is a list of pluginids to call hooks
+}
+
+// SupportPacketOptionsFromReader decodes a json-encoded request from the given io.Reader.
+func SupportPacketOptionsFromReader(reader io.Reader) (*SupportPacketOptions, error) {
+ var r *SupportPacketOptions
+ err := json.NewDecoder(reader).Decode(&r)
+ if err != nil {
+ return nil, err
+ }
+
+ return r, nil
+}
diff --git a/server/public/model/system.go b/server/public/model/system.go
index ecf3ff0017..bea20ed938 100644
--- a/server/public/model/system.go
+++ b/server/public/model/system.go
@@ -78,73 +78,6 @@ type ServerBusyState struct {
ExpiresTS string `json:"expires_ts,omitempty"`
}
-type SupportPacket struct {
- /* Build information */
-
- ServerOS string `yaml:"server_os"`
- ServerArchitecture string `yaml:"server_architecture"`
- ServerVersion string `yaml:"server_version"`
- BuildHash string `yaml:"build_hash"`
-
- /* DB */
-
- DatabaseType string `yaml:"database_type"`
- DatabaseVersion string `yaml:"database_version"`
- DatabaseSchemaVersion string `yaml:"database_schema_version"`
- WebsocketConnections int `yaml:"websocket_connections"`
- MasterDbConnections int `yaml:"master_db_connections"`
- ReplicaDbConnections int `yaml:"read_db_connections"`
-
- /* Cluster */
-
- ClusterID string `yaml:"cluster_id"`
-
- /* File store */
-
- FileDriver string `yaml:"file_driver"`
- FileStatus string `yaml:"file_status"`
-
- /* LDAP */
-
- LdapVendorName string `yaml:"ldap_vendor_name,omitempty"`
- LdapVendorVersion string `yaml:"ldap_vendor_version,omitempty"`
-
- /* Elastic Search */
-
- ElasticServerVersion string `yaml:"elastic_server_version,omitempty"`
- ElasticServerPlugins []string `yaml:"elastic_server_plugins,omitempty"`
-
- /* License */
-
- LicenseTo string `yaml:"license_to"`
- LicenseSupportedUsers int `yaml:"license_supported_users"`
- LicenseIsTrial bool `yaml:"license_is_trial,omitempty"`
-
- /* Server stats */
-
- ActiveUsers int `yaml:"active_users"`
- DailyActiveUsers int `yaml:"daily_active_users"`
- MonthlyActiveUsers int `yaml:"monthly_active_users"`
- InactiveUserCount int `yaml:"inactive_user_count"`
- TotalPosts int `yaml:"total_posts"`
- TotalChannels int `yaml:"total_channels"`
- TotalTeams int `yaml:"total_teams"`
-
- /* Jobs */
-
- DataRetentionJobs []*Job `yaml:"data_retention_jobs"`
- MessageExportJobs []*Job `yaml:"message_export_jobs"`
- ElasticPostIndexingJobs []*Job `yaml:"elastic_post_indexing_jobs"`
- ElasticPostAggregationJobs []*Job `yaml:"elastic_post_aggregation_jobs"`
- BlevePostIndexingJobs []*Job `yaml:"bleve_post_indexin_jobs"`
- LdapSyncJobs []*Job `yaml:"ldap_sync_jobs"`
- MigrationJobs []*Job `yaml:"migration_jobs"`
-}
-
-type FileData struct {
- Filename string
- Body []byte
-}
type AppliedMigration struct {
Version int `json:"version"`
Name string `json:"name"`
diff --git a/server/public/plugin/client_rpc_generated.go b/server/public/plugin/client_rpc_generated.go
index b5f84a2181..ea1905fa76 100644
--- a/server/public/plugin/client_rpc_generated.go
+++ b/server/public/plugin/client_rpc_generated.go
@@ -1125,6 +1125,42 @@ func (s *hooksRPCServer) OnSharedChannelsProfileImageSyncMsg(args *Z_OnSharedCha
return nil
}
+func init() {
+ hookNameToId["GenerateSupportData"] = GenerateSupportDataID
+}
+
+type Z_GenerateSupportDataArgs struct {
+ A *Context
+}
+
+type Z_GenerateSupportDataReturns struct {
+ A []*model.FileData
+ B error
+}
+
+func (g *hooksRPCClient) GenerateSupportData(c *Context) ([]*model.FileData, error) {
+ _args := &Z_GenerateSupportDataArgs{c}
+ _returns := &Z_GenerateSupportDataReturns{}
+ if g.implemented[GenerateSupportDataID] {
+ if err := g.client.Call("Plugin.GenerateSupportData", _args, _returns); err != nil {
+ g.log.Error("RPC call GenerateSupportData to plugin failed.", mlog.Err(err))
+ }
+ }
+ return _returns.A, _returns.B
+}
+
+func (s *hooksRPCServer) GenerateSupportData(args *Z_GenerateSupportDataArgs, returns *Z_GenerateSupportDataReturns) error {
+ if hook, ok := s.impl.(interface {
+ GenerateSupportData(c *Context) ([]*model.FileData, error)
+ }); ok {
+ returns.A, returns.B = hook.GenerateSupportData(args.A)
+ returns.B = encodableError(returns.B)
+ } else {
+ return encodableError(fmt.Errorf("Hook GenerateSupportData called but not implemented."))
+ }
+ return nil
+}
+
type Z_RegisterCommandArgs struct {
A *model.Command
}
diff --git a/server/public/plugin/hooks.go b/server/public/plugin/hooks.go
index b1dbf032ad..a8b33fe97a 100644
--- a/server/public/plugin/hooks.go
+++ b/server/public/plugin/hooks.go
@@ -60,6 +60,7 @@ const (
PreferencesHaveChangedID = 42
OnSharedChannelsAttachmentSyncMsgID = 43
OnSharedChannelsProfileImageSyncMsgID = 44
+ GenerateSupportDataID = 45
TotalHooksID = iota
)
@@ -382,4 +383,10 @@ type Hooks interface {
//
// Minimum server version: 9.5
OnSharedChannelsProfileImageSyncMsg(user *model.User, rc *model.RemoteCluster) error
+
+ // GenerateSupportData is invoked when a Support Packet gets generated.
+ // It allows plugins to include their own content in the Support Packet.
+ //
+ // Minimum server version: 9.8
+ GenerateSupportData(c *Context) ([]*model.FileData, error)
}
diff --git a/server/public/plugin/hooks_timer_layer_generated.go b/server/public/plugin/hooks_timer_layer_generated.go
index 531be80321..130a8c0545 100644
--- a/server/public/plugin/hooks_timer_layer_generated.go
+++ b/server/public/plugin/hooks_timer_layer_generated.go
@@ -284,3 +284,10 @@ func (hooks *hooksTimerLayer) OnSharedChannelsProfileImageSyncMsg(user *model.Us
hooks.recordTime(startTime, "OnSharedChannelsProfileImageSyncMsg", _returnsA == nil)
return _returnsA
}
+
+func (hooks *hooksTimerLayer) GenerateSupportData(c *Context) ([]*model.FileData, error) {
+ startTime := timePkg.Now()
+ _returnsA, _returnsB := hooks.hooksImpl.GenerateSupportData(c)
+ hooks.recordTime(startTime, "GenerateSupportData", _returnsB == nil)
+ return _returnsA, _returnsB
+}
diff --git a/server/public/plugin/plugintest/hooks.go b/server/public/plugin/plugintest/hooks.go
index c61eae7892..3846798913 100644
--- a/server/public/plugin/plugintest/hooks.go
+++ b/server/public/plugin/plugintest/hooks.go
@@ -105,6 +105,32 @@ func (_m *Hooks) FileWillBeUploaded(c *plugin.Context, info *model.FileInfo, fil
return r0, r1
}
+// GenerateSupportData provides a mock function with given fields: c
+func (_m *Hooks) GenerateSupportData(c *plugin.Context) ([]*model.FileData, error) {
+ ret := _m.Called(c)
+
+ var r0 []*model.FileData
+ var r1 error
+ if rf, ok := ret.Get(0).(func(*plugin.Context) ([]*model.FileData, error)); ok {
+ return rf(c)
+ }
+ if rf, ok := ret.Get(0).(func(*plugin.Context) []*model.FileData); ok {
+ r0 = rf(c)
+ } else {
+ if ret.Get(0) != nil {
+ r0 = ret.Get(0).([]*model.FileData)
+ }
+ }
+
+ if rf, ok := ret.Get(1).(func(*plugin.Context) error); ok {
+ r1 = rf(c)
+ } else {
+ r1 = ret.Error(1)
+ }
+
+ return r0, r1
+}
+
// Implemented provides a mock function with given fields:
func (_m *Hooks) Implemented() ([]string, error) {
ret := _m.Called()
diff --git a/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap b/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap
index 7fe67ed899..e50a9f88ef 100644
--- a/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap
+++ b/webapp/channels/src/components/commercial_support_modal/__snapshots__/commercial_support_modal.test.tsx.snap
@@ -52,11 +52,7 @@ exports[`components/CommercialSupportModal should match snapshot 1`] = `
className="CommercialSupportModal"
>