Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

fix(site): exclude workspace schedule settings for prebuilt workspaces#18826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
11 commits
Select commitHold shift + click to select a range
95ca5f7
fix(site): exclude workspace schedule settings for prebuilt workspaces
ssncferreiraJul 10, 2025
207c80f
feat: add is_prebuild flag to workspace API response
ssncferreiraJul 10, 2025
450b3e1
fix: fmt
ssncferreiraJul 10, 2025
0bde254
chore: add comment to IsPrebuild parameter on codersdk.Workspaces
ssncferreiraJul 14, 2025
73f5476
chore: add story to WorkspaceSchedulePage
ssncferreiraJul 14, 2025
f306854
Merge remote-tracking branch 'origin/main' into ssncferreira/exclude-…
ssncferreiraJul 14, 2025
d5e45bb
fix: run make gen
ssncferreiraJul 14, 2025
0120c5b
chore: use workspace.IsPrebuild() on convertWorkspace
ssncferreiraJul 14, 2025
ad475cf
simplify story
BrunoQuaresmaJul 14, 2025
02c0ff5
fix: run make fmt
ssncferreiraJul 15, 2025
1260e49
Merge remote-tracking branch 'origin/main' into ssncferreira/exclude-…
ssncferreiraJul 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletioncli/testdata/coder_list_--output_json.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -86,6 +86,7 @@
"automatic_updates": "never",
"allow_renames": false,
"favorite": false,
"next_start_at": "====[timestamp]====="
"next_start_at": "====[timestamp]=====",
"is_prebuild": false
}
]
4 changes: 4 additions & 0 deletionscoderd/apidoc/docs.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

4 changes: 4 additions & 0 deletionscoderd/apidoc/swagger.json
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

