mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
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:
@@ -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
|
||||
|
||||
Generated
+1
@@ -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
|
||||
);
|
||||
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user