fix: force task to be created with latest version (#19923)

Fixes https://github.com/coder/coder/issues/19744
This commit is contained in:
Bruno Quaresma
2025-09-24 13:23:31 -03:00
committed by GitHub
parent acc0890dce
commit 5ff503b8fc
2 changed files with 40 additions and 4 deletions
+23 -4
View File
@@ -186,11 +186,12 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
const createTaskMutation = useMutation({
mutationFn: async ({ prompt }: CreateTaskMutationFnProps) =>
API.experimental.createTask(user.id, {
createTaskWithLatestTemplateVersion(
prompt,
template_version_id: selectedTemplate.active_version_id,
template_version_preset_id: selectedPresetId,
}),
user.id,
selectedTemplate.id,
selectedPresetId,
),
onSuccess: async (task) => {
await queryClient.invalidateQueries({ queryKey: ["tasks"] });
onSuccess(task);
@@ -427,3 +428,21 @@ function sortByDefault(a: Preset, b: Preset) {
// Otherwise, sort alphabetically by name
return a.Name.localeCompare(b.Name);
}
// TODO: Enforce task creation to always use the latest active template version.
// During task creation, the active version might change between template load
// and user action. Since handling this in the FE cannot guarantee correctness,
// we should move the logic to the BE after the experimental phase.
async function createTaskWithLatestTemplateVersion(
prompt: string,
userId: string,
templateId: string,
presetId: string | undefined,
): Promise<Task> {
const template = await API.getTemplate(templateId);
return API.experimental.createTask(userId, {
prompt,
template_version_id: template.active_version_id,
template_version_preset_id: presetId,
});
}
@@ -245,7 +245,12 @@ export const CreateTaskSuccessfully: Story = {
}),
},
beforeEach: () => {
const activeVersionId = `${MockTemplate.active_version_id}-latest`;
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API, "getTemplate").mockResolvedValue({
...MockTemplate,
active_version_id: activeVersionId,
});
spyOn(API.experimental, "getTasks")
.mockResolvedValueOnce(MockTasks)
.mockResolvedValue([MockNewTaskData, ...MockTasks]);
@@ -262,6 +267,17 @@ export const CreateTaskSuccessfully: Story = {
await userEvent.click(submitButton);
});
await step("Uses latest template version", () => {
expect(API.experimental.createTask).toHaveBeenCalledWith(
MockUserOwner.id,
{
prompt: MockNewTaskData.prompt,
template_version_id: `${MockTemplate.active_version_id}-latest`,
template_version_preset_id: undefined,
},
);
});
await step("Displays success message", async () => {
const body = within(canvasElement.ownerDocument.body);
const successMessage = await body.findByText(/task created/i);
@@ -281,6 +297,7 @@ export const CreateTaskError: Story = {
decorators: [withGlobalSnackbar],
beforeEach: () => {
spyOn(API, "getTemplates").mockResolvedValue([MockTemplate]);
spyOn(API, "getTemplate").mockResolvedValue(MockTemplate);
spyOn(API.experimental, "getTasks").mockResolvedValue(MockTasks);
spyOn(API.experimental, "createTask").mockRejectedValue(
mockApiError({