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

refactor: create tasks in coderd instead of frontend#19280

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
DanielleMaywood merged 15 commits intomainfromdanielle/tasks/move-to-be
Aug 12, 2025

Conversation

DanielleMaywood
Copy link
Contributor

Instead of creating tasks with a specialised call toCreateWorkspace on the frontend, we instead lift this to the backend and allow the frontend to simply callCreateAITask.

Instead of creating tasks with a specialised call to `CreateWorkspace`on the frontend, we instead lift this to the backend and allow thefrontend to simply call `CreateAITask`.
@DanielleMaywoodDanielleMaywood changed the titlerefactor: lift task creation to coderdrefactor: create tasks in coderd instead of frontendAug 11, 2025
@DanielleMaywood
Copy link
ContributorAuthor

@coderabbitai review

coderabbitai[bot] reacted with eyes emoji

@coderabbitaicoderabbitai
Copy link

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Comment on lines 95 to 108
hasAIPrompt,err:=api.Database.GetTemplateVersionHasAIPrompt(ctx,req.TemplateVersionID)
iferr!=nil {
httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
Message:"Internal error fetching if template version has ai prompt.",
Detail:err.Error(),
})
return
}
if!hasAIPrompt {
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
Message:`Template does not have required parameter "AI Prompt"`,
})
return
}
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

As we're moving creation of tasks to the backend, I think it makes sense to validate the given template version ID actually corresponds to a task.

@coderabbitaicoderabbitai
Copy link

📝 Walkthrough

Walkthrough

Introduces an experimental POST /api/experimental/aitasks endpoint to create AI tasks by embedding a prompt into a workspace creation request. Adds SDK and frontend support, database query and authorization checks for AI-prompt capability on template versions, metrics and mocks, routing, and tests.

Changes

Cohort / File(s)Summary
Experimental AI Tasks API
coderd/aitasks.go,coderd/coderd.go
Adds aiTasksCreate handler and routes POST /api/experimental/aitasks. Validates API key, fetches user, checks template version supports AI prompt, constructs workspace creation payload with prompt, audits, and invokes createWorkspace.
SDK and Web API Bindings
codersdk/aitasks.go,site/src/api/api.ts,site/src/api/typesGenerated.ts
Adds CreateAITasksRequest model and ExperimentalClient.AITasksCreate. Frontend ExperimentalApiMethods.createAITask posts to new endpoint. Generates TS interface for request.
UI Tasks Page Integration
site/src/pages/TasksPage/TasksPage.tsx
Updates createTask to use experimental createAITask; removes userId parameter and switches payload to include prompt directly.
DB Query and SQL
coderd/database/queries/templateversions.sql,coderd/database/queries.sql.go,coderd/database/querier.go
Introduces GetTemplateVersionHasAIPrompt SQL and method on sqlQuerier to check has_ai_task flag for a template version.
DB Authorization
coderd/database/dbauthz/dbauthz.go
Adds dbauthz.GetTemplateVersionHasAIPrompt with authz via GetTemplateVersionByID; refines authz for GetTemplateVersionByTemplateIDAndName and GetTemplateVersionParameters.
DB Metrics Wrapper
coderd/database/dbmetrics/querymetrics.go
Wraps GetTemplateVersionHasAIPrompt with latency metrics.
DB Mocks
coderd/database/dbmock/dbmock.go
Adds gomock methods for GetTemplateVersionHasAIPrompt.
Tests
coderd/aitasks_test.go,coderd/database/dbauthz/dbauthz_test.go
Adds tests for AI task creation success/failure and dbauthz coverage for AI prompt check and template-level authorization.

Sequence Diagram(s)

