MM-64518: Update Playbooks license requirements from Enterprise to Professional+ and unprepackage playbooks v1 (#31323)

* Remove TestPlaybooksLicenseChecking test function

Co-Authored-By: Claude <noreply@anthropic.com>

* fix test

* Remove playbooks v1 from prepackaged plugins

- Remove mattermost-plugin-playbooks-v1.41.1 from Makefile
- Remove license-based logic for choosing between playbooks v1/v2
- Remove obsolete test TestGetPrepackagedPlaybooksPluginIn
- Clean up transitionally prepackaged plugins logic
- Only ship playbooks v2.3.0 as regular prepackaged plugin

* Fix formatting with gofmt

* Fix linting issues

- Fix formatting in plugin_test.go
- Remove unnecessary blank line in plugin.go
- Use slices.Contains instead of manual loop

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mattermost Build <build@mattermost.com>
This commit is contained in:
Julien Tant
2025-08-27 13:07:31 -07:00
committed by GitHub
co-authored by Claude Mattermost Build
parent 93ebaf3d9f
commit ec4a6235d4
3 changed files with 2 additions and 141 deletions
-2
View File
@@ -146,8 +146,6 @@ PLUGIN_PACKAGES += mattermost-plugin-calls-v1.10.0
PLUGIN_PACKAGES += mattermost-plugin-github-v2.4.0
PLUGIN_PACKAGES += mattermost-plugin-gitlab-v1.10.0
PLUGIN_PACKAGES += mattermost-plugin-jira-v4.3.0
# We need to prepackage both versions of playbooks and install the correct one based on the server license. See MM-60025.
PLUGIN_PACKAGES += mattermost-plugin-playbooks-v1.41.1
PLUGIN_PACKAGES += mattermost-plugin-playbooks-v2.4.0
PLUGIN_PACKAGES += mattermost-plugin-servicenow-v2.3.4
PLUGIN_PACKAGES += mattermost-plugin-zoom-v1.8.0
-74
View File
@@ -1331,80 +1331,6 @@ func TestGetPrepackagedPluginInMarketplace(t *testing.T) {
})
}
func TestGetPrepackagedPlaybooksPluginIn(t *testing.T) {
mainHelper.Parallel(t)
th := Setup(t)
defer th.TearDown()
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.WriteHeader(http.StatusOK)
json, err := json.Marshal([]*model.MarketplacePlugin{})
require.NoError(t, err)
_, err = res.Write(json)
require.NoError(t, err)
}))
defer testServer.Close()
prepackagePlugins := []*plugin.PrepackagedPlugin{
{
Manifest: &model.Manifest{
Version: "1.40.0",
Id: "playbooks",
},
},
{
Manifest: &model.Manifest{
Version: "2.0.1",
Id: "playbooks",
},
},
}
env := th.App.GetPluginsEnvironment()
env.SetPrepackagedPlugins(prepackagePlugins, nil)
th.App.UpdateConfig(func(cfg *model.Config) {
*cfg.PluginSettings.Enable = true
*cfg.PluginSettings.EnableMarketplace = true
*cfg.PluginSettings.MarketplaceURL = testServer.URL
})
t.Run("playbooks v1 is returned if not licensed", func(t *testing.T) {
plugins, _, err := th.SystemAdminClient.GetMarketplacePlugins(context.Background(), &model.MarketplacePluginFilter{})
require.NoError(t, err)
expectedPlugins := prepackagePlugins[0]
require.Equal(t, expectedPlugins.Manifest.Version, plugins[0].Manifest.Version)
require.Len(t, plugins, 1)
})
t.Run("playbooks v2 is returned if Enterprise licensed", func(t *testing.T) {
lic := th.App.Srv().License()
th.App.Srv().SetLicense(model.NewTestLicenseSKU("enterprise"))
defer th.App.Srv().SetLicense(lic)
plugins, _, err := th.SystemAdminClient.GetMarketplacePlugins(context.Background(), &model.MarketplacePluginFilter{})
require.NoError(t, err)
expectedPlugins := prepackagePlugins[1]
require.Equal(t, expectedPlugins.Manifest.Version, plugins[0].Manifest.Version)
require.Len(t, plugins, 1)
})
t.Run("playbooks v1 is returned if professional licensed", func(t *testing.T) {
lic := th.App.Srv().License()
th.App.Srv().SetLicense(model.NewTestLicenseSKU("professional"))
defer th.App.Srv().SetLicense(lic)
plugins, _, err := th.SystemAdminClient.GetMarketplacePlugins(context.Background(), &model.MarketplacePluginFilter{})
require.NoError(t, err)
expectedPlugins := prepackagePlugins[0]
require.Equal(t, expectedPlugins.Manifest.Version, plugins[0].Manifest.Version)
require.Len(t, plugins, 1)
})
}
func TestInstallMarketplacePlugin(t *testing.T) {
path, _ := fileutils.FindDir("tests")
+2 -65
View File
@@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"sort"
"strings"
"sync"
@@ -679,22 +680,6 @@ func (a *App) mergePrepackagedPlugins(remoteMarketplacePlugins map[string]*model
},
}
// If not enterprise, check version.
// Playbooks is not listed in the marketplace, this only handles prepackaged.
if !model.MinimumEnterpriseLicense(a.License()) {
if prepackaged.Manifest.Id == model.PluginIdPlaybooks {
version, err := semver.Parse(prepackaged.Manifest.Version)
if err != nil {
mlog.Error("Unable to verify prepackaged playbooks version", mlog.Err(err))
continue
}
// Do not show playbooks >=v2 if we do not have an enterprise license
if version.GTE(SemVerV2) {
continue
}
}
}
// If not available in marketplace, add the prepackaged
if remoteMarketplacePlugins[prepackaged.Manifest.Id] == nil {
remoteMarketplacePlugins[prepackaged.Manifest.Id] = prepackagedMarketplace
@@ -1000,8 +985,6 @@ func (ch *Channels) processPrepackagedPlugins(prepackagedPluginsDir string) erro
return nil
}
var SemVerV2 = semver.MustParse("2.0.0")
// processPrepackagedPlugin will return the prepackaged plugin metadata and will also
// install the prepackaged plugin if it had been previously enabled and AutomaticPrepackagedPlugins is true.
func (ch *Channels) processPrepackagedPlugin(pluginPath *pluginSignaturePath) (*plugin.PrepackagedPlugin, error) {
@@ -1031,27 +1014,6 @@ func (ch *Channels) processPrepackagedPlugin(pluginPath *pluginSignaturePath) (*
logger = logger.With(mlog.String("plugin_id", plugin.Manifest.Id))
if plugin.Manifest.Id == model.PluginIdPlaybooks {
version, err := semver.Parse(plugin.Manifest.Version)
if err != nil {
return nil, errors.Wrapf(err, "Unable to verify prepackaged playbooks version")
}
hasEnterpriseLicense := model.MinimumEnterpriseLicense(ch.License())
// Do not install playbooks >=v2 if we do not have an enterprise license
if version.GTE(SemVerV2) && !hasEnterpriseLicense {
logger.Info("Skip installing prepackaged playbooks >=v2 because the license does not allow it")
return plugin, nil
}
// Do not install playbooks <v2 if we have an enterprise license
if version.LT(SemVerV2) && hasEnterpriseLicense {
logger.Info("Skip installing prepackaged playbooks <v2 because the license allows v2")
return plugin, nil
}
}
// Skip installing the plugin at all if automatic prepackaged plugins is disabled
if !*ch.cfgSvc.Config().PluginSettings.AutomaticPrepackagedPlugins {
logger.Info("Not installing prepackaged plugin: automatic prepackaged plugins disabled")
@@ -1084,37 +1046,12 @@ var transitionallyPrepackagedPlugins = []string{
"com.mattermost.plugin-todo",
"com.mattermost.welcomebot",
"com.mattermost.apps",
"playbooks",
}
// pluginIsTransitionallyPrepackaged identifies plugin ids that are currently prepackaged but
// slated for future removal.
func (ch *Channels) pluginIsTransitionallyPrepackaged(m *model.Manifest) bool {
for _, id := range transitionallyPrepackagedPlugins {
if id == m.Id {
if m.Id == model.PluginIdPlaybooks {
return ch.playbooksIsTransitionallyPrepackaged(m)
}
return true
}
}
return false
}
// playbooksIsTransitionallyPrepackaged determines if the playbooks plugin is transitionally prepackaged.
// conditions are:
// - the server is not enterprise licensed
// - the playbooks version is <v2
func (ch *Channels) playbooksIsTransitionallyPrepackaged(m *model.Manifest) bool {
version, err := semver.Parse(m.Version)
if err != nil {
ch.srv.Log().Warn("unable to parse prepackaged playbooks version - not marking it as transitional.", mlog.String("version", m.Version), mlog.Err(err))
return false
}
return !model.MinimumEnterpriseLicense(ch.srv.License()) && version.LT(SemVerV2)
return slices.Contains(transitionallyPrepackagedPlugins, m.Id)
}
// shouldPersistTransitionallyPrepackagedPlugin determines if a transitionally prepackaged plugin