mirror of https://github.com/coder/coder.git
feat: remove workspace_actions experiment (#11427)
This commit is contained in:
parent
04afb88e6f
commit
9b437032e9
|
@ -49,18 +49,6 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
|
|||
isTemplateSchedulingOptionsSet := failureTTL != 0 || dormancyThreshold != 0 || dormancyAutoDeletion != 0 || maxTTL != 0
|
||||
|
||||
if isTemplateSchedulingOptionsSet || requireActiveVersion {
|
||||
if failureTTL != 0 || dormancyThreshold != 0 || dormancyAutoDeletion != 0 {
|
||||
// This call can be removed when workspace_actions is no longer experimental
|
||||
experiments, exErr := client.Experiments(inv.Context())
|
||||
if exErr != nil {
|
||||
return xerrors.Errorf("get experiments: %w", exErr)
|
||||
}
|
||||
|
||||
if !experiments.Enabled(codersdk.ExperimentWorkspaceActions) {
|
||||
return xerrors.Errorf("--failure-ttl, --dormancy-threshold, and --dormancy-auto-deletion are experimental features. Use the workspace_actions CODER_EXPERIMENTS flag to set these configuration values.")
|
||||
}
|
||||
}
|
||||
|
||||
entitlements, err := client.Entitlements(inv.Context())
|
||||
if cerr, ok := codersdk.AsError(err); ok && cerr.StatusCode() == http.StatusNotFound {
|
||||
return xerrors.Errorf("your deployment appears to be an AGPL deployment, so you cannot set enterprise-only flags")
|
||||
|
|
|
@ -47,18 +47,6 @@ func (r *RootCmd) templateEdit() *clibase.Cmd {
|
|||
),
|
||||
Short: "Edit the metadata of a template by name.",
|
||||
Handler: func(inv *clibase.Invocation) error {
|
||||
// This clause can be removed when workspace_actions is no longer experimental
|
||||
if failureTTL != 0 || dormancyThreshold != 0 || dormancyAutoDeletion != 0 {
|
||||
experiments, exErr := client.Experiments(inv.Context())
|
||||
if exErr != nil {
|
||||
return xerrors.Errorf("get experiments: %w", exErr)
|
||||
}
|
||||
|
||||
if !experiments.Enabled(codersdk.ExperimentWorkspaceActions) {
|
||||
return xerrors.Errorf("--failure-ttl, --dormancy-threshold, and --dormancy-auto-deletion are experimental features. Use the workspace_actions CODER_EXPERIMENTS flag to set these configuration values.")
|
||||
}
|
||||
}
|
||||
|
||||
unsetAutostopRequirementDaysOfWeek := len(autostopRequirementDaysOfWeek) == 1 && autostopRequirementDaysOfWeek[0] == "none"
|
||||
requiresScheduling := (len(autostopRequirementDaysOfWeek) > 0 && !unsetAutostopRequirementDaysOfWeek) ||
|
||||
autostopRequirementWeeks > 0 ||
|
||||
|
|
|
@ -9108,11 +9108,9 @@ const docTemplate = `{
|
|||
"codersdk.Experiment": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"workspace_actions",
|
||||
"deployment_health_page"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"ExperimentWorkspaceActions",
|
||||
"ExperimentDeploymentHealthPage"
|
||||
]
|
||||
},
|
||||
|
|
|
@ -8153,11 +8153,8 @@
|
|||
},
|
||||
"codersdk.Experiment": {
|
||||
"type": "string",
|
||||
"enum": ["workspace_actions", "deployment_health_page"],
|
||||
"x-enum-varnames": [
|
||||
"ExperimentWorkspaceActions",
|
||||
"ExperimentDeploymentHealthPage"
|
||||
]
|
||||
"enum": ["deployment_health_page"],
|
||||
"x-enum-varnames": ["ExperimentDeploymentHealthPage"]
|
||||
},
|
||||
"codersdk.ExternalAuth": {
|
||||
"type": "object",
|
||||
|
|
|
@ -2077,9 +2077,6 @@ func (c *Client) BuildInfo(ctx context.Context) (BuildInfoResponse, error) {
|
|||
type Experiment string
|
||||
|
||||
const (
|
||||
// https://github.com/coder/coder/milestone/19
|
||||
ExperimentWorkspaceActions Experiment = "workspace_actions"
|
||||
|
||||
// Deployment health page
|
||||
ExperimentDeploymentHealthPage Experiment = "deployment_health_page"
|
||||
|
||||
|
|
|
@ -563,7 +563,7 @@ curl -X GET http://coder-server:8080/api/v2/experiments \
|
|||
> 200 Response
|
||||
|
||||
```json
|
||||
["workspace_actions"]
|
||||
["deployment_health_page"]
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
@ -600,7 +600,7 @@ curl -X GET http://coder-server:8080/api/v2/experiments/available \
|
|||
> 200 Response
|
||||
|
||||
```json
|
||||
["workspace_actions"]
|
||||
["deployment_health_page"]
|
||||
```
|
||||
|
||||
### Responses
|
||||
|
|
|
@ -2869,7 +2869,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
## codersdk.Experiment
|
||||
|
||||
```json
|
||||
"workspace_actions"
|
||||
"deployment_health_page"
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
@ -2878,7 +2878,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||
|
||||
| Value |
|
||||
| ------------------------ |
|
||||
| `workspace_actions` |
|
||||
| `deployment_health_page` |
|
||||
|
||||
## codersdk.ExternalAuth
|
||||
|
|
|
@ -62,11 +62,6 @@ func TestTemplateCreate(t *testing.T) {
|
|||
t.Run("WorkspaceCleanup", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dv := coderdtest.DeploymentValues(t)
|
||||
dv.Experiments = []string{
|
||||
string(codersdk.ExperimentWorkspaceActions),
|
||||
}
|
||||
|
||||
client, user := coderdenttest.New(t, &coderdenttest.Options{
|
||||
LicenseOptions: &coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
|
@ -74,7 +69,6 @@ func TestTemplateCreate(t *testing.T) {
|
|||
},
|
||||
},
|
||||
Options: &coderdtest.Options{
|
||||
DeploymentValues: dv,
|
||||
IncludeProvisionerDaemon: true,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -89,11 +89,6 @@ func TestTemplateEdit(t *testing.T) {
|
|||
t.Run("WorkspaceCleanup", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dv := coderdtest.DeploymentValues(t)
|
||||
dv.Experiments = []string{
|
||||
string(codersdk.ExperimentWorkspaceActions),
|
||||
}
|
||||
|
||||
ownerClient, owner := coderdenttest.New(t, &coderdenttest.Options{
|
||||
LicenseOptions: &coderdenttest.LicenseOptions{
|
||||
Features: license.Features{
|
||||
|
@ -101,7 +96,6 @@ func TestTemplateEdit(t *testing.T) {
|
|||
},
|
||||
},
|
||||
Options: &coderdtest.Options{
|
||||
DeploymentValues: dv,
|
||||
IncludeProvisionerDaemon: true,
|
||||
},
|
||||
})
|
||||
|
|
|
@ -1813,11 +1813,8 @@ export const Entitlements: Entitlement[] = [
|
|||
];
|
||||
|
||||
// From codersdk/deployment.go
|
||||
export type Experiment = "deployment_health_page" | "workspace_actions";
|
||||
export const Experiments: Experiment[] = [
|
||||
"deployment_health_page",
|
||||
"workspace_actions",
|
||||
];
|
||||
export type Experiment = "deployment_health_page";
|
||||
export const Experiments: Experiment[] = ["deployment_health_page"];
|
||||
|
||||
// From codersdk/deployment.go
|
||||
export type FeatureName =
|
||||
|
|
|
@ -113,11 +113,6 @@ export const useDashboard = (): DashboardProviderValue => {
|
|||
};
|
||||
|
||||
export const useIsWorkspaceActionsEnabled = (): boolean => {
|
||||
const { entitlements, experiments } = useDashboard();
|
||||
const allowAdvancedScheduling =
|
||||
entitlements.features["advanced_template_scheduling"].enabled;
|
||||
// This check can be removed when https://github.com/coder/coder/milestone/19
|
||||
// is merged up
|
||||
const allowWorkspaceActions = experiments.includes("workspace_actions");
|
||||
return allowWorkspaceActions && allowAdvancedScheduling;
|
||||
const { entitlements } = useDashboard();
|
||||
return entitlements.features["advanced_template_scheduling"].enabled;
|
||||
};
|
||||
|
|
|
@ -10,20 +10,13 @@ interface DormantDeletionTextProps {
|
|||
export const DormantDeletionText: FC<DormantDeletionTextProps> = ({
|
||||
workspace,
|
||||
}) => {
|
||||
const { entitlements, experiments } = useDashboard();
|
||||
const { entitlements } = useDashboard();
|
||||
const allowAdvancedScheduling =
|
||||
entitlements.features["advanced_template_scheduling"].enabled;
|
||||
// This check can be removed when https://github.com/coder/coder/milestone/19
|
||||
// is merged up
|
||||
const allowWorkspaceActions = experiments.includes("workspace_actions");
|
||||
|
||||
if (
|
||||
!displayDormantDeletion(
|
||||
workspace,
|
||||
allowAdvancedScheduling,
|
||||
allowWorkspaceActions,
|
||||
)
|
||||
) {
|
||||
if (!displayDormantDeletion(workspace, allowAdvancedScheduling)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ export interface TemplateScheduleForm {
|
|||
isSubmitting: boolean;
|
||||
error?: unknown;
|
||||
allowAdvancedScheduling: boolean;
|
||||
allowWorkspaceActions: boolean;
|
||||
// Helpful to show field errors on Storybook
|
||||
initialTouched?: FormikTouched<UpdateTemplateMeta>;
|
||||
}
|
||||
|
@ -65,7 +64,6 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
|
|||
onCancel,
|
||||
error,
|
||||
allowAdvancedScheduling,
|
||||
allowWorkspaceActions,
|
||||
isSubmitting,
|
||||
initialTouched,
|
||||
}) => {
|
||||
|
@ -562,7 +560,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
|
|||
</Stack>
|
||||
</Stack>
|
||||
</FormSection>
|
||||
{allowAdvancedScheduling && allowWorkspaceActions && (
|
||||
{allowAdvancedScheduling && (
|
||||
<>
|
||||
<FormSection
|
||||
title="Failure Cleanup"
|
||||
|
|
|
@ -139,9 +139,6 @@ describe("TemplateSchedulePage", () => {
|
|||
jest
|
||||
.spyOn(API, "getEntitlements")
|
||||
.mockResolvedValue(MockEntitlementsWithScheduling);
|
||||
|
||||
// remove when https://github.com/coder/coder/milestone/19 is completed.
|
||||
jest.spyOn(API, "getExperiments").mockResolvedValue(["workspace_actions"]);
|
||||
});
|
||||
|
||||
it("Calls the API when user fills in and submits a form", async () => {
|
||||
|
|
|
@ -18,12 +18,9 @@ const TemplateSchedulePage: FC = () => {
|
|||
const queryClient = useQueryClient();
|
||||
const orgId = useOrganizationId();
|
||||
const { template } = useTemplateSettings();
|
||||
const { entitlements, experiments } = useDashboard();
|
||||
const { entitlements } = useDashboard();
|
||||
const allowAdvancedScheduling =
|
||||
entitlements.features["advanced_template_scheduling"].enabled;
|
||||
// This check can be removed when https://github.com/coder/coder/milestone/19
|
||||
// is merged up
|
||||
const allowWorkspaceActions = experiments.includes("workspace_actions");
|
||||
const { clearLocal } = useLocalStorage();
|
||||
|
||||
const {
|
||||
|
@ -52,7 +49,6 @@ const TemplateSchedulePage: FC = () => {
|
|||
</Helmet>
|
||||
<TemplateSchedulePageView
|
||||
allowAdvancedScheduling={allowAdvancedScheduling}
|
||||
allowWorkspaceActions={allowWorkspaceActions}
|
||||
isSubmitting={isSubmitting}
|
||||
template={template}
|
||||
submitError={submitError}
|
||||
|
|
|
@ -31,7 +31,6 @@ type Story = StoryObj<typeof TemplateSchedulePageView>;
|
|||
|
||||
const defaultArgs = {
|
||||
allowAdvancedScheduling: true,
|
||||
allowWorkspaceActions: true,
|
||||
template: MockTemplate,
|
||||
onSubmit: action("onSubmit"),
|
||||
onCancel: action("cancel"),
|
||||
|
|
|
@ -13,7 +13,6 @@ export interface TemplateSchedulePageViewProps {
|
|||
typeof TemplateScheduleForm
|
||||
>["initialTouched"];
|
||||
allowAdvancedScheduling: boolean;
|
||||
allowWorkspaceActions: boolean;
|
||||
}
|
||||
|
||||
export const TemplateSchedulePageView: FC<TemplateSchedulePageViewProps> = ({
|
||||
|
@ -22,7 +21,6 @@ export const TemplateSchedulePageView: FC<TemplateSchedulePageViewProps> = ({
|
|||
onSubmit,
|
||||
isSubmitting,
|
||||
allowAdvancedScheduling,
|
||||
allowWorkspaceActions,
|
||||
submitError,
|
||||
initialTouched,
|
||||
}) => {
|
||||
|
@ -34,7 +32,6 @@ export const TemplateSchedulePageView: FC<TemplateSchedulePageViewProps> = ({
|
|||
|
||||
<TemplateScheduleForm
|
||||
allowAdvancedScheduling={allowAdvancedScheduling}
|
||||
allowWorkspaceActions={allowWorkspaceActions}
|
||||
initialTouched={initialTouched}
|
||||
isSubmitting={isSubmitting}
|
||||
template={template}
|
||||
|
|
|
@ -24,7 +24,6 @@ const meta: Meta<typeof WorkspaceTopbar> = {
|
|||
parameters: {
|
||||
layout: "fullscreen",
|
||||
features: ["advanced_template_scheduling"],
|
||||
experiments: ["workspace_actions"],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -88,16 +88,14 @@ export const WorkspaceTopbar = (props: WorkspaceProps) => {
|
|||
});
|
||||
|
||||
// Dormant
|
||||
const { entitlements, experiments } = useDashboard();
|
||||
const { entitlements } = useDashboard();
|
||||
const allowAdvancedScheduling =
|
||||
entitlements.features["advanced_template_scheduling"].enabled;
|
||||
// This check can be removed when https://github.com/coder/coder/milestone/19
|
||||
// is merged up
|
||||
const allowWorkspaceActions = experiments.includes("workspace_actions");
|
||||
const shouldDisplayDormantData = displayDormantDeletion(
|
||||
workspace,
|
||||
allowAdvancedScheduling,
|
||||
allowWorkspaceActions,
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -2047,7 +2047,9 @@ export const MockEntitlementsWithUserLimit: TypesGen.Entitlements = {
|
|||
}),
|
||||
};
|
||||
|
||||
export const MockExperiments: TypesGen.Experiment[] = ["workspace_actions"];
|
||||
export const MockExperiments: TypesGen.Experiment[] = [
|
||||
"deployment_health_page",
|
||||
];
|
||||
|
||||
export const MockAuditLog: TypesGen.AuditLog = {
|
||||
id: "fbd2116a-8961-4954-87ae-e4575bd29ce0",
|
||||
|
|
|
@ -4,53 +4,39 @@ import { displayDormantDeletion } from "./dormant";
|
|||
|
||||
describe("displayDormantDeletion", () => {
|
||||
const today = new Date();
|
||||
it.each<[string, boolean, boolean, boolean]>([
|
||||
it.each<[string, boolean, boolean]>([
|
||||
[
|
||||
new Date(new Date().setDate(today.getDate() + 15)).toISOString(),
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
], // today + 15 days out
|
||||
[
|
||||
new Date(new Date().setDate(today.getDate() + 14)).toISOString(),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], // today + 14
|
||||
[
|
||||
new Date(new Date().setDate(today.getDate() + 13)).toISOString(),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], // today + 13
|
||||
[
|
||||
new Date(new Date().setDate(today.getDate() + 1)).toISOString(),
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
], // today + 1
|
||||
[new Date().toISOString(), true, true, true], // today + 0
|
||||
[new Date().toISOString(), false, true, false], // Advanced Scheduling off
|
||||
[new Date().toISOString(), true, false, false], // Workspace Actions off
|
||||
[new Date().toISOString(), true, true], // today + 0
|
||||
[new Date().toISOString(), false, false], // Advanced Scheduling off
|
||||
])(
|
||||
`deleting_at=%p, allowAdvancedScheduling=%p, AllowWorkspaceActions=%p, shouldDisplay=%p`,
|
||||
(
|
||||
deleting_at,
|
||||
allowAdvancedScheduling,
|
||||
allowWorkspaceActions,
|
||||
shouldDisplay,
|
||||
) => {
|
||||
`deleting_at=%p, allowAdvancedScheduling=%p, shouldDisplay=%p`,
|
||||
(deleting_at, allowAdvancedScheduling, shouldDisplay) => {
|
||||
const workspace: TypesGen.Workspace = {
|
||||
...Mocks.MockWorkspace,
|
||||
deleting_at,
|
||||
};
|
||||
expect(
|
||||
displayDormantDeletion(
|
||||
workspace,
|
||||
allowAdvancedScheduling,
|
||||
allowWorkspaceActions,
|
||||
),
|
||||
).toBe(shouldDisplay);
|
||||
expect(displayDormantDeletion(workspace, allowAdvancedScheduling)).toBe(
|
||||
shouldDisplay,
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
|
|
@ -14,14 +14,9 @@ const IMPENDING_DELETION_DISPLAY_THRESHOLD = 14; // 14 days
|
|||
export const displayDormantDeletion = (
|
||||
workspace: Workspace,
|
||||
allowAdvancedScheduling: boolean,
|
||||
allowWorkspaceActions: boolean,
|
||||
) => {
|
||||
const today = new Date();
|
||||
if (
|
||||
!workspace.deleting_at ||
|
||||
!allowAdvancedScheduling ||
|
||||
!allowWorkspaceActions
|
||||
) {
|
||||
if (!workspace.deleting_at || !allowAdvancedScheduling) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
|
|
Loading…
Reference in New Issue