Code: codeownership for feature toggles (#64266)

* ownership for feature toggles v2

* add traceqlSearch

* MT -> app platform

* assign publicdashboards

---------

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Artur Wierzbicki 2023-03-07 20:04:20 +04:00 committed by GitHub
parent 1c2e3993f6
commit 13650f3dc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 0 deletions

View File

@ -0,0 +1,15 @@
package featuremgmt
// codeowner string that references a GH team or user
// the value must match the format used in the CODEOWNERS file
type codeowner string
const (
grafanaAppPlatformSquad codeowner = "@grafana/grafana-app-platform-squad"
grafanaDashboardsSquad codeowner = "@grafana/dashboards-squad"
grafanaBiSquad codeowner = "@grafana/grafana-bi-squad"
grafanaDatavizSquad codeowner = "@grafana/dataviz-squad"
grafanaUserEssentialsSquad codeowner = "@grafana/user-essentials"
grafanaBackendPlatformSquad codeowner = "@grafana/backend-platform"
grafanaPluginsPlatformSquad codeowner = "@grafana/plugins-platform-backend"
)

View File

@ -85,6 +85,9 @@ type FeatureFlag struct {
State FeatureFlagState `json:"state,omitempty"`
DocsURL string `json:"docsURL,omitempty"`
// Owner person or team that owns this feature flag
Owner codeowner `json:"-"`
// CEL-GO expression. Using the value "true" will mean this is on by default
Expression string `json:"expression,omitempty"`

View File

@ -33,28 +33,33 @@ var (
Name: "dashboardPreviews",
Description: "Create and show thumbnails for dashboard search results",
State: FeatureStateAlpha,
Owner: grafanaAppPlatformSquad,
},
{
Name: "live-pipeline",
Description: "Enable a generic live processing pipeline",
State: FeatureStateAlpha,
Owner: grafanaAppPlatformSquad,
},
{
Name: "live-service-web-worker",
Description: "This will use a webworker thread to processes events rather than the main thread",
State: FeatureStateAlpha,
FrontendOnly: true,
Owner: grafanaAppPlatformSquad,
},
{
Name: "queryOverLive",
Description: "Use Grafana Live WebSocket to execute backend queries",
State: FeatureStateAlpha,
FrontendOnly: true,
Owner: grafanaAppPlatformSquad,
},
{
Name: "panelTitleSearch",
Description: "Search for dashboards using panel title",
State: FeatureStateBeta,
Owner: grafanaAppPlatformSquad,
},
{
Name: "prometheusAzureOverrideAudience",
@ -65,6 +70,7 @@ var (
Name: "publicDashboards",
Description: "Enables public access to dashboards",
State: FeatureStateAlpha,
Owner: grafanaDashboardsSquad,
},
{
Name: "publicDashboardsEmailSharing",
@ -72,11 +78,13 @@ var (
State: FeatureStateAlpha,
RequiresLicense: true,
RequiresDevMode: true,
Owner: grafanaDashboardsSquad,
},
{
Name: "lokiLive",
Description: "Support WebSocket streaming for loki (early prototype)",
State: FeatureStateAlpha,
Owner: grafanaAppPlatformSquad,
},
{
Name: "lokiDataframeApi",
@ -92,11 +100,13 @@ var (
Name: "dashboardComments",
Description: "Enable dashboard-wide comments",
State: FeatureStateAlpha,
Owner: grafanaAppPlatformSquad,
},
{
Name: "annotationComments",
Description: "Enable annotation comments",
State: FeatureStateAlpha,
Owner: grafanaAppPlatformSquad,
},
{
Name: "migrationLocking",
@ -107,18 +117,21 @@ var (
Name: "storage",
Description: "Configurable storage for dashboards, datasources, and resources",
State: FeatureStateAlpha,
Owner: grafanaAppPlatformSquad,
},
{
Name: "k8s",
Description: "Explore native k8s integrations",
State: FeatureStateAlpha,
RequiresDevMode: true,
Owner: grafanaAppPlatformSquad,
},
{
Name: "dashboardsFromStorage",
Description: "Load dashboards from the generic storage interface",
State: FeatureStateAlpha,
RequiresDevMode: true, // Also a gate on automatic git storage (for now)
Owner: grafanaAppPlatformSquad,
},
{
Name: "exploreMixedDatasource",
@ -153,6 +166,7 @@ var (
Name: "datasourceQueryMultiStatus",
Description: "Introduce HTTP 207 Multi Status for api/ds/query",
State: FeatureStateAlpha,
Owner: grafanaPluginsPlatformSquad,
},
{
Name: "traceToMetrics",
@ -164,6 +178,7 @@ var (
Name: "newDBLibrary",
Description: "Use jmoiron/sqlx rather than xorm for a few backend services",
State: FeatureStateBeta,
Owner: grafanaBackendPlatformSquad,
},
{
Name: "validateDashboardsOnSave",
@ -176,6 +191,7 @@ var (
Description: "Replace the angular graph panel with timeseries",
State: FeatureStateBeta,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "prometheusWideSeries",
@ -187,12 +203,14 @@ var (
Description: "Allow elements nesting",
State: FeatureStateAlpha,
FrontendOnly: true,
Owner: grafanaDatavizSquad,
},
{
Name: "scenes",
Description: "Experimental framework to build interactive dashboards",
State: FeatureStateAlpha,
FrontendOnly: true,
Owner: grafanaDashboardsSquad,
},
{
Name: "disableSecretsCompatibility",
@ -215,23 +233,27 @@ var (
Description: "Enables internationalization",
State: FeatureStateStable,
Expression: "true", // enabled by default
Owner: grafanaUserEssentialsSquad,
},
{
Name: "topnav",
Description: "Displays new top nav and page layouts",
State: FeatureStateBeta,
Owner: grafanaUserEssentialsSquad,
},
{
Name: "grpcServer",
Description: "Run GRPC server",
State: FeatureStateAlpha,
RequiresDevMode: true,
Owner: grafanaAppPlatformSquad,
},
{
Name: "entityStore",
Description: "SQL-based entity store (requires storage flag also)",
State: FeatureStateAlpha,
RequiresDevMode: true,
Owner: grafanaAppPlatformSquad,
},
{
Name: "cloudWatchCrossAccountQuerying",
@ -262,6 +284,7 @@ var (
Description: "Reusable query library",
State: FeatureStateAlpha,
RequiresDevMode: true,
Owner: grafanaAppPlatformSquad,
},
{
Name: "showDashboardValidationWarnings",
@ -324,6 +347,7 @@ var (
Description: "Enables drag and drop for CSV and Excel files",
FrontendOnly: true,
State: FeatureStateAlpha,
Owner: grafanaBiSquad,
},
{
Name: "alertingNoNormalState",
@ -361,6 +385,7 @@ var (
Description: "Changes the user experience for data source selection to a drawer.",
State: FeatureStateAlpha,
FrontendOnly: true,
Owner: grafanaBiSquad,
},
{
Name: "traceqlSearch",

View File

@ -41,6 +41,69 @@ func TestFeatureToggleFiles(t *testing.T) {
}
})
ownerlessFeatures := map[string]bool{
"alertingBigTransactions": true,
"trimDefaults": true,
"disableEnvelopeEncryption": true,
"database_metrics": true,
"prometheusAzureOverrideAudience": true,
"lokiDataframeApi": true,
"featureHighlights": true,
"migrationLocking": true,
"exploreMixedDatasource": true,
"tracing": true,
"newTraceView": true,
"correlations": true,
"cloudWatchDynamicLabels": true,
"traceToMetrics": true,
"validateDashboardsOnSave": true,
"prometheusWideSeries": true,
"disableSecretsCompatibility": true,
"logRequestsInstrumentedAsUnknown": true,
"dataConnectionsConsole": true,
"cloudWatchCrossAccountQuerying": true,
"redshiftAsyncQueryDataSupport": true,
"athenaAsyncQueryDataSupport": true,
"newPanelChromeUI": true,
"showDashboardValidationWarnings": true,
"mysqlAnsiQuotes": true,
"accessControlOnCall": true,
"nestedFolders": true,
"accessTokenExpirationCheck": true,
"elasticsearchBackendMigration": true,
"datasourceOnboarding": true,
"secureSocksDatasourceProxy": true,
"authnService": true,
"disablePrometheusExemplarSampling": true,
"alertingBacktesting": true,
"alertingNoNormalState": true,
"logsSampleInExplore": true,
"logsContextDatasourceUi": true,
"lokiQuerySplitting": true,
"individualCookiePreferences": true,
"traceqlSearch": true,
}
t.Run("all new features should have an owner", func(t *testing.T) {
for _, flag := range standardFeatureFlags {
if flag.Owner == "" {
if _, ok := ownerlessFeatures[flag.Name]; !ok {
t.Errorf("feature %s does not have an owner", flag.Name)
}
}
}
})
t.Run("features with assigned owner should not be on the ownerless list", func(t *testing.T) {
for _, flag := range standardFeatureFlags {
if flag.Owner != "" {
if _, ok := ownerlessFeatures[flag.Name]; ok {
t.Errorf("feature %s should be removed from the ownerless list", flag.Name)
}
}
}
})
t.Run("verify files", func(t *testing.T) {
// Typescript files
verifyAndGenerateFile(t,