sequenceDiagram  participant Web as Frontend (TasksPage)  participant SDK as SDK ExperimentalClient  participant API as Server /api/experimental/aitasks  participant MW as API Key Middleware  participant DB as DB + dbauthz  participant AUD as Audit  participant WS as Workspace Creator  Web->>SDK: AITasksCreate(request)  SDK->>API: POST /api/experimental/aitasks  API->>MW: Authenticate API key  MW-->>API: User context  API->>DB: Get user by API key  API->>DB: GetTemplateVersionHasAIPrompt(tvID)  DB-->>API: bool  API->>AUD: audit.InitRequest(WorkspaceCreate)  API->>WS: createWorkspace(payload with prompt)  WS-->>API: Workspace  API->>AUD: commit  API-->>SDK: 201 Workspace  SDK-->>Web: Workspace
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Suggested reviewers

  • johnstcn
  • BrunoQuaresma
  • aslilac
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branchdanielle/tasks/move-to-be

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat withCodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag@coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag@coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on oursupport page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings togenerate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add@coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add@coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add@coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit ourDocumentation for detailed information on how to use CodeRabbit.
  • Join ourDiscord Community to get help, request features, and share feedback.
  • Follow us onX/Twitter for updates and announcements.

Copy link

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (9)
coderd/database/queries/templateversions.sql (1)

238-238:Rename to align with column and existing query names ("AITask" vs "AIPrompt").

The column is has_ai_task and related queries use AITask (e.g., UpdateTemplateVersionAITaskByJobID). Rename this query to avoid mixed terminology.

Apply within this file, then regenerate sqlc:

- -- name: GetTemplateVersionHasAIPrompt :one+ -- name: GetTemplateVersionHasAITask :one
site/src/api/api.ts (1)

2669-2678:Allow cancellation (AbortSignal) for better UX on long/aborted submissions.

Add optional AbortSignal support so callers can cancel in-flight requests (e.g., route changes).

-  createAITask = async (-    req: TypesGen.CreateAITasksRequest,-  ): Promise<TypesGen.Workspace> => {-    const response = await this.axios.post<TypesGen.Workspace>(-      "/api/experimental/aitasks",-      req,-    );--    return response.data;-  };+  createAITask = async (+    req: TypesGen.CreateAITasksRequest,+    signal?: AbortSignal,+  ): Promise<TypesGen.Workspace> => {+    const response = await this.axios.post<TypesGen.Workspace>(+      "/api/experimental/aitasks",+      req,+      { signal },+    );+    return response.data;+  };

Nit: consider naming the method createAITasks to mirror the plural route/type. Only do this if you can update call sites in the same PR to avoid breakage.

coderd/database/querier.go (1)

358-358:Naming consistency: prefer “HasAITask” to match schema and existing queries.

Interface name stems from SQL. If you adopt the suggested SQL rename (GetTemplateVersionHasAITask), regenerate sqlc so this becomes:

  • GetTemplateVersionHasAITask(ctx context.Context, id uuid.UUID) (bool, error)

Do not hand-edit this file; re-generate from the .sql change.

coderd/database/dbmetrics/querymetrics.go (1)

1541-1546:Align wrapper and metric label with “AITask” naming if SQL is renamed.

If you rename the SQL to GetTemplateVersionHasAITask, update this wrapper and label accordingly.

