[MM-44056] Make Calls plugin's state on Cloud controllable by feature flag (#20161)

* Make Calls plugin's state on Cloud controllable by feature flag

* Prepackage Calls v0.4.9 (#20148)

* Update app/plugin.go

Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>

* Update app/plugin_install.go

Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>

* Bump Calls version to latest

Co-authored-by: Jesse Hallam <jesse.hallam@gmail.com>
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
Claudio Costa
2022-05-10 19:29:48 +02:00
коммит произвёл GitHub
родитель a4ad6eda5d
Коммит aee68c7ae4
9 изменённых файлов: 155 добавлений и 6 удалений

Просмотреть файл

@@ -119,6 +119,7 @@ TEMPLATES_DIR=templates
PLUGIN_PACKAGES ?= mattermost-plugin-antivirus-v0.1.2 PLUGIN_PACKAGES ?= mattermost-plugin-antivirus-v0.1.2
PLUGIN_PACKAGES += mattermost-plugin-autolink-v1.2.2 PLUGIN_PACKAGES += mattermost-plugin-autolink-v1.2.2
PLUGIN_PACKAGES += mattermost-plugin-aws-SNS-v1.2.0 PLUGIN_PACKAGES += mattermost-plugin-aws-SNS-v1.2.0
PLUGIN_PACKAGES += mattermost-plugin-calls-v0.5.1
PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0 PLUGIN_PACKAGES += mattermost-plugin-channel-export-v1.0.0
PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.0 PLUGIN_PACKAGES += mattermost-plugin-custom-attributes-v1.3.0
PLUGIN_PACKAGES += mattermost-plugin-github-v2.0.1 PLUGIN_PACKAGES += mattermost-plugin-github-v2.0.1

Просмотреть файл

@@ -98,11 +98,8 @@ func (ch *Channels) syncPluginsActiveState() {
pluginEnabled = state.Enable pluginEnabled = state.Enable
} }
// Tie Apps proxy disabled status to the feature flag. if hasOverride, value := ch.getPluginStateOverride(pluginID); hasOverride {
if pluginID == "com.mattermost.apps" { pluginEnabled = value
if !ch.cfgSvc.Config().FeatureFlags.AppsEnabled {
pluginEnabled = false
}
} }
if pluginEnabled { if pluginEnabled {
@@ -1064,3 +1061,19 @@ func getIcon(iconPath string) (string, error) {
return fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(icon)), nil return fmt.Sprintf("data:image/svg+xml;base64,%s", base64.StdEncoding.EncodeToString(icon)), nil
} }
func (ch *Channels) getPluginStateOverride(pluginID string) (bool, bool) {
switch pluginID {
case "com.mattermost.apps":
// Tie Apps proxy disabled status to the feature flag.
if !ch.cfgSvc.Config().FeatureFlags.AppsEnabled {
return true, false
}
case "com.mattermost.calls":
if model.IsCloud() {
return true, ch.cfgSvc.Config().FeatureFlags.CallsEnabled
}
}
return false, false
}

Просмотреть файл

