Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e48df2e

Browse files
committed
chore: add tests
Signed-off-by: Danny Kopping <[email protected]> # Conflicts: # go.sum
1 parent 4816ed5 commit e48df2e

File tree

6 files changed

+387
-8
lines changed

6 files changed

+387
-8
lines changed

coderd/database/dbmem/dbmem.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12075,6 +12075,7 @@ func (q *FakeQuerier) UpdateWorkspaceBuildAITaskByID(_ context.Context, arg data
1207512075
continue
1207612076
}
1207712077
workspaceBuild.HasAITask = arg.HasAITask
12078+
workspaceBuild.AITaskSidebarAppID = arg.SidebarAppID
1207812079
workspaceBuild.UpdatedAt = dbtime.Now()
1207912080
q.workspaceBuilds[index] = workspaceBuild
1208012081
return nil

coderd/provisionerdserver/provisionerdserver_test.go

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1564,6 +1564,69 @@ func TestCompleteJob(t *testing.T) {
15641564
require.Contains(t, job.Error.String, `external auth provider "github" is not configured`)
15651565
})
15661566

1567+
t.Run("TemplateImport_WithAITasks", func(t *testing.T) {
1568+
t.Parallel()
1569+
1570+
t.Run("WithoutPromptParam", func(t *testing.T) {
1571+
t.Parallel()
1572+
1573+
srv, db, _, pd := setup(t, false, &overrides{})
1574+
jobID := uuid.New()
1575+
versionID := uuid.New()
1576+
err := db.InsertTemplateVersion(ctx, database.InsertTemplateVersionParams{
1577+
ID: versionID,
1578+
JobID: jobID,
1579+
OrganizationID: pd.OrganizationID,
1580+
})
1581+
require.NoError(t, err)
1582+
job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
1583+
ID: jobID,
1584+
Provisioner: database.ProvisionerTypeEcho,
1585+
Input: []byte(`{"template_version_id": "` + versionID.String() + `"}`),
1586+
StorageMethod: database.ProvisionerStorageMethodFile,
1587+
Type: database.ProvisionerJobTypeWorkspaceBuild,
1588+
OrganizationID: pd.OrganizationID,
1589+
Tags: pd.Tags,
1590+
})
1591+
require.NoError(t, err)
1592+
_, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{
1593+
OrganizationID: pd.OrganizationID,
1594+
WorkerID: uuid.NullUUID{
1595+
UUID: pd.ID,
1596+
Valid: true,
1597+
},
1598+
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
1599+
StartedAt: sql.NullTime{
1600+
Time: dbtime.Now(),
1601+
Valid: true,
1602+
},
1603+
ProvisionerTags: must(json.Marshal(job.Tags)),
1604+
})
1605+
require.NoError(t, err)
1606+
completeJob := func() {
1607+
_, err = srv.CompleteJob(ctx, &proto.CompletedJob{
1608+
JobId: job.ID.String(),
1609+
Type: &proto.CompletedJob_TemplateImport_{
1610+
TemplateImport: &proto.CompletedJob_TemplateImport{
1611+
StartResources: []*sdkproto.Resource{{
1612+
Name: "my_task",
1613+
Type: "coder_ai_task",
1614+
}},
1615+
StopResources: []*sdkproto.Resource{},
1616+
HasAiTasks: true,
1617+
Plan: []byte("{}"),
1618+
},
1619+
},
1620+
})
1621+
require.NoError(t, err)
1622+
}
1623+
completeJob()
1624+
job, err = db.GetProvisionerJobByID(ctx, job.ID)
1625+
require.NoError(t, err)
1626+
require.Contains(t, job.Error.String, `external auth provider "github" is not configured`)
1627+
})
1628+
})
1629+
15671630
t.Run("TemplateImport_WithGitAuth", func(t *testing.T) {
15681631
t.Parallel()
15691632
srv, db, _, pd := setup(t, false, &overrides{
@@ -2435,6 +2498,233 @@ func TestCompleteJob(t *testing.T) {
24352498
testutil.RequireReceive(ctx, t, done)
24362499
require.Equal(t, replacements, orchestrator.replacements)
24372500
})
2501+
2502+
t.Run("AITasks", func(t *testing.T) {
2503+
t.Parallel()
2504+
2505+
// has_ai_task has a default value of nil, but once the template import completes it will have a value;
2506+
// it is set to "true" if the template has any coder_ai_task resources defined.
2507+
t.Run("TemplateImport", func(t *testing.T) {
2508+
type testcase struct {
2509+
name string
2510+
input *proto.CompletedJob_TemplateImport
2511+
expected bool
2512+
}
2513+
2514+
for _, tc := range []testcase{
2515+
{
2516+
name: "has_ai_task is false by default",
2517+
input: &proto.CompletedJob_TemplateImport{
2518+
// HasAiTasks is not set.
2519+
Plan: []byte("{}"),
2520+
},
2521+
expected: false,
2522+
},
2523+
{
2524+
name: "has_ai_task gets set to true",
2525+
input: &proto.CompletedJob_TemplateImport{
2526+
HasAiTasks: true,
2527+
Plan: []byte("{}"),
2528+
},
2529+
expected: true,
2530+
},
2531+
} {
2532+
t.Run(tc.name, func(t *testing.T) {
2533+
t.Parallel()
2534+
2535+
srv, db, _, pd := setup(t, false, &overrides{})
2536+
2537+
importJobID := uuid.New()
2538+
tvID := uuid.New()
2539+
template := dbgen.Template(t, db, database.Template{
2540+
Name: "template",
2541+
Provisioner: database.ProvisionerTypeEcho,
2542+
OrganizationID: pd.OrganizationID,
2543+
})
2544+
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{
2545+
ID: tvID,
2546+
OrganizationID: pd.OrganizationID,
2547+
TemplateID: uuid.NullUUID{
2548+
UUID: template.ID,
2549+
Valid: true,
2550+
},
2551+
JobID: importJobID,
2552+
})
2553+
_ = version
2554+
2555+
ctx := testutil.Context(t, testutil.WaitShort)
2556+
job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
2557+
ID: importJobID,
2558+
CreatedAt: dbtime.Now(),
2559+
UpdatedAt: dbtime.Now(),
2560+
OrganizationID: pd.OrganizationID,
2561+
InitiatorID: uuid.New(),
2562+
Input: must(json.Marshal(provisionerdserver.TemplateVersionImportJob{
2563+
TemplateVersionID: tvID,
2564+
})),
2565+
Provisioner: database.ProvisionerTypeEcho,
2566+
StorageMethod: database.ProvisionerStorageMethodFile,
2567+
Type: database.ProvisionerJobTypeTemplateVersionImport,
2568+
Tags: pd.Tags,
2569+
})
2570+
require.NoError(t, err)
2571+
2572+
_, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{
2573+
OrganizationID: pd.OrganizationID,
2574+
WorkerID: uuid.NullUUID{
2575+
UUID: pd.ID,
2576+
Valid: true,
2577+
},
2578+
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
2579+
ProvisionerTags: must(json.Marshal(job.Tags)),
2580+
StartedAt: sql.NullTime{Time: job.CreatedAt, Valid: true},
2581+
})
2582+
require.NoError(t, err)
2583+
2584+
version, err = db.GetTemplateVersionByID(ctx, tvID)
2585+
require.NoError(t, err)
2586+
require.False(t, version.HasAITask.Valid) // Value should be nil (i.e. valid = false).
2587+
2588+
completedJob := proto.CompletedJob{
2589+
JobId: job.ID.String(),
2590+
Type: &proto.CompletedJob_TemplateImport_{
2591+
TemplateImport: tc.input,
2592+
},
2593+
}
2594+
_, err = srv.CompleteJob(ctx, &completedJob)
2595+
require.NoError(t, err)
2596+
2597+
version, err = db.GetTemplateVersionByID(ctx, tvID)
2598+
require.NoError(t, err)
2599+
require.True(t, version.HasAITask.Valid) // We ALWAYS expect a value to be set, therefore not nil, i.e. valid = true.
2600+
require.Equal(t, tc.expected, version.HasAITask.Bool)
2601+
})
2602+
}
2603+
})
2604+
2605+
// has_ai_task has a default value of nil, but once the workspace build completes it will have a value;
2606+
// it is set to "true" if the related template has any coder_ai_task resources defined, and its sidebar app ID
2607+
// will be set as well in that case.
2608+
t.Run("WorkspaceBuild", func(t *testing.T) {
2609+
type testcase struct {
2610+
name string
2611+
input *proto.CompletedJob_WorkspaceBuild
2612+
expected bool
2613+
}
2614+
2615+
sidebarAppID := uuid.NewString()
2616+
for _, tc := range []testcase{
2617+
{
2618+
name: "has_ai_task is false by default",
2619+
input: &proto.CompletedJob_WorkspaceBuild{
2620+
// No AiTasks defined.
2621+
},
2622+
expected: false,
2623+
},
2624+
{
2625+
name: "has_ai_task is set to true",
2626+
input: &proto.CompletedJob_WorkspaceBuild{
2627+
AiTasks: []*sdkproto.AITask{
2628+
{
2629+
Id: uuid.NewString(),
2630+
SidebarApp: &sdkproto.AITaskSidebarApp{
2631+
Id: sidebarAppID,
2632+
},
2633+
},
2634+
},
2635+
},
2636+
expected: true,
2637+
},
2638+
} {
2639+
t.Run(tc.name, func(t *testing.T) {
2640+
t.Parallel()
2641+
2642+
srv, db, _, pd := setup(t, false, &overrides{})
2643+
2644+
importJobID := uuid.New()
2645+
tvID := uuid.New()
2646+
template := dbgen.Template(t, db, database.Template{
2647+
Name: "template",
2648+
Provisioner: database.ProvisionerTypeEcho,
2649+
OrganizationID: pd.OrganizationID,
2650+
})
2651+
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{
2652+
ID: tvID,
2653+
OrganizationID: pd.OrganizationID,
2654+
TemplateID: uuid.NullUUID{
2655+
UUID: template.ID,
2656+
Valid: true,
2657+
},
2658+
JobID: importJobID,
2659+
})
2660+
user := dbgen.User(t, db, database.User{})
2661+
workspaceTable := dbgen.Workspace(t, db, database.WorkspaceTable{
2662+
TemplateID: template.ID,
2663+
OwnerID: user.ID,
2664+
OrganizationID: pd.OrganizationID,
2665+
})
2666+
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{
2667+
WorkspaceID: workspaceTable.ID,
2668+
TemplateVersionID: version.ID,
2669+
InitiatorID: user.ID,
2670+
Transition: database.WorkspaceTransitionStart,
2671+
})
2672+
2673+
ctx := testutil.Context(t, testutil.WaitShort)
2674+
job, err := db.InsertProvisionerJob(ctx, database.InsertProvisionerJobParams{
2675+
ID: importJobID,
2676+
CreatedAt: dbtime.Now(),
2677+
UpdatedAt: dbtime.Now(),
2678+
OrganizationID: pd.OrganizationID,
2679+
InitiatorID: uuid.New(),
2680+
Input: must(json.Marshal(provisionerdserver.WorkspaceProvisionJob{
2681+
WorkspaceBuildID: build.ID,
2682+
LogLevel: "DEBUG",
2683+
})),
2684+
Provisioner: database.ProvisionerTypeEcho,
2685+
StorageMethod: database.ProvisionerStorageMethodFile,
2686+
Type: database.ProvisionerJobTypeWorkspaceBuild,
2687+
Tags: pd.Tags,
2688+
})
2689+
require.NoError(t, err)
2690+
2691+
_, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{
2692+
OrganizationID: pd.OrganizationID,
2693+
WorkerID: uuid.NullUUID{
2694+
UUID: pd.ID,
2695+
Valid: true,
2696+
},
2697+
Types: []database.ProvisionerType{database.ProvisionerTypeEcho},
2698+
ProvisionerTags: must(json.Marshal(job.Tags)),
2699+
StartedAt: sql.NullTime{Time: job.CreatedAt, Valid: true},
2700+
})
2701+
require.NoError(t, err)
2702+
2703+
build, err = db.GetWorkspaceBuildByID(ctx, build.ID)
2704+
require.NoError(t, err)
2705+
require.False(t, build.HasAITask.Valid) // Value should be nil (i.e. valid = false).
2706+
2707+
completedJob := proto.CompletedJob{
2708+
JobId: job.ID.String(),
2709+
Type: &proto.CompletedJob_WorkspaceBuild_{
2710+
WorkspaceBuild: tc.input,
2711+
},
2712+
}
2713+
_, err = srv.CompleteJob(ctx, &completedJob)
2714+
require.NoError(t, err)
2715+
2716+
build, err = db.GetWorkspaceBuildByID(ctx, build.ID)
2717+
require.NoError(t, err)
2718+
require.True(t, build.HasAITask.Valid) // We ALWAYS expect a value to be set, therefore not nil, i.e. valid = true.
2719+
require.Equal(t, tc.expected, build.HasAITask.Bool)
2720+
2721+
if tc.expected {
2722+
require.Equal(t, sidebarAppID, build.AITaskSidebarAppID.UUID.String())
2723+
}
2724+
})
2725+
}
2726+
})
2727+
})
24382728
}
24392729