-func (m queryMetricsStore) GetTemplateVersionHasAIPrompt(ctx context.Context, id uuid.UUID) (bool, error) {+func (m queryMetricsStore) GetTemplateVersionHasAITask(ctx context.Context, id uuid.UUID) (bool, error) {   start := time.Now()-  r0, r1 := m.s.GetTemplateVersionHasAIPrompt(ctx, id)-  m.queryLatencies.WithLabelValues("GetTemplateVersionHasAIPrompt").Observe(time.Since(start).Seconds())+  r0, r1 := m.s.GetTemplateVersionHasAITask(ctx, id)+  m.queryLatencies.WithLabelValues("GetTemplateVersionHasAITask").Observe(time.Since(start).Seconds())   return r0, r1 }
coderd/database/dbauthz/dbauthz_test.go (1)

1446-1459:RBAC assertion for TemplateVersion AI-prompt check looks correct

This follows the established pattern where TemplateVersion reads authorize on the parent Template via RBACObject. No issues.

Optional:

  • Add a brief comment clarifying the test intent (TemplateVersion read → Template read) to improve readability.
  • Consider a negative-path variant (e.g., WithNotAuthorized) similar to other tests where applicable.
coderd/database/queries.sql.go (1)

12873-12887:Nit: align naming with underlying column (has_ai_task) to avoid confusion

The method/SQL name uses “AIPrompt” while the column is has_ai_task. Since this file is generated, consider renaming the query in the source SQL to keep terminology consistent (e.g., “GetTemplateVersionHasAITask”). sqlc will then regenerate matching Go.

Example in coderd/database/queries/templateversions.sql:

-- name: GetTemplateVersionHasAITask :oneSELECT EXISTS (SELECT1FROM template_versionsWHERE id= $1AND has_ai_task);
coderd/aitasks.go (1)

95-102:Clarify error message wording (nit)

Small copy nit: “whether template version has AI Prompt” reads clearer than “if template version has ai prompt.”

-           Message: "Internal error fetching if template version has ai prompt.",+           Message: "Internal error checking whether the template version has AI Prompt.",
codersdk/aitasks.go (1)

56-64:Drop trailing slash in POST path for consistency

Standardize the path to avoid relying on router slash normalization.

-   res, err := c.Request(ctx, http.MethodPost, "/api/experimental/aitasks/", request)+   res, err := c.Request(ctx, http.MethodPost, "/api/experimental/aitasks", request)
site/src/pages/TasksPage/TasksPage.tsx (1)

742-747:Use conditional property for preset_id (minor nit)

Avoid sending undefined fields by conditionally including template_version_preset_id. Keeps payload minimal and avoids any strict decoder issues.

-    const workspace = await API.experimental.createAITask({-      name: `task-${generateWorkspaceName()}`,-      template_version_id: templateVersionId,-      template_version_preset_id: preset_id || undefined,-      prompt,-    });+    const req = {+      name: `task-${generateWorkspaceName()}`,+      template_version_id: templateVersionId,+      prompt,+      ...(preset_id ? { template_version_preset_id: preset_id } : {}),+    };+    const workspace = await API.experimental.createAITask(req);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and betweendadeab8 and0ad6ce3.

📒 Files selected for processing (14)
  • coderd/aitasks.go (2 hunks)
  • coderd/aitasks_test.go (2 hunks)
  • coderd/coderd.go (1 hunks)
  • coderd/database/dbauthz/dbauthz.go (1 hunks)
  • coderd/database/dbauthz/dbauthz_test.go (1 hunks)
  • coderd/database/dbmetrics/querymetrics.go (1 hunks)
  • coderd/database/dbmock/dbmock.go (1 hunks)
  • coderd/database/querier.go (1 hunks)
  • coderd/database/queries.sql.go (1 hunks)
  • coderd/database/queries/templateversions.sql (1 hunks)
  • codersdk/aitasks.go (1 hunks)
  • site/src/api/api.ts (1 hunks)
  • site/src/api/typesGenerated.ts (1 hunks)
  • site/src/pages/TasksPage/TasksPage.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-07-21T14:32:43.064Z
Learnt from: CRPR: coder/coder#0File: .cursorrules:0-0Timestamp: 2025-07-21T14:32:43.064ZLearning: Applies to coderd/coderd.go : The REST API is defined in `coderd/coderd.go` and uses Chi for HTTP routing.

Applied to files:

  • coderd/coderd.go
  • coderd/aitasks_test.go
📚 Learning: 2025-07-21T14:32:43.064Z
Learnt from: CRPR: coder/coder#0File: .cursorrules:0-0Timestamp: 2025-07-21T14:32:43.064ZLearning: Applies to coderd/coderdtest/**/* : The `coderdtest` package in `coderd/coderdtest/` provides utilities for creating test instances of the Coder server, setting up test users and workspaces, and mocking external components.

Applied to files:

  • coderd/aitasks_test.go
📚 Learning: 2025-07-21T14:32:43.064Z
Learnt from: CRPR: coder/coder#0File: .cursorrules:0-0Timestamp: 2025-07-21T14:32:43.064ZLearning: Applies to coderdenttest/**/* : Enterprise features have dedicated test utilities in the `coderdenttest` package.

Applied to files:

  • coderd/aitasks_test.go
📚 Learning: 2025-07-21T14:32:43.064Z
Learnt from: CRPR: coder/coder#0File: .cursorrules:0-0Timestamp: 2025-07-21T14:32:43.064ZLearning: Applies to coderd/dbauthz/*.go : The database authorization (dbauthz) system enforces fine-grained access control across all database operations. All database operations must pass through this layer to ensure security.

Applied to files:

  • coderd/database/dbauthz/dbauthz.go
🧬 Code Graph Analysis (10)
site/src/api/typesGenerated.ts (1)
codersdk/aitasks.go (1)
  • CreateAITasksRequest (48-53)
coderd/database/querier.go (1)
testutil/ctx.go (1)
  • Context (9-13)
coderd/database/dbmetrics/querymetrics.go (2)
testutil/ctx.go (1)
  • Context (9-13)
coderd/database/dbtime/dbtime.go (1)
  • Now (6-8)
site/src/api/api.ts (2)
codersdk/aitasks.go (1)
  • CreateAITasksRequest (48-53)
site/src/api/typesGenerated.ts (2)
  • CreateAITasksRequest (426-431)
  • Workspace (3489-3521)
codersdk/aitasks.go (3)
codersdk/client_experimental.go (1)
  • ExperimentalClient (6-8)
site/src/api/typesGenerated.ts (2)
  • CreateAITasksRequest (426-431)
  • Workspace (3489-3521)
codersdk/client.go (1)
  • ReadBodyAsError (391-465)
coderd/aitasks_test.go (8)
testutil/ctx.go (1)
  • Context (9-13)
testutil/duration.go (1)
  • WaitShort (10-10)
coderd/coderdtest/coderdtest.go (3)
  • CreateFirstUser (743-754)
  • AwaitTemplateVersionJobCompleted (1065-1081)
  • AwaitWorkspaceBuildJobCompleted (1084-1099)
provisioner/echo/serve.go (1)
  • Responses (227-241)
site/src/api/typesGenerated.ts (2)
  • Response (2563-2567)
  • CreateAITasksRequest (426-431)
codersdk/client_experimental.go (1)
  • NewExperimentalClient (10-14)
codersdk/aitasks.go (1)
  • CreateAITasksRequest (48-53)
codersdk/client.go (1)
  • Error (469-477)
coderd/database/dbauthz/dbauthz_test.go (4)
coderd/database/models.go (4)
  • Organization (3299-3309)
  • User (3760-3785)
  • Template (3509-3546)
  • TemplateVersion (3620-3638)
coderd/database/modelmethods.go (1)
  • TemplateVersion (180-183)
coderd/rbac/policy/policy.go (1)
  • ActionRead (10-10)
codersdk/rbacresources_gen.go (1)
  • ActionRead (57-57)
coderd/aitasks.go (6)
site/src/api/typesGenerated.ts (5)
  • APIKey (18-29)
  • CreateAITasksRequest (426-431)
  • Response (2563-2567)
  • CreateWorkspaceRequest (598-607)
  • WorkspaceBuildParameter (3880-3883)
codersdk/aitasks.go (1)
  • CreateAITasksRequest (48-53)
coderd/httpapi/httpapi.go (3)
  • Is404Error (121-131)
  • ResourceNotFound (153-155)
  • Write (191-212)
coderd/audit/request.go (2)
  • InitRequest (350-446)
  • RequestParams (26-36)
coderd/database/models.go (1)
  • WorkspaceTable (4275-4295)
coderd/audit/audit.go (1)
  • AdditionalFields (19-25)
coderd/database/dbmock/dbmock.go (1)
testutil/ctx.go (1)
  • Context (9-13)
site/src/pages/TasksPage/TasksPage.tsx (2)
site/src/pages/TaskPage/TaskPage.tsx (1)
  • data (206-231)
coderd/coderd.go (1)
  • API (1636-1718)
🔇 Additional comments (10)
site/src/api/typesGenerated.ts (2)

425-432:CreateAITasksRequest matches server schema (LGTM).

Fields and optionality align with codersdk/aitasks.go (UUIDs as strings, preset_id optional). Generated location and naming look consistent with existing request types.


425-432:createAITask payloads include required fields and use snake_case

I’ve verified the lone caller ofAPI.experimental.createAITask in site/src/pages/TasksPage/TasksPage.tsx (line 742) supplies:

  • name (required)
  • template_version_id (required)
  • prompt (required)
  • template_version_preset_id (optional)

All keys are snake_case. No changes needed.

coderd/database/queries.sql.go (2)

12873-12887:LGTM: correct EXISTS query and bool mapping

The query and sqlc mapping to a boolean look correct and efficient. Returning false when the row is missing or has_ai_task is false is appropriate, especially given prior authorization/version lookups upstream.


12873-12887:Confirm whether archived template versions should be excluded

If the intent is to allow AI tasks only on active (non-archived) versions, consider adding AND archived = false. If this is enforced elsewhere (e.g., creating a workspace is already blocked for archived versions), feel free to ignore.

Proposed SQL (in the source .sql file):

SELECT EXISTS (SELECT1FROM template_versionsWHERE id= $1AND has_ai_taskAND archived= false);
coderd/aitasks_test.go (1)

198-230:Good negative-path coverage (400 on non-task template)

The check for HTTP 400 and error type is solid. This guards the server-side validation as intended.

coderd/database/dbmock/dbmock.go (1)

3274-3287:Mock addition LGTM

Method and recorder follow gomock conventions and match the interface signature.

coderd/aitasks.go (1)

20-66:Verify RBAC for prompts retrieval to prevent data leakage

The prompts endpoint fetches build parameters by IDs. Ensure the underlying store enforces authorization for the caller (e.g., via dbauthz wrapper or the authorized query variant) so members cannot see prompts of builds they don’t have access to. The MultipleBuilds test expects this.

If RBAC is not guaranteed by the wrapper, switch to the authorized query (GetAuthorizedWorkspaceBuildParametersByBuildIDs) with the appropriate prepared authorization from the request context.

codersdk/aitasks.go (1)

48-53:SDK request and handler flow looks good

Request shape matches server expectations, status check and decode logic are correct.

Also applies to: 55-72

site/src/pages/TasksPage/TasksPage.tsx (1)

295-295:No remaining createTask call sites to update
Verified thatcreateTask( only appears inTasksPage.tsx (lines 295 & 727) and that workspace APIs are untouched. No stale or legacy calls found—changes are good to go.

coderd/database/dbauthz/dbauthz.go (1)

2877-2886:Authz wrapper correctly gates AI-prompt presence check

This follows the established dbauthz pattern: authorize via GetTemplateVersionByID, then query the store. Consistent with the requirement that all DB operations flow through dbauthz.

Copy link
Collaborator

@BrunoQuaresmaBrunoQuaresma left a comment

Choose a reason for hiding this comment

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

FE code looks good to me.

Comment on lines 98 to 116
hasAITask,err:=api.Database.GetTemplateVersionHasAITask(ctx,req.TemplateVersionID)
iferr!=nil {
iferrors.Is(err,sql.ErrNoRows)||rbac.IsUnauthorizedError(err) {
httpapi.ResourceNotFound(rw)
return
}

httpapi.Write(ctx,rw,http.StatusInternalServerError, codersdk.Response{
Message:"Internal error fetching whether the template version has an AI task.",
Detail:err.Error(),
})
return
}
if!hasAITask {
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
Message:`Template does not have required parameter "`+codersdk.AITaskPromptParameterName+`"`,
})
return
}
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: This might be better moved insidewsbuilder as it runs inside a tx and has access to the parameters.

@DanielleMaywoodDanielleMaywood merged commitf349edc intomainAug 12, 2025
103 of 113 checks passed
@DanielleMaywoodDanielleMaywood deleted the danielle/tasks/move-to-be branchAugust 12, 2025 10:23
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsAug 12, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@mafredrimafredrimafredri left review comments

@BrunoQuaresmaBrunoQuaresmaBrunoQuaresma approved these changes

@johnstcnjohnstcnjohnstcn approved these changes

@aslilacaslilacAwaiting requested review from aslilacaslilac is a code owner

+1 more reviewer

@coderabbitaicoderabbitai[bot]coderabbitai[bot] left review comments

Reviewers whose approvals may not affect merge requirements
Assignees

@DanielleMaywoodDanielleMaywood

Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@DanielleMaywood@mafredri@BrunoQuaresma@johnstcn

[8]ページ先頭

©2009-2025 Movatter.jp