@@ -393,9 +393,10 @@ func (ch *Channels) installExtractedPlugin(manifest *model.Manifest, fromPluginD
// Activate the plugin if enabled. // Activate the plugin if enabled.
pluginState := ch.cfgSvc.Config().PluginSettings.PluginStates[manifest.Id] pluginState := ch.cfgSvc.Config().PluginSettings.PluginStates[manifest.Id]
if pluginState != nil && pluginState.Enable { if pluginState != nil && pluginState.Enable {
if manifest.Id == "com.mattermost.apps" && !ch.cfgSvc.Config().FeatureFlags.AppsEnabled { if hasOverride, enabled := ch.getPluginStateOverride(manifest.Id); hasOverride && !enabled {
return manifest, nil return manifest, nil
} }
updatedManifest, _, err := pluginsEnvironment.Activate(manifest.Id) updatedManifest, _, err := pluginsEnvironment.Activate(manifest.Id)
if err != nil { if err != nil {
return nil, model.NewAppError("installExtractedPlugin", "app.plugin.restart.app_error", nil, err.Error(), http.StatusInternalServerError) return nil, model.NewAppError("installExtractedPlugin", "app.plugin.restart.app_error", nil, err.Error(), http.StatusInternalServerError)

Просмотреть файл

@@ -965,3 +965,78 @@ func TestProcessPrepackagedPlugins(t *testing.T) {
require.Len(t, pluginStatus, 0) require.Len(t, pluginStatus, 0)
}) })
} }
func TestGetPluginStateOverride(t *testing.T) {
th := Setup(t)
defer th.TearDown()
t.Run("no override", func(t *testing.T) {
overrides, value := th.App.ch.getPluginStateOverride("focalboard")
require.False(t, overrides)
require.False(t, value)
})
t.Run("calls override", func(t *testing.T) {
t.Run("on-prem", func(t *testing.T) {
overrides, value := th.App.ch.getPluginStateOverride("com.mattermost.calls")
require.False(t, overrides)
require.False(t, value)
})
t.Run("Cloud, without enabled flag", func(t *testing.T) {
os.Setenv("MM_CLOUD_INSTALLATION_ID", "test")
defer os.Unsetenv("MM_CLOUD_INSTALLATION_ID")
overrides, value := th.App.ch.getPluginStateOverride("com.mattermost.calls")
require.True(t, overrides)
require.False(t, value)
})
t.Run("Cloud, with enabled flag set to true", func(t *testing.T) {
os.Setenv("MM_CLOUD_INSTALLATION_ID", "test")
defer os.Unsetenv("MM_CLOUD_INSTALLATION_ID")
os.Setenv("MM_FEATUREFLAGS_CALLSENABLED", "true")
defer os.Unsetenv("MM_FEATUREFLAGS_CALLSENABLED")
th2 := Setup(t)
defer th2.TearDown()
overrides, value := th2.App.ch.getPluginStateOverride("com.mattermost.calls")
require.True(t, overrides)
require.True(t, value)
})
t.Run("Cloud, with enabled flag set to false", func(t *testing.T) {
os.Setenv("MM_CLOUD_INSTALLATION_ID", "test")
defer os.Unsetenv("MM_CLOUD_INSTALLATION_ID")
os.Setenv("MM_FEATUREFLAGS_CALLSENABLED", "false")
defer os.Unsetenv("MM_FEATUREFLAGS_CALLSENABLED")
th2 := Setup(t)
defer th2.TearDown()
overrides, value := th2.App.ch.getPluginStateOverride("com.mattermost.calls")
require.True(t, overrides)
require.False(t, value)
})
})
t.Run("apps override", func(t *testing.T) {
t.Run("without enabled flag", func(t *testing.T) {
overrides, value := th.App.ch.getPluginStateOverride("com.mattermost.apps")
require.False(t, overrides)
require.False(t, value)
})
t.Run("with enabled flag set to false", func(t *testing.T) {
os.Setenv("MM_FEATUREFLAGS_APPSENABLED", "false")
defer os.Unsetenv("MM_FEATUREFLAGS_APPSENABLED")
th2 := Setup(t)
defer th2.TearDown()
overrides, value := th2.App.ch.getPluginStateOverride("com.mattermost.apps")
require.True(t, overrides)
require.False(t, value)
})
})
}

Просмотреть файл

@@ -170,6 +170,11 @@ else
@# Prepackage plugins @# Prepackage plugins
@for plugin_package in $(PLUGIN_PACKAGES) ; do \ @for plugin_package in $(PLUGIN_PACKAGES) ; do \
ARCH=$(PLUGIN_ARCH); \ ARCH=$(PLUGIN_ARCH); \
if [ "$$ARCH" != "linux-amd64" ]; then \
case $$plugin_package in \
"mattermost-plugin-calls"*) continue ;; \
esac; \
fi; \
cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz $(DIST_PATH_GENERIC)/prepackaged_plugins; \ cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz $(DIST_PATH_GENERIC)/prepackaged_plugins; \
cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz.sig $(DIST_PATH_GENERIC)/prepackaged_plugins; \ cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz.sig $(DIST_PATH_GENERIC)/prepackaged_plugins; \
HAS_ARCH=`tar -tf $(DIST_PATH_GENERIC)/prepackaged_plugins/$$plugin_package-$$ARCH.tar.gz | grep -oE "dist/plugin-.*"`; \ HAS_ARCH=`tar -tf $(DIST_PATH_GENERIC)/prepackaged_plugins/$$plugin_package-$$ARCH.tar.gz | grep -oE "dist/plugin-.*"`; \
@@ -234,6 +239,9 @@ endif
@# Prepackage plugins @# Prepackage plugins
@for plugin_package in $(PLUGIN_PACKAGES) ; do \ @for plugin_package in $(PLUGIN_PACKAGES) ; do \
ARCH="windows-amd64"; \ ARCH="windows-amd64"; \
case $$plugin_package in \
"mattermost-plugin-calls"*) continue ;; \
esac; \
cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz $(DIST_PATH_WIN)/prepackaged_plugins; \ cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz $(DIST_PATH_WIN)/prepackaged_plugins; \
cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz.sig $(DIST_PATH_WIN)/prepackaged_plugins; \ cp tmpprepackaged/$$plugin_package-$$ARCH.tar.gz.sig $(DIST_PATH_WIN)/prepackaged_plugins; \
HAS_ARCH=`tar -tf $(DIST_PATH_WIN)/prepackaged_plugins/$$plugin_package-$$ARCH.tar.gz | grep -oE "dist/plugin-.*"`; \ HAS_ARCH=`tar -tf $(DIST_PATH_WIN)/prepackaged_plugins/$$plugin_package-$$ARCH.tar.gz | grep -oE "dist/plugin-.*"`; \