2 changes: 2 additions & 0 deletionscoderd/workspaces.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2231,6 +2231,7 @@ func convertWorkspace(
if latestAppStatus.ID == uuid.Nil {
appStatus = nil
}

return codersdk.Workspace{
ID: workspace.ID,
CreatedAt: workspace.CreatedAt,
Expand DownExpand Up@@ -2265,6 +2266,7 @@ func convertWorkspace(
AllowRenames: allowRenames,
Favorite: requesterFavorite,
NextStartAt: nextStartAt,
IsPrebuild: workspace.IsPrebuild(),
}, nil
}

Expand Down
6 changes: 6 additions & 0 deletionscodersdk/workspaces.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -66,6 +66,12 @@ type Workspace struct {
AllowRenames bool `json:"allow_renames"`
Favorite bool `json:"favorite"`
NextStartAt *time.Time `json:"next_start_at" format:"date-time"`
// IsPrebuild indicates whether the workspace is a prebuilt workspace.
// Prebuilt workspaces are owned by the prebuilds system user and have specific behavior,
// such as being managed differently from regular workspaces.
// Once a prebuilt workspace is claimed by a user, it transitions to a regular workspace,
// and IsPrebuild returns false.
IsPrebuild bool `json:"is_prebuild"`
}

func (w Workspace) FullName() string {
Expand Down
67 changes: 35 additions & 32 deletionsdocs/reference/api/schemas.md
View file
Open in desktop

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletionsdocs/reference/api/workspaces.md
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

1 change: 1 addition & 0 deletionssite/src/api/typesGenerated.ts
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
import type { Meta, StoryObj } from "@storybook/react";
import { getAuthorizationKey } from "api/queries/authCheck";
import { templateByNameKey } from "api/queries/templates";
import { workspaceByOwnerAndNameKey } from "api/queries/workspaces";
import type { Workspace } from "api/typesGenerated";
import {
reactRouterNestedAncestors,
reactRouterParameters,
} from "storybook-addon-remix-react-router";
import {
MockPrebuiltWorkspace,
MockTemplate,
MockUserOwner,
MockWorkspace,
} from "testHelpers/entities";
import { withAuthProvider, withDashboardProvider } from "testHelpers/storybook";
import { WorkspaceSettingsLayout } from "../WorkspaceSettingsLayout";
import WorkspaceSchedulePage from "./WorkspaceSchedulePage";

const meta = {
title: "pages/WorkspaceSchedulePage",
component: WorkspaceSchedulePage,
decorators: [withAuthProvider, withDashboardProvider],
parameters: {
layout: "fullscreen",
user: MockUserOwner,
},
} satisfies Meta<typeof WorkspaceSchedulePage>;

export default meta;
type Story = StoryObj<typeof WorkspaceSchedulePage>;

export const RegularWorkspace: Story = {
parameters: {
reactRouter: workspaceRouterParameters(MockWorkspace),
queries: workspaceQueries(MockWorkspace),
},
};

export const PrebuiltWorkspace: Story = {
parameters: {
reactRouter: workspaceRouterParameters(MockPrebuiltWorkspace),
queries: workspaceQueries(MockPrebuiltWorkspace),
},
};

function workspaceRouterParameters(workspace: Workspace) {
return reactRouterParameters({
location: {
pathParams: {
username: `@${workspace.owner_name}`,
workspace: workspace.name,
},
},
routing: reactRouterNestedAncestors(
{
path: "/:username/:workspace/settings/schedule",
},
<WorkspaceSettingsLayout />,
),
});
}

function workspaceQueries(workspace: Workspace) {
return [
{
key: workspaceByOwnerAndNameKey(workspace.owner_name, workspace.name),
data: workspace,
},
{
key: getAuthorizationKey({
checks: {
updateWorkspace: {
object: {
resource_type: "workspace",
resource_id: MockWorkspace.id,
owner_id: MockWorkspace.owner_id,
},
action: "update",
},
},
}),
data: { updateWorkspace: true },
},
{
key: templateByNameKey(
MockWorkspace.organization_id,
MockWorkspace.template_name,
),
data: MockTemplate,
},
];
}
View file
Open in desktop
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I'd suggest adding a story here to showcase the new behaviour.

BrunoQuaresma reacted with thumbs up emoji
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Good catch!

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Addressed in73f5476

Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,7 @@ import { Alert } from "components/Alert/Alert";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
import { Link } from "components/Link/Link";
import { Loader } from "components/Loader/Loader";
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
import dayjs from "dayjs";
Expand All@@ -20,6 +21,7 @@ import { type FC, useState } from "react";
import { Helmet } from "react-helmet-async";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { useNavigate, useParams } from "react-router-dom";
import { docs } from "utils/docs";
import { pageTitle } from "utils/page";
import { WorkspaceScheduleForm } from "./WorkspaceScheduleForm";
import {
Expand All@@ -32,7 +34,7 @@ const permissionsToCheck = (workspace: TypesGen.Workspace) =>
updateWorkspace: {
object: {
resource_type: "workspace",
resourceId: workspace.id,
resource_id: workspace.id,
owner_id: workspace.owner_id,
},
action: "update",
Expand DownExpand Up@@ -94,42 +96,62 @@ const WorkspaceSchedulePage: FC = () => {
</Alert>
)}

{template && (
<WorkspaceScheduleForm
template={template}
error={submitScheduleMutation.error}
initialValues={{
...getAutostart(workspace),
...getAutostop(workspace),
}}
isLoading={submitScheduleMutation.isPending}
defaultTTL={dayjs.duration(template.default_ttl_ms, "ms").asHours()}
onCancel={() => {
navigate(`/@${username}/${workspaceName}`);
}}
onSubmit={async (values) => {
const data = {
workspace,
autostart: formValuesToAutostartRequest(values),
ttl: formValuesToTTLRequest(values),
autostartChanged: scheduleChanged(
getAutostart(workspace),
values,
),
autostopChanged: scheduleChanged(getAutostop(workspace), values),
};

await submitScheduleMutation.mutateAsync(data);

if (
data.autostopChanged &&
getAutostop(workspace).autostopEnabled
) {
setIsConfirmingApply(true);
}
}}
/>
)}
{template &&
(workspace.is_prebuild ? (
<Alert severity="info">
Prebuilt workspaces ignore workspace-level scheduling until they are
claimed. For prebuilt workspace specific scheduling refer to the{" "}
<Link
title="Prebuilt Workspaces Scheduling"
href={docs(
"/admin/templates/extending-templates/prebuilt-workspaces#scheduling",
)}
target="_blank"
rel="noreferrer"
>
Prebuilt Workspaces Scheduling
</Link>
documentation page.
</Alert>
) : (
<WorkspaceScheduleForm
template={template}
error={submitScheduleMutation.error}
initialValues={{
...getAutostart(workspace),
...getAutostop(workspace),
}}
isLoading={submitScheduleMutation.isPending}
defaultTTL={dayjs.duration(template.default_ttl_ms, "ms").asHours()}
onCancel={() => {
navigate(`/@${username}/${workspaceName}`);
}}
onSubmit={async (values) => {
const data = {
workspace,
autostart: formValuesToAutostartRequest(values),
ttl: formValuesToTTLRequest(values),
autostartChanged: scheduleChanged(
getAutostart(workspace),
values,
),
autostopChanged: scheduleChanged(
getAutostop(workspace),
values,
),
};

await submitScheduleMutation.mutateAsync(data);

if (
data.autostopChanged &&
getAutostop(workspace).autostopEnabled
) {
setIsConfirmingApply(true);
}
}}
/>
))}

<ConfirmDialog
open={isConfirmingApply}
Expand Down
8 changes: 8 additions & 0 deletionssite/src/testHelpers/entities.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1411,6 +1411,14 @@ export const MockWorkspace: TypesGen.Workspace = {
deleting_at: null,
dormant_at: null,
next_start_at: null,
is_prebuild: false,
};

export const MockPrebuiltWorkspace = {
...MockWorkspace,
owner_name: "prebuilds",
name: "prebuilt-workspace",
is_prebuild: true,
};

export const MockFavoriteWorkspace: TypesGen.Workspace = {
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp