feat: Add stage to build logs (#577)

* feat: Add stage to build logs

This adds a stage property to logs, and refactors the job logs
cliui.

It also adds tests to the cliui for build logs!

* Fix comments
This commit is contained in:
Kyle Carberry
2022-03-28 18:43:22 +00:00
committed by GitHub
parent eb18925f11
commit b33dec9d38
29 changed files with 604 additions and 262 deletions
+1 -1
View File
@@ -898,6 +898,7 @@ func (q *fakeQuerier) InsertProvisionerJobLogs(_ context.Context, arg database.I
CreatedAt: arg.CreatedAt[index],
Source: arg.Source[index],
Level: arg.Level[index],
Stage: arg.Stage[index],
Output: output,
})
}
@@ -1201,7 +1202,6 @@ func (q *fakeQuerier) UpdateProvisionerJobWithCompleteByID(_ context.Context, ar
}
job.UpdatedAt = arg.UpdatedAt
job.CompletedAt = arg.CompletedAt
job.CanceledAt = arg.CanceledAt
job.Error = arg.Error
q.provisionerJobs[index] = job
return nil
+1
View File
@@ -190,6 +190,7 @@ CREATE TABLE provisioner_job_logs (
created_at timestamp with time zone NOT NULL,
source log_source NOT NULL,
level log_level NOT NULL,
stage character varying(128) NOT NULL,
output character varying(1024) NOT NULL
);
@@ -53,6 +53,7 @@ CREATE TABLE IF NOT EXISTS provisioner_job_logs (
created_at timestamptz NOT NULL,
source log_source NOT NULL,
level log_level NOT NULL,
stage varchar(128) NOT NULL,
output varchar(1024) NOT NULL
);
+1
View File
@@ -388,6 +388,7 @@ type ProvisionerJobLog struct {
CreatedAt time.Time `db:"created_at" json:"created_at"`
Source LogSource `db:"source" json:"source"`
Level LogLevel `db:"level" json:"level"`
Stage string `db:"stage" json:"stage"`
Output string `db:"output" json:"output"`
}
+2 -2
View File
@@ -482,6 +482,7 @@ SELECT
unnest(@created_at :: timestamptz [ ]) AS created_at,
unnest(@source :: log_source [ ]) as source,
unnest(@level :: log_level [ ]) as level,
unnest(@stage :: varchar(128) [ ]) as stage,
unnest(@output :: varchar(1024) [ ]) as output RETURNING *;
-- name: InsertOrganization :one
@@ -757,8 +758,7 @@ UPDATE
SET
updated_at = $2,
completed_at = $3,
canceled_at = $4,
error = $5
error = $4
WHERE
id = $1;
+8 -6
View File
@@ -829,7 +829,7 @@ func (q *sqlQuerier) GetProvisionerJobsByIDs(ctx context.Context, ids []uuid.UUI
const getProvisionerLogsByIDBetween = `-- name: GetProvisionerLogsByIDBetween :many
SELECT
id, job_id, created_at, source, level, output
id, job_id, created_at, source, level, stage, output
FROM
provisioner_job_logs
WHERE
@@ -863,6 +863,7 @@ func (q *sqlQuerier) GetProvisionerLogsByIDBetween(ctx context.Context, arg GetP
&i.CreatedAt,
&i.Source,
&i.Level,
&i.Stage,
&i.Output,
); err != nil {
return nil, err
@@ -2121,7 +2122,8 @@ SELECT
unnest($3 :: timestamptz [ ]) AS created_at,
unnest($4 :: log_source [ ]) as source,
unnest($5 :: log_level [ ]) as level,
unnest($6 :: varchar(1024) [ ]) as output RETURNING id, job_id, created_at, source, level, output
unnest($6 :: varchar(128) [ ]) as stage,
unnest($7 :: varchar(1024) [ ]) as output RETURNING id, job_id, created_at, source, level, stage, output
`
type InsertProvisionerJobLogsParams struct {
@@ -2130,6 +2132,7 @@ type InsertProvisionerJobLogsParams struct {
CreatedAt []time.Time `db:"created_at" json:"created_at"`
Source []LogSource `db:"source" json:"source"`
Level []LogLevel `db:"level" json:"level"`
Stage []string `db:"stage" json:"stage"`
Output []string `db:"output" json:"output"`
}
@@ -2140,6 +2143,7 @@ func (q *sqlQuerier) InsertProvisionerJobLogs(ctx context.Context, arg InsertPro
pq.Array(arg.CreatedAt),
pq.Array(arg.Source),
pq.Array(arg.Level),
pq.Array(arg.Stage),
pq.Array(arg.Output),
)
if err != nil {
@@ -2155,6 +2159,7 @@ func (q *sqlQuerier) InsertProvisionerJobLogs(ctx context.Context, arg InsertPro
&i.CreatedAt,
&i.Source,
&i.Level,
&i.Stage,
&i.Output,
); err != nil {
return nil, err
@@ -2617,8 +2622,7 @@ UPDATE
SET
updated_at = $2,
completed_at = $3,
canceled_at = $4,
error = $5
error = $4
WHERE
id = $1
`
@@ -2627,7 +2631,6 @@ type UpdateProvisionerJobWithCompleteByIDParams struct {
ID uuid.UUID `db:"id" json:"id"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
CompletedAt sql.NullTime `db:"completed_at" json:"completed_at"`
CanceledAt sql.NullTime `db:"canceled_at" json:"canceled_at"`
Error sql.NullString `db:"error" json:"error"`
}
@@ -2636,7 +2639,6 @@ func (q *sqlQuerier) UpdateProvisionerJobWithCompleteByID(ctx context.Context, a
arg.ID,
arg.UpdatedAt,
arg.CompletedAt,
arg.CanceledAt,
arg.Error,
)
return err
+7 -5
View File
@@ -94,9 +94,7 @@ func TestPatchCancelProjectVersion(t *testing.T) {
var err error
version, err = client.ProjectVersion(context.Background(), version.ID)
require.NoError(t, err)
// The echo provisioner doesn't respond to a shutdown request,
// so the job cancel will time out and fail.
return version.Job.Status == codersdk.ProvisionerJobFailed
return version.Job.Status == codersdk.ProvisionerJobCanceled
}, 5*time.Second, 25*time.Millisecond)
})
}
@@ -274,6 +272,10 @@ func TestProjectVersionLogs(t *testing.T) {
t.Cleanup(cancelFunc)
logs, err := client.ProjectVersionLogsAfter(ctx, version.ID, before)
require.NoError(t, err)
log := <-logs
require.Equal(t, "example", log.Output)
for {
_, ok := <-logs
if !ok {
return
}
}
}
+1
View File
@@ -303,6 +303,7 @@ func (server *provisionerdServer) UpdateJob(ctx context.Context, request *proto.
insertParams.ID = append(insertParams.ID, uuid.New())
insertParams.CreatedAt = append(insertParams.CreatedAt, time.UnixMilli(log.CreatedAt))
insertParams.Level = append(insertParams.Level, logLevel)
insertParams.Stage = append(insertParams.Stage, log.Stage)
insertParams.Source = append(insertParams.Source, logSource)
insertParams.Output = append(insertParams.Output, log.Output)
}
+1
View File
@@ -224,6 +224,7 @@ func convertProvisionerJobLog(provisionerJobLog database.ProvisionerJobLog) code
CreatedAt: provisionerJobLog.CreatedAt,
Source: provisionerJobLog.Source,
Level: provisionerJobLog.Level,
Stage: provisionerJobLog.Stage,
Output: provisionerJobLog.Output,
}
}
+13 -11
View File
@@ -45,12 +45,12 @@ func TestProvisionerJobLogs(t *testing.T) {
t.Cleanup(cancelFunc)
logs, err := client.WorkspaceBuildLogsAfter(ctx, workspace.LatestBuild.ID, before)
require.NoError(t, err)
log, ok := <-logs
require.True(t, ok)
require.Equal(t, "log-output", log.Output)
// Make sure the channel automatically closes!
_, ok = <-logs
require.False(t, ok)
for {
_, ok := <-logs
if !ok {
return
}
}
})
t.Run("StreamWhileRunning", func(t *testing.T) {
@@ -81,10 +81,12 @@ func TestProvisionerJobLogs(t *testing.T) {
t.Cleanup(cancelFunc)
logs, err := client.WorkspaceBuildLogsAfter(ctx, workspace.LatestBuild.ID, before)
require.NoError(t, err)
log := <-logs
require.Equal(t, "log-output", log.Output)
_, ok := <-logs
require.False(t, ok)
for {
_, ok := <-logs
if !ok {
return
}
}
})
t.Run("List", func(t *testing.T) {
@@ -113,6 +115,6 @@ func TestProvisionerJobLogs(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
logs, err := client.WorkspaceBuildLogsBefore(context.Background(), workspace.LatestBuild.ID, time.Now())
require.NoError(t, err)
require.Len(t, logs, 1)
require.Greater(t, len(logs), 1)
})
}
+11 -5
View File
@@ -57,9 +57,7 @@ func TestPatchCancelWorkspaceBuild(t *testing.T) {
var err error
build, err = client.WorkspaceBuild(context.Background(), build.ID)
require.NoError(t, err)
// The echo provisioner doesn't respond to a shutdown request,
// so the job cancel will time out and fail.
return build.Job.Status == codersdk.ProvisionerJobFailed
return build.Job.Status == codersdk.ProvisionerJobCanceled
}, 5*time.Second, 25*time.Millisecond)
}
@@ -159,6 +157,14 @@ func TestWorkspaceBuildLogs(t *testing.T) {
t.Cleanup(cancelFunc)
logs, err := client.WorkspaceBuildLogsAfter(ctx, workspace.LatestBuild.ID, before)
require.NoError(t, err)
log := <-logs
require.Equal(t, "example", log.Output)
for {
log, ok := <-logs
if !ok {
break
}
if log.Output == "example" {
return
}
}
require.Fail(t, "example message never happened")
}