Просмотреть файл

@@ -2810,6 +2810,11 @@ func (s *PluginSettings) SetDefaults(ls LogSettings) {
s.PluginStates["com.mattermost.apps"] = &PluginState{Enable: true} s.PluginStates["com.mattermost.apps"] = &PluginState{Enable: true}
} }
if s.PluginStates["com.mattermost.calls"] == nil && IsCloud() {
// Enable the calls plugin by default on Cloud only
s.PluginStates["com.mattermost.calls"] = &PluginState{Enable: true}
}
if s.EnableMarketplace == nil { if s.EnableMarketplace == nil {
s.EnableMarketplace = NewBool(PluginSettingsDefaultEnableMarketplace) s.EnableMarketplace = NewBool(PluginSettingsDefaultEnableMarketplace)
} }

Просмотреть файл

@@ -6,6 +6,7 @@ package model
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"os"
"reflect" "reflect"
"testing" "testing"
@@ -1491,3 +1492,38 @@ func TestConfigServiceSettingsIsValid(t *testing.T) {
require.NotNil(t, err) require.NotNil(t, err)
require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", err.Id) require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", err.Id)
} }
func TestConfigDefaultCallsPluginState(t *testing.T) {
t.Run("should not enable Calls plugin by default when not in Cloud", func(t *testing.T) {
c1 := Config{}
c1.SetDefaults()
assert.Nil(t, c1.PluginSettings.PluginStates["com.mattermost.calls"])
})
t.Run("should enable Calls plugin by default on Cloud", func(t *testing.T) {
os.Setenv("MM_CLOUD_INSTALLATION_ID", "test")
defer os.Unsetenv("MM_CLOUD_INSTALLATION_ID")
c1 := Config{}
c1.SetDefaults()
assert.True(t, c1.PluginSettings.PluginStates["com.mattermost.calls"].Enable)
})
t.Run("should not re-enable Calls plugin after it has been disabled", func(t *testing.T) {
os.Setenv("MM_CLOUD_INSTALLATION_ID", "test")
defer os.Unsetenv("MM_CLOUD_INSTALLATION_ID")
c1 := Config{
PluginSettings: PluginSettings{
PluginStates: map[string]*PluginState{
"com.mattermost.calls": {
Enable: false,
},
},
},
}
c1.SetDefaults()
assert.False(t, c1.PluginSettings.PluginStates["com.mattermost.calls"].Enable)
})
}

Просмотреть файл

@@ -32,12 +32,16 @@ type FeatureFlags struct {
PluginPlaybooks string `plugin_id:"playbooks"` PluginPlaybooks string `plugin_id:"playbooks"`
PluginApps string `plugin_id:"com.mattermost.apps"` PluginApps string `plugin_id:"com.mattermost.apps"`
PluginFocalboard string `plugin_id:"focalboard"` PluginFocalboard string `plugin_id:"focalboard"`
PluginCalls string `plugin_id:"com.mattermost.calls"`
PermalinkPreviews bool PermalinkPreviews bool
// Enable Calls plugin support in the mobile app // Enable Calls plugin support in the mobile app
CallsMobile bool CallsMobile bool
// CallsEnabled controls whether or not the Calls plugin should be enabled
CallsEnabled bool
// A dash separated list for feature flags to turn on for Boards // A dash separated list for feature flags to turn on for Boards
BoardsFeatureFlags string BoardsFeatureFlags string
@@ -93,6 +97,7 @@ func (f *FeatureFlags) SetDefaults() {
f.CloudFree = false f.CloudFree = false
f.CommandPalette = false f.CommandPalette = false
} }
func (f *FeatureFlags) Plugins() map[string]string { func (f *FeatureFlags) Plugins() map[string]string {
rFFVal := reflect.ValueOf(f).Elem() rFFVal := reflect.ValueOf(f).Elem()
rFFType := reflect.TypeOf(f).Elem() rFFType := reflect.TypeOf(f).Elem()

Просмотреть файл

@@ -16,6 +16,7 @@ import (
"net/http" "net/http"
"net/mail" "net/mail"
"net/url" "net/url"
"os"
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
@@ -691,3 +692,7 @@ func filterBlocklist(r rune) rune {
return r return r
} }
func IsCloud() bool {
return os.Getenv("MM_CLOUD_INSTALLATION_ID") != ""
}