Skip to content

Commit 616f825

Browse files
committed
chore: add database dump and dbfake logging
1 parent e80f91e commit 616f825

File tree

4 files changed

+85
-10
lines changed

4 files changed

+85
-10
lines changed

.github/workflows/ci.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,12 @@ jobs:
490490
gotestsum --format standard-quiet --packages "$PACKAGES" \
491491
-- -timeout=20m -v -p $NUM_PARALLEL_PACKAGES -parallel=$NUM_PARALLEL_TESTS $TESTCOUNT
492492
493+
- name: Upload failed test db dumps
494+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
495+
with:
496+
name: failed-test-db-dump-${{matrix.os}}
497+
path: "**/*.test.sql"
498+
493499
- name: Upload Go Build Cache
494500
uses: ./.github/actions/test-cache/upload
495501
with:

cli/agent_test.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/coder/coder/v2/coderd/coderdtest"
2222
"github.com/coder/coder/v2/coderd/database"
2323
"github.com/coder/coder/v2/coderd/database/dbfake"
24+
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2425
"github.com/coder/coder/v2/codersdk"
2526
"github.com/coder/coder/v2/codersdk/workspacesdk"
2627
"github.com/coder/coder/v2/provisionersdk/proto"
@@ -67,7 +68,12 @@ func TestWorkspaceAgent(t *testing.T) {
6768
t.Parallel()
6869
instanceID := "instanceidentifier"
6970
certificates, metadataClient := coderdtest.NewAzureInstanceIdentity(t, instanceID)
70-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
71+
db, ps := dbtestutil.NewDB(t,
72+
dbtestutil.WithDumpOnFailure(),
73+
)
74+
client := coderdtest.New(t, &coderdtest.Options{
75+
Database: db,
76+
Pubsub: ps,
7177
AzureCertificates: certificates,
7278
})
7379
user := coderdtest.CreateFirstUser(t, client)
@@ -106,7 +112,12 @@ func TestWorkspaceAgent(t *testing.T) {
106112
t.Parallel()
107113
instanceID := "instanceidentifier"
108114
certificates, metadataClient := coderdtest.NewAWSInstanceIdentity(t, instanceID)
109-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
115+
db, ps := dbtestutil.NewDB(t,
116+
dbtestutil.WithDumpOnFailure(),
117+
)
118+
client := coderdtest.New(t, &coderdtest.Options{
119+
Database: db,
120+
Pubsub: ps,
110121
AWSCertificates: certificates,
111122
})
112123
user := coderdtest.CreateFirstUser(t, client)
@@ -146,7 +157,12 @@ func TestWorkspaceAgent(t *testing.T) {
146157
t.Parallel()
147158
instanceID := "instanceidentifier"
148159
validator, metadataClient := coderdtest.NewGoogleInstanceIdentity(t, instanceID, false)
149-
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
160+
db, ps := dbtestutil.NewDB(t,
161+
dbtestutil.WithDumpOnFailure(),
162+
)
163+
client := coderdtest.New(t, &coderdtest.Options{
164+
Database: db,
165+
Pubsub: ps,
150166
GoogleTokenValidator: validator,
151167
})
152168
owner := coderdtest.CreateFirstUser(t, client)

coderd/database/dbfake/dbfake.go

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"testing"
99
"time"
1010

11+
"cdr.dev/slog"
12+
"cdr.dev/slog/sloggers/slogtest"
1113
"github.com/google/uuid"
1214
"github.com/sqlc-dev/pqtype"
1315
"github.com/stretchr/testify/require"
@@ -43,6 +45,7 @@ type WorkspaceResponse struct {
4345
// resources.
4446
type WorkspaceBuildBuilder struct {
4547
t testing.TB
48+
logger slog.Logger
4649
db database.Store
4750
ps pubsub.Pubsub
4851
ws database.WorkspaceTable
@@ -62,7 +65,10 @@ type workspaceBuildDisposition struct {
6265
// Omitting the template ID on a workspace will also generate a new template
6366
// with a template version.
6467
func WorkspaceBuild(t testing.TB, db database.Store, ws database.WorkspaceTable) WorkspaceBuildBuilder {
65-
return WorkspaceBuildBuilder{t: t, db: db, ws: ws}
68+
return WorkspaceBuildBuilder{
69+
t: t, db: db, ws: ws,
70+
logger: slogtest.Make(t, &slogtest.Options{}).Named("dbfake").Leveled(slog.LevelDebug),
71+
}
6672
}
6773

6874
func (b WorkspaceBuildBuilder) Pubsub(ps pubsub.Pubsub) WorkspaceBuildBuilder {
@@ -131,6 +137,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
131137
AgentToken: b.agentToken,
132138
}
133139
if b.ws.TemplateID == uuid.Nil {
140+
b.logger.Debug(context.Background(), "creating template and version")
134141
resp.TemplateVersionResponse = TemplateVersion(b.t, b.db).
135142
Resources(b.resources...).
136143
Pubsub(b.ps).
@@ -145,6 +152,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
145152

146153
// If no template version is set assume the active version.
147154
if b.seed.TemplateVersionID == uuid.Nil {
155+
b.logger.Debug(context.Background(), "assuming active template version")
148156
template, err := b.db.GetTemplateByID(ownerCtx, b.ws.TemplateID)
149157
require.NoError(b.t, err)
150158
require.NotNil(b.t, template.ActiveVersionID, "active version ID unexpectedly nil")
@@ -156,6 +164,9 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
156164
// nolint: revive
157165
b.ws = dbgen.Workspace(b.t, b.db, b.ws)
158166
resp.Workspace = b.ws
167+
b.logger.Debug(context.Background(), "created workspace",
168+
slog.F("name", resp.Workspace.Name),
169+
slog.F("workspace_id", resp.Workspace.ID))
159170
}
160171
b.seed.WorkspaceID = b.ws.ID
161172
b.seed.InitiatorID = takeFirst(b.seed.InitiatorID, b.ws.OwnerID)
@@ -182,10 +193,12 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
182193
LogsOverflowed: false,
183194
})
184195
require.NoError(b.t, err, "insert job")
196+
b.logger.Debug(context.Background(), "inserted provisioner job", slog.F("job_id", job.ID))
185197

186198
if b.dispo.starting {
187199
// might need to do this multiple times if we got a template version
188200
// import job as well
201+
b.logger.Debug(context.Background(), "looping to acquire provisioner job")
189202
for {
190203
j, err := b.db.AcquireProvisionerJob(ownerCtx, database.AcquireProvisionerJobParams{
191204
OrganizationID: job.OrganizationID,
@@ -202,10 +215,12 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
202215
})
203216
require.NoError(b.t, err, "acquire starting job")
204217
if j.ID == job.ID {
218+
b.logger.Debug(context.Background(), "acquired provisioner job", slog.F("job_id", job.ID))
205219
break
206220
}
207221
}
208222
} else {
223+
b.logger.Debug(context.Background(), "completing the provisioner job")
209224
err = b.db.UpdateProvisionerJobWithCompleteByID(ownerCtx, database.UpdateProvisionerJobWithCompleteByIDParams{
210225
ID: job.ID,
211226
UpdatedAt: dbtime.Now(),
@@ -221,18 +236,24 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
221236
}
222237

223238
resp.Build = dbgen.WorkspaceBuild(b.t, b.db, b.seed)
239+
b.logger.Debug(context.Background(), "created workspace build",
240+
slog.F("build_id", resp.Build.ID),
241+
slog.F("workspace_id", resp.Workspace.ID),
242+
slog.F("build_number", resp.Build.BuildNumber))
224243

225244
for i := range b.params {
226245
b.params[i].WorkspaceBuildID = resp.Build.ID
227246
}
228-
_ = dbgen.WorkspaceBuildParameters(b.t, b.db, b.params)
247+
params := dbgen.WorkspaceBuildParameters(b.t, b.db, b.params)
248+
b.logger.Debug(context.Background(), "created workspace build parameters", slog.F("count", len(params)))
229249

230250
if b.ws.Deleted {
231251
err = b.db.UpdateWorkspaceDeletedByID(ownerCtx, database.UpdateWorkspaceDeletedByIDParams{
232252
ID: b.ws.ID,
233253
Deleted: true,
234254
})
235255
require.NoError(b.t, err)
256+
b.logger.Debug(context.Background(), "deleted workspace", slog.F("workspace_id", resp.Workspace.ID))
236257
}
237258

238259
if b.ps != nil {
@@ -243,6 +264,9 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
243264
require.NoError(b.t, err)
244265
err = b.ps.Publish(wspubsub.WorkspaceEventChannel(resp.Workspace.OwnerID), msg)
245266
require.NoError(b.t, err)
267+
b.logger.Debug(context.Background(), "published workspace event",
268+
slog.F("owner_id", resp.Workspace.ID),
269+
slog.F("owner_id", resp.Workspace.OwnerID))
246270
}
247271

248272
agents, err := b.db.GetWorkspaceAgentsByWorkspaceAndBuildNumber(ownerCtx, database.GetWorkspaceAgentsByWorkspaceAndBuildNumberParams{
@@ -260,7 +284,12 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
260284
err = b.db.DeleteWorkspaceSubAgentByID(ownerCtx, subAgent.ID)
261285
require.NoError(b.t, err, "delete workspace agent subagent antagonist")
262286

263-
b.t.Logf("inserted deleted subagent antagonist %s (%v) for workspace agent %s (%v)", subAgent.Name, subAgent.ID, agent.Name, agent.ID)
287+
b.logger.Debug(context.Background(), "inserted deleted subagent antagonist",
288+
slog.F("subagent_name", subAgent.Name),
289+
slog.F("subagent_id", subAgent.ID),
290+
slog.F("agent_name", agent.Name),
291+
slog.F("agent_id", agent.ID),
292+
)
264293
}
265294
}
266295

@@ -269,6 +298,7 @@ func (b WorkspaceBuildBuilder) Do() WorkspaceResponse {
269298

270299
type ProvisionerJobResourcesBuilder struct {
271300
t testing.TB
301+
logger slog.Logger
272302
db database.Store
273303
jobID uuid.UUID
274304
transition database.WorkspaceTransition
@@ -281,6 +311,7 @@ func ProvisionerJobResources(
281311
) ProvisionerJobResourcesBuilder {
282312
return ProvisionerJobResourcesBuilder{
283313
t: t,
314+
logger: slogtest.Make(t, &slogtest.Options{}).Named("dbfake").Leveled(slog.LevelDebug).With(slog.F("job_id", jobID)),
284315
db: db,
285316
jobID: jobID,
286317
transition: transition,
@@ -292,13 +323,17 @@ func (b ProvisionerJobResourcesBuilder) Do() {
292323
b.t.Helper()
293324
transition := b.transition
294325
if transition == "" {
295-
// Default to start!
326+
b.logger.Debug(context.Background(), "setting default transition to start")
296327
transition = database.WorkspaceTransitionStart
297328
}
298329
for _, resource := range b.resources {
299330
//nolint:gocritic // This is only used by tests.
300331
err := provisionerdserver.InsertWorkspaceResource(ownerCtx, b.db, b.jobID, transition, resource, &telemetry.Snapshot{})
301332
require.NoError(b.t, err)
333+
b.logger.Debug(context.Background(), "created workspace resource",
334+
slog.F("resource_name", resource.Name),
335+
slog.F("agent_count", len(resource.Agents)),
336+
)
302337
}
303338
}
304339

@@ -309,6 +344,7 @@ type TemplateVersionResponse struct {
309344

310345
type TemplateVersionBuilder struct {
311346
t testing.TB
347+
logger slog.Logger
312348
db database.Store
313349
seed database.TemplateVersion
314350
fileID uuid.UUID
@@ -326,6 +362,7 @@ type TemplateVersionBuilder struct {
326362
func TemplateVersion(t testing.TB, db database.Store) TemplateVersionBuilder {
327363
return TemplateVersionBuilder{
328364
t: t,
365+
logger: slogtest.Make(t, &slogtest.Options{}).Named("dbfake").Leveled(slog.LevelDebug),
329366
db: db,
330367
promote: true,
331368
autoCreateTemplate: true,
@@ -396,20 +433,30 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
396433
Valid: true,
397434
UUID: resp.Template.ID,
398435
}
436+
t.logger.Debug(context.Background(), "created template",
437+
slog.F("organization_id", resp.Template.OrganizationID),
438+
slog.F("template_id", resp.Template.CreatedBy),
439+
)
399440
}
400441

401442
version := dbgen.TemplateVersion(t.t, t.db, t.seed)
443+
t.logger.Debug(context.Background(), "created template version",
444+
slog.F("template_version_id", version.ID),
445+
)
402446
if t.promote {
403447
err := t.db.UpdateTemplateActiveVersionByID(ownerCtx, database.UpdateTemplateActiveVersionByIDParams{
404448
ID: t.seed.TemplateID.UUID,
405449
ActiveVersionID: t.seed.ID,
406450
UpdatedAt: dbtime.Now(),
407451
})
408452
require.NoError(t.t, err)
453+
t.logger.Debug(context.Background(), "promoted template version",
454+
slog.F("template_version_id", t.seed.ID),
455+
)
409456
}
410457

411458
for _, preset := range t.presets {
412-
dbgen.Preset(t.t, t.db, database.InsertPresetParams{
459+
prst := dbgen.Preset(t.t, t.db, database.InsertPresetParams{
413460
ID: preset.ID,
414461
TemplateVersionID: version.ID,
415462
Name: preset.Name,
@@ -421,14 +468,19 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
421468
Description: preset.Description,
422469
Icon: preset.Icon,
423470
})
471+
t.logger.Debug(context.Background(), "added preset",
472+
slog.F("preset_id", prst.ID),
473+
slog.F("preset_name", prst.Name),
474+
)
424475
}
425476

426477
for _, presetParam := range t.presetParams {
427-
dbgen.PresetParameter(t.t, t.db, database.InsertPresetParametersParams{
478+
prm := dbgen.PresetParameter(t.t, t.db, database.InsertPresetParametersParams{
428479
TemplateVersionPresetID: presetParam.TemplateVersionPresetID,
429480
Names: []string{presetParam.Name},
430481
Values: []string{presetParam.Value},
431482
})
483+
t.logger.Debug(context.Background(), "added preset parameter", slog.F("param_name", prm[0].Name))
432484
}
433485

434486
payload, err := json.Marshal(provisionerdserver.TemplateVersionImportJob{
@@ -448,6 +500,7 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
448500
},
449501
FileID: t.fileID,
450502
})
503+
t.logger.Debug(context.Background(), "added template version import job", slog.F("job_id", job.ID))
451504

452505
t.seed.JobID = job.ID
453506

coderd/database/dbtestutil/db.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ func DumpOnFailure(t testing.TB, connectionURL string) {
206206
outPath := filepath.Join(cwd, snakeCaseName+"."+timeSuffix+".test.sql")
207207
dump, err := PGDump(connectionURL)
208208
if err != nil {
209-
t.Errorf("dump on failure: failed to run pg_dump")
209+
t.Errorf("dump on failure: failed to run pg_dump: %s", err.Error())
210210
return
211211
}
212212
if err := os.WriteFile(outPath, normalizeDump(dump), 0o600); err != nil {

0 commit comments

Comments
 (0)