mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat: add experimental flag (#4364)
This commit is contained in:
+18
@@ -48,10 +48,12 @@ const (
|
||||
varNoFeatureWarning = "no-feature-warning"
|
||||
varForceTty = "force-tty"
|
||||
varVerbose = "verbose"
|
||||
varExperimental = "experimental"
|
||||
notLoggedInMessage = "You are not logged in. Try logging in using 'coder login <url>'."
|
||||
|
||||
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
|
||||
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
|
||||
envExperimental = "CODER_EXPERIMENTAL"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -184,6 +186,7 @@ func Root(subcommands []*cobra.Command) *cobra.Command {
|
||||
cmd.PersistentFlags().Bool(varNoOpen, false, "Block automatically opening URLs in the browser.")
|
||||
_ = cmd.PersistentFlags().MarkHidden(varNoOpen)
|
||||
cliflag.Bool(cmd.PersistentFlags(), varVerbose, "v", "CODER_VERBOSE", false, "Enable verbose output.")
|
||||
cliflag.Bool(cmd.PersistentFlags(), varExperimental, "", envExperimental, false, "Enable experimental features. Experimental features are not ready for production.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -598,3 +601,18 @@ func (h *headerTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
}
|
||||
return h.transport.RoundTrip(req)
|
||||
}
|
||||
|
||||
// ExperimentalEnabled returns if the experimental feature flag is enabled.
|
||||
func ExperimentalEnabled(cmd *cobra.Command) bool {
|
||||
return cliflag.IsSetBool(cmd, varExperimental)
|
||||
}
|
||||
|
||||
// EnsureExperimental will ensure that the experimental feature flag is set if the given flag is set.
|
||||
func EnsureExperimental(cmd *cobra.Command, name string) error {
|
||||
_, set := cliflag.IsSet(cmd, name)
|
||||
if set && !ExperimentalEnabled(cmd) {
|
||||
return xerrors.Errorf("flag %s is set but requires flag --experimental or environment variable CODER_EXPERIMENTAL=true.", name)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/coder/coder/buildinfo"
|
||||
"github.com/coder/coder/cli"
|
||||
"github.com/coder/coder/cli/cliflag"
|
||||
"github.com/coder/coder/cli/clitest"
|
||||
"github.com/coder/coder/codersdk"
|
||||
)
|
||||
@@ -153,4 +154,19 @@ func TestRoot(t *testing.T) {
|
||||
// This won't succeed, because we're using the login cmd to assert requests.
|
||||
_ = cmd.Execute()
|
||||
})
|
||||
|
||||
t.Run("Experimental", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cmd, _ := clitest.New(t, "--experimental")
|
||||
err := cmd.Execute()
|
||||
require.NoError(t, err)
|
||||
require.True(t, cli.ExperimentalEnabled(cmd))
|
||||
|
||||
cmd, _ = clitest.New(t, "help", "--verbose")
|
||||
_ = cmd.Execute()
|
||||
_, set := cliflag.IsSet(cmd, "verbose")
|
||||
require.True(t, set)
|
||||
require.ErrorContains(t, cli.EnsureExperimental(cmd, "verbose"), "--experimental")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -368,6 +368,7 @@ func Server(newAPI func(context.Context, *coderd.Options) (*coderd.API, error))
|
||||
AutoImportTemplates: validatedAutoImportTemplates,
|
||||
MetricsCacheRefreshInterval: metricsCacheRefreshInterval,
|
||||
AgentStatsRefreshInterval: agentStatRefreshInterval,
|
||||
Experimental: ExperimentalEnabled(cmd),
|
||||
}
|
||||
|
||||
if oauth2GithubClientSecret != "" {
|
||||
|
||||
@@ -81,6 +81,7 @@ type Options struct {
|
||||
|
||||
MetricsCacheRefreshInterval time.Duration
|
||||
AgentStatsRefreshInterval time.Duration
|
||||
Experimental bool
|
||||
}
|
||||
|
||||
// New constructs a Coder API handler.
|
||||
|
||||
@@ -38,9 +38,10 @@ type Feature struct {
|
||||
}
|
||||
|
||||
type Entitlements struct {
|
||||
Features map[string]Feature `json:"features"`
|
||||
Warnings []string `json:"warnings"`
|
||||
HasLicense bool `json:"has_license"`
|
||||
Features map[string]Feature `json:"features"`
|
||||
Warnings []string `json:"warnings"`
|
||||
HasLicense bool `json:"has_license"`
|
||||
Experimental bool `json:"experimental"`
|
||||
}
|
||||
|
||||
func (c *Client) Entitlements(ctx context.Context) (Entitlements, error) {
|
||||
|
||||
@@ -68,5 +68,6 @@ func TestFeaturesList(t *testing.T) {
|
||||
assert.Equal(t, codersdk.EntitlementNotEntitled,
|
||||
entitlements.Features[codersdk.FeatureWorkspaceQuota].Entitlement)
|
||||
assert.False(t, entitlements.HasLicense)
|
||||
assert.False(t, entitlements.Experimental)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -346,8 +346,9 @@ func (*fakeLicenseAPI) entitlements(rw http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.Entitlements{
|
||||
Features: features,
|
||||
Warnings: []string{testWarning},
|
||||
HasLicense: true,
|
||||
Features: features,
|
||||
Warnings: []string{testWarning},
|
||||
HasLicense: true,
|
||||
Experimental: true,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -237,9 +237,10 @@ func (api *API) serveEntitlements(rw http.ResponseWriter, r *http.Request) {
|
||||
api.entitlementsMu.RUnlock()
|
||||
|
||||
resp := codersdk.Entitlements{
|
||||
Features: make(map[string]codersdk.Feature),
|
||||
Warnings: make([]string, 0),
|
||||
HasLicense: entitlements.hasLicense,
|
||||
Features: make(map[string]codersdk.Feature),
|
||||
Warnings: make([]string, 0),
|
||||
HasLicense: entitlements.hasLicense,
|
||||
Experimental: api.Experimental,
|
||||
}
|
||||
|
||||
if entitlements.activeUsers.Limit != nil {
|
||||
|
||||
@@ -29,6 +29,7 @@ export const defaultEntitlements = (): TypesGen.Entitlements => {
|
||||
features: features,
|
||||
has_license: false,
|
||||
warnings: [],
|
||||
experimental: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,6 +244,7 @@ export interface Entitlements {
|
||||
readonly features: Record<string, Feature>
|
||||
readonly warnings: string[]
|
||||
readonly has_license: boolean
|
||||
readonly experimental: boolean
|
||||
}
|
||||
|
||||
// From codersdk/features.go
|
||||
|
||||
@@ -771,11 +771,13 @@ export const MockEntitlements: TypesGen.Entitlements = {
|
||||
warnings: [],
|
||||
has_license: false,
|
||||
features: {},
|
||||
experimental: false,
|
||||
}
|
||||
|
||||
export const MockEntitlementsWithWarnings: TypesGen.Entitlements = {
|
||||
warnings: ["You are over your active user limit.", "And another thing."],
|
||||
has_license: true,
|
||||
experimental: false,
|
||||
features: {
|
||||
user_limit: {
|
||||
enabled: true,
|
||||
@@ -797,6 +799,7 @@ export const MockEntitlementsWithWarnings: TypesGen.Entitlements = {
|
||||
export const MockEntitlementsWithAuditLog: TypesGen.Entitlements = {
|
||||
warnings: [],
|
||||
has_license: true,
|
||||
experimental: false,
|
||||
features: {
|
||||
audit_log: {
|
||||
enabled: true,
|
||||
|
||||
@@ -23,6 +23,7 @@ const emptyEntitlements = {
|
||||
warnings: [],
|
||||
features: {},
|
||||
has_license: false,
|
||||
experimental: false,
|
||||
}
|
||||
|
||||
export const entitlementsMachine = createMachine(
|
||||
|
||||
Reference in New Issue
Block a user