24402730
type mockPrebuildsOrchestrator struct {

go.mod

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ require (
101101
github.com/coder/quartz v0.2.1
102102
github.com/coder/retry v1.5.1
103103
github.com/coder/serpent v0.10.0
104-
github.com/coder/terraform-provider-coder/v2 v2.6.0
104+
github.com/coder/terraform-provider-coder/v2 v2.7.0
105105
github.com/coder/websocket v1.8.13
106106
github.com/coder/wgtunnel v0.1.13-0.20240522110300-ade90dfb2da0
107107
github.com/coreos/go-oidc/v3 v3.14.1
@@ -535,6 +535,3 @@ require (
535535
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
536536
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
537537
)
538-
539-
// TODO: replace once new version is cut.
540-
replace github.com/coder/terraform-provider-coder/v2 => github.com/coder/terraform-provider-coder/v2 v2.5.4-0.20250619093524-d9b0f892f9c2

go.sum

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -928,9 +928,8 @@ github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c h1:d/qBIi3Ez7Kko
928928
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
929929
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e h1:JNLPDi2P73laR1oAclY6jWzAbucf70ASAvf5mh2cME0=
930930
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI=
931-
github.com/coder/terraform-provider-coder/v2 v2.5.4-0.20250619093524-d9b0f892f9c2/go.mod h1:WrdLSbihuzH1RZhwrU+qmkqEhUbdZT/sjHHdarm5b5g=
932-
github.com/coder/terraform-provider-coder/v2 v2.6.0 h1:ybSVxkblpFdanNX7hibex41yvwjswUlA3RPh4BAHjBI=
933-
github.com/coder/terraform-provider-coder/v2 v2.6.0/go.mod h1:WrdLSbihuzH1RZhwrU+qmkqEhUbdZT/sjHHdarm5b5g=
931+
github.com/coder/terraform-provider-coder/v2 v2.7.0 h1:0WV89TuboHnoy4J8MwNnCtNjF3Onx2Ny959FC2ClGQg=
932+
github.com/coder/terraform-provider-coder/v2 v2.7.0/go.mod h1:WrdLSbihuzH1RZhwrU+qmkqEhUbdZT/sjHHdarm5b5g=
934933
github.com/coder/trivy v0.0.0-20250527170238-9416a59d7019 h1:MHkv/W7l9eRAN9gOG0qZ1TLRGWIIfNi92273vPAQ8Fs=
935934
github.com/coder/trivy v0.0.0-20250527170238-9416a59d7019/go.mod h1:eqk+w9RLBmbd/cB5XfPZFuVn77cf/A6fB7qmEVeSmXk=
936935
github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=

0 commit comments

Comments
 (0)