Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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 deletion cli/testdata/coder_list_--output_json.golden
Original file line number Diff line number Diff 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
}
]
3 changes: 3 additions & 0 deletions coderd/apidoc/docs.go

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

3 changes: 3 additions & 0 deletions coderd/apidoc/swagger.json

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

7 changes: 7 additions & 0 deletions coderd/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -2231,6 +2231,12 @@ func convertWorkspace(
if latestAppStatus.ID == uuid.Nil {
appStatus = nil
}

isPrebuild := false
Copy link
Contributor

@SasSwart SasSwart Jul 14, 2025

Choose a reason for hiding this comment

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

A few nonblocking thoughts:

  • Consider isPrebuilt instead of isPrebuilt. I know is a small and subtle naming change but a Prebuild is not the same thing as a prebuilt workspace.
  • Also perhaps consider a comment or something to explain that this is for unclaimed prebuilt workspaces only. A claimed workspace can still be called prebuilt and the change in this PR does not affect those.
  • should we have a prebuilds.IsUnclaimedPrebuiltWorkspace(...) function to encapsulate and abstract this logic?

Copy link
Contributor Author

@ssncferreira ssncferreira Jul 14, 2025

Choose a reason for hiding this comment

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

Consider isPrebuilt instead of isPrebuilt. I know is a small and subtle naming change but a Prebuild is not the same thing as a prebuilt workspace.

The way I have been using these terms, is Prebuild = Prebuilt Workspace, but maybe I have been using it wrong. What is the difference between Prebuild and Prebuilt Workspace?

Also perhaps consider a comment or something to explain that this is for unclaimed prebuilt workspaces only. A claimed workspace can still be called prebuilt and the change in this PR does not affect those.

Added a comment in 0bde254, let me know if it works.

should we have a prebuilds.IsUnclaimedPrebuiltWorkspace(...) function to encapsulate and abstract this logic?

Yes, we can do that and reuse it in other parts of the code that already have this logic. I can address it in a separate PR. Edit: actually, there is a better solution that I completely forgot 🤦‍♀️ which is to use workspace.IsPrebuild(). This encapsulates that logic on workspace and improves readability: 0120c5b
I will create a follow up PR to add some tests to test this parameter.

if workspace.OwnerID == database.PrebuildsSystemUserID {
isPrebuild = true
}

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

Expand Down
1 change: 1 addition & 0 deletions codersdk/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type Workspace struct {
AllowRenames bool `json:"allow_renames"`
Favorite bool `json:"favorite"`
NextStartAt *time.Time `json:"next_start_at" format:"date-time"`
IsPrebuild bool `json:"is_prebuild"`
}

func (w Workspace) FullName() string {
Expand Down
3 changes: 3 additions & 0 deletions docs/reference/api/schemas.md

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

6 changes: 6 additions & 0 deletions docs/reference/api/workspaces.md

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

1 change: 1 addition & 0 deletions site/src/api/typesGenerated.ts

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

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.

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
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 73f5476

Original file line number Diff line number Diff 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 Down Expand 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
1 change: 1 addition & 0 deletions site/src/testHelpers/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,7 @@ export const MockWorkspace: TypesGen.Workspace = {
deleting_at: null,
dormant_at: null,
next_start_at: null,
is_prebuild: false,
};

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