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

Skip to content

Commit d240c0e

Browse files
committed
chore: add tests
Signed-off-by: Danny Kopping <[email protected]>
1 parent 8aef94a commit d240c0e

File tree

6 files changed

+387
-7
lines changed

6 files changed

+387
-7
lines changed

coderd/database/dbmem/dbmem.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12035,6 +12035,7 @@ func (q *FakeQuerier) UpdateWorkspaceBuildAITaskByID(_ context.Context, arg data
1203512035
continue
1203612036
}
1203712037
workspaceBuild.HasAITask = arg.HasAITask
12038+
workspaceBuild.AITaskSidebarAppID = arg.SidebarAppID
1203812039
workspaceBuild.UpdatedAt = dbtime.Now()
1203912040
q.workspaceBuilds[index] = workspaceBuild
1204012041
return nil

coderd/provisionerdserver/provisionerdserver_test.go

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

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

24462736
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 & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,8 +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 h1:m/AiSodThXfD4vppmdQW11k8TQ6K2Gv/uaq2UZAC/ok=
932-
github.com/coder/terraform-provider-coder/v2 v2.5.4-0.20250619093524-d9b0f892f9c2/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=
933933
github.com/coder/trivy v0.0.0-20250527170238-9416a59d7019 h1:MHkv/W7l9eRAN9gOG0qZ1TLRGWIIfNi92273vPAQ8Fs=
934934
github.com/coder/trivy v0.0.0-20250527170238-9416a59d7019/go.mod h1:eqk+w9RLBmbd/cB5XfPZFuVn77cf/A6fB7qmEVeSmXk=
935935
github.com/coder/websocket v1.8.13 h1:f3QZdXy7uGVz+4uCJy2nTZyM0yTBj8yANEHhqlXZ9FE=

0 commit comments

Comments
 (0)