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

Commitd32f3e4

Browse files
committed
endpoint
1 parentb5ab9d3 commitd32f3e4

File tree

8 files changed

+232
-4
lines changed

8 files changed

+232
-4
lines changed

‎coderd/database/dbmem/dbmem.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13233,6 +13233,17 @@ func (q *FakeQuerier) GetAuthorizedTemplates(ctx context.Context, arg database.G
1323313233
continue
1323413234
}
1323513235
}
13236+
13237+
ifarg.HasAITask.Valid {
13238+
build,err:=q.getTemplateVersionByIDNoLock(ctx,template.ActiveVersionID)
13239+
iferr!=nil {
13240+
returnnil,xerrors.Errorf("get latest build: %w",err)
13241+
}
13242+
ifbuild.HasAITask!=arg.HasAITask.Bool {
13243+
continue
13244+
}
13245+
}
13246+
1323613247
templates=append(templates,template)
1323713248
}
1323813249
iflen(templates)>0 {
@@ -13562,6 +13573,16 @@ func (q *FakeQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg database.
1356213573
}
1356313574
}
1356413575

13576+
ifarg.HasAITask.Valid {
13577+
build,err:=q.getLatestWorkspaceBuildByWorkspaceIDNoLock(ctx,workspace.ID)
13578+
iferr!=nil {
13579+
returnnil,xerrors.Errorf("get latest build: %w",err)
13580+
}
13581+
ifbuild.HasAITask!=arg.HasAITask.Bool {
13582+
continue
13583+
}
13584+
}
13585+
1356513586
// If the filter exists, ensure the object is authorized.
1356613587
ifprepared!=nil&&prepared.Authorize(ctx,workspace.RBACObject())!=nil {
1356713588
continue

‎coderd/rbac/regosql/compile_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,8 @@ internal.member_2(input.object.org_owner, {"3bf82434-e40b-44ae-b3d8-d0115bba9bad
236236
neq(input.object.owner, "");
237237
"806dd721-775f-4c85-9ce3-63fbbd975954" = input.object.owner`,
238238
},
239-
ExpectedSQL:p(p("organization_id :: text != ''")+" AND "+
240-
p("organization_id :: text = ANY(ARRAY ['3bf82434-e40b-44ae-b3d8-d0115bba9bad','5630fda3-26ab-462c-9014-a88a62d7a415','c304877a-bc0d-4e9b-9623-a38eae412929'])")+" AND "+
239+
ExpectedSQL:p(p("t.organization_id :: text != ''")+" AND "+
240+
p("t.organization_id :: text = ANY(ARRAY ['3bf82434-e40b-44ae-b3d8-d0115bba9bad','5630fda3-26ab-462c-9014-a88a62d7a415','c304877a-bc0d-4e9b-9623-a38eae412929'])")+" AND "+
241241
p("false")+" AND "+
242242
p("false")),
243243
VariableConverter:regosql.TemplateConverter(),

‎coderd/rbac/regosql/configs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func userACLMatcher(m sqltypes.VariableMatcher) sqltypes.VariableMatcher {
2525
funcTemplateConverter()*sqltypes.VariableConverter {
2626
matcher:=sqltypes.NewVariableConverter().RegisterMatcher(
2727
resourceIDMatcher(),
28-
organizationOwnerMatcher(),
28+
sqltypes.StringVarMatcher("t.organization_id :: text", []string{"input","object","org_owner"}),
2929
// Templates have no user owner, only owner by an organization.
3030
sqltypes.AlwaysFalse(userOwnerMatcher()),
3131
)

‎coderd/searchquery/search.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ func Workspaces(ctx context.Context, db database.Store, query string, page coder
146146
// which will return all workspaces.
147147
Valid:values.Has("outdated"),
148148
}
149+
filter.HasAITask=parser.NullableBoolean(values, sql.NullBool{},"has-ai-task")
149150
filter.OrganizationID=parseOrganization(ctx,db,parser,values,"organization")
150151

151152
typeparamMatchstruct {
@@ -206,6 +207,7 @@ func Templates(ctx context.Context, db database.Store, query string) (database.G
206207
IDs:parser.UUIDs(values, []uuid.UUID{},"ids"),
207208
Deprecated:parser.NullableBoolean(values, sql.NullBool{},"deprecated"),
208209
OrganizationID:parseOrganization(ctx,db,parser,values,"organization"),
210+
HasAITask:parser.NullableBoolean(values, sql.NullBool{},"has-ai-task"),
209211
}
210212

211213
parser.ErrorExcessParams(values)

‎coderd/searchquery/search_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,36 @@ func TestSearchWorkspace(t *testing.T) {
222222
OrganizationID:uuid.MustParse("08eb6715-02f8-45c5-b86d-03786fcfbb4e"),
223223
},
224224
},
225+
{
226+
Name:"HasAITaskTrue",
227+
Query:"has-ai-task:true",
228+
Expected: database.GetWorkspacesParams{
229+
HasAITask: sql.NullBool{
230+
Bool:true,
231+
Valid:true,
232+
},
233+
},
234+
},
235+
{
236+
Name:"HasAITaskFalse",
237+
Query:"has-ai-task:false",
238+
Expected: database.GetWorkspacesParams{
239+
HasAITask: sql.NullBool{
240+
Bool:false,
241+
Valid:true,
242+
},
243+
},
244+
},
245+
{
246+
Name:"HasAITaskMissing",
247+
Query:"",
248+
Expected: database.GetWorkspacesParams{
249+
HasAITask: sql.NullBool{
250+
Bool:false,
251+
Valid:false,
252+
},
253+
},
254+
},
225255

226256
// Failures
227257
{
@@ -559,6 +589,36 @@ func TestSearchTemplates(t *testing.T) {
559589
FuzzyName:"foobar",
560590
},
561591
},
592+
{
593+
Name:"HasAITaskTrue",
594+
Query:"has-ai-task:true",
595+
Expected: database.GetTemplatesWithFilterParams{
596+
HasAITask: sql.NullBool{
597+
Bool:true,
598+
Valid:true,
599+
},
600+
},
601+
},
602+
{
603+
Name:"HasAITaskFalse",
604+
Query:"has-ai-task:false",
605+
Expected: database.GetTemplatesWithFilterParams{
606+
HasAITask: sql.NullBool{
607+
Bool:false,
608+
Valid:true,
609+
},
610+
},
611+
},
612+
{
613+
Name:"HasAITaskMissing",
614+
Query:"",
615+
Expected: database.GetTemplatesWithFilterParams{
616+
HasAITask: sql.NullBool{
617+
Bool:false,
618+
Valid:false,
619+
},
620+
},
621+
},
562622
}
563623

564624
for_,c:=rangetestCases {

‎coderd/templates_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/coder/coder/v2/coderd/coderdtest"
1717
"github.com/coder/coder/v2/coderd/database"
1818
"github.com/coder/coder/v2/coderd/database/dbauthz"
19+
"github.com/coder/coder/v2/coderd/database/dbgen"
1920
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2021
"github.com/coder/coder/v2/coderd/database/dbtime"
2122
"github.com/coder/coder/v2/coderd/notifications"
@@ -1809,3 +1810,66 @@ func TestTemplateNotifications(t *testing.T) {
18091810
})
18101811
})
18111812
}
1813+
1814+
funcTestTemplateFilterHasAITask(t*testing.T) {
1815+
t.Parallel()
1816+
1817+
db,pubsub:=dbtestutil.NewDB(t)
1818+
client:=coderdtest.New(t,&coderdtest.Options{
1819+
Database:db,
1820+
Pubsub:pubsub,
1821+
IncludeProvisionerDaemon:true,
1822+
})
1823+
user:=coderdtest.CreateFirstUser(t,client)
1824+
1825+
jobWithAI:=dbgen.ProvisionerJob(t,db,pubsub, database.ProvisionerJob{
1826+
OrganizationID:user.OrganizationID,
1827+
InitiatorID:user.UserID,
1828+
Tags: database.StringMap{},
1829+
Type:database.ProvisionerJobTypeTemplateVersionImport,
1830+
})
1831+
jobWithoutAI:=dbgen.ProvisionerJob(t,db,pubsub, database.ProvisionerJob{
1832+
OrganizationID:user.OrganizationID,
1833+
InitiatorID:user.UserID,
1834+
Tags: database.StringMap{},
1835+
Type:database.ProvisionerJobTypeTemplateVersionImport,
1836+
})
1837+
versionWithAI:=dbgen.TemplateVersion(t,db, database.TemplateVersion{
1838+
OrganizationID:user.OrganizationID,
1839+
CreatedBy:user.UserID,
1840+
HasAITask:true,
1841+
JobID:jobWithAI.ID,
1842+
})
1843+
versionWithoutAI:=dbgen.TemplateVersion(t,db, database.TemplateVersion{
1844+
OrganizationID:user.OrganizationID,
1845+
CreatedBy:user.UserID,
1846+
HasAITask:false,
1847+
JobID:jobWithoutAI.ID,
1848+
})
1849+
templateWithAI:=coderdtest.CreateTemplate(t,client,user.OrganizationID,versionWithAI.ID)
1850+
templateWithoutAI:=coderdtest.CreateTemplate(t,client,user.OrganizationID,versionWithoutAI.ID)
1851+
1852+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
1853+
defercancel()
1854+
1855+
// Test filtering
1856+
templates,err:=client.Templates(ctx, codersdk.TemplateFilter{
1857+
SearchQuery:"has-ai-task:true",
1858+
})
1859+
require.NoError(t,err)
1860+
require.Len(t,templates,1)
1861+
require.Equal(t,templateWithAI.ID,templates[0].ID)
1862+
1863+
templates,err=client.Templates(ctx, codersdk.TemplateFilter{
1864+
SearchQuery:"has-ai-task:false",
1865+
})
1866+
require.NoError(t,err)
1867+
require.Len(t,templates,1)
1868+
require.Equal(t,templateWithoutAI.ID,templates[0].ID)
1869+
1870+
templates,err=client.Templates(ctx, codersdk.TemplateFilter{})
1871+
require.NoError(t,err)
1872+
require.Len(t,templates,2)
1873+
require.Contains(t,templates,templateWithAI)
1874+
require.Contains(t,templates,templateWithoutAI)
1875+
}

‎coderd/workspaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func (api *API) workspace(rw http.ResponseWriter, r *http.Request) {
136136
// @Security CoderSessionToken
137137
// @Produce json
138138
// @Tags Workspaces
139-
// @Param q query string false "Search query in the format `key:value`. Available keys are: owner, template, name, status, has-agent, dormant, last_used_after, last_used_before."
139+
// @Param q query string false "Search query in the format `key:value`. Available keys are: owner, template, name, status, has-agent, dormant, last_used_after, last_used_before, has-ai-task."
140140
// @Param limit query int false "Page limit"
141141
// @Param offset query int false "Page offset"
142142
// @Success 200 {object} codersdk.WorkspacesResponse

‎coderd/workspaces_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4494,3 +4494,84 @@ func TestOIDCRemoved(t *testing.T) {
44944494
require.NoError(t,err,"delete the workspace")
44954495
coderdtest.AwaitWorkspaceBuildJobCompleted(t,owner,deleteBuild.ID)
44964496
}
4497+
4498+
funcTestWorkspaceFilterHasAITask(t*testing.T) {
4499+
t.Parallel()
4500+
4501+
db,pubsub:=dbtestutil.NewDB(t)
4502+
client:=coderdtest.New(t,&coderdtest.Options{
4503+
Database:db,
4504+
Pubsub:pubsub,
4505+
IncludeProvisionerDaemon:true,
4506+
})
4507+
user:=coderdtest.CreateFirstUser(t,client)
4508+
4509+
// Create template versions with different HasAITask values
4510+
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
4511+
4512+
coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
4513+
4514+
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
4515+
4516+
wsWithAI:=dbgen.Workspace(t,db, database.WorkspaceTable{
4517+
OwnerID:user.UserID,
4518+
OrganizationID:user.OrganizationID,
4519+
TemplateID:template.ID,
4520+
})
4521+
jobWithAI:=dbgen.ProvisionerJob(t,db,pubsub, database.ProvisionerJob{
4522+
OrganizationID:user.OrganizationID,
4523+
InitiatorID:user.UserID,
4524+
Tags: database.StringMap{},
4525+
})
4526+
dbgen.WorkspaceBuild(t,db, database.WorkspaceBuild{
4527+
WorkspaceID:wsWithAI.ID,
4528+
TemplateVersionID:version.ID,
4529+
InitiatorID:user.UserID,
4530+
JobID:jobWithAI.ID,
4531+
BuildNumber:1,
4532+
HasAITask:true,
4533+
})
4534+
4535+
wsWithoutAI:=dbgen.Workspace(t,db, database.WorkspaceTable{
4536+
OwnerID:user.UserID,
4537+
OrganizationID:user.OrganizationID,
4538+
TemplateID:template.ID,
4539+
})
4540+
jobWithoutAI:=dbgen.ProvisionerJob(t,db,pubsub, database.ProvisionerJob{
4541+
OrganizationID:user.OrganizationID,
4542+
InitiatorID:user.UserID,
4543+
Tags: database.StringMap{},
4544+
})
4545+
dbgen.WorkspaceBuild(t,db, database.WorkspaceBuild{
4546+
WorkspaceID:wsWithoutAI.ID,
4547+
TemplateVersionID:version.ID,
4548+
InitiatorID:user.UserID,
4549+
JobID:jobWithoutAI.ID,
4550+
BuildNumber:1,
4551+
HasAITask:false,
4552+
})
4553+
4554+
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
4555+
defercancel()
4556+
4557+
// Test filtering for workspaces with AI tasks
4558+
res,err:=client.Workspaces(ctx, codersdk.WorkspaceFilter{
4559+
FilterQuery:"has-ai-task:true",
4560+
})
4561+
require.NoError(t,err)
4562+
require.Len(t,res.Workspaces,1)
4563+
require.Equal(t,wsWithAI.ID,res.Workspaces[0].ID)
4564+
4565+
// Test filtering for workspaces without AI tasks
4566+
res,err=client.Workspaces(ctx, codersdk.WorkspaceFilter{
4567+
FilterQuery:"has-ai-task:false",
4568+
})
4569+
require.NoError(t,err)
4570+
require.Len(t,res.Workspaces,1)
4571+
require.Equal(t,wsWithoutAI.ID,res.Workspaces[0].ID)
4572+
4573+
// Test no filter returns both
4574+
res,err=client.Workspaces(ctx, codersdk.WorkspaceFilter{})
4575+
require.NoError(t,err)
4576+
require.Len(t,res.Workspaces,2)
4577+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp