Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: notifications: report failed workspace builds#14571

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
mtojek merged 126 commits intomainfrom40-failure-summary
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
126 commits
Select commitHold shift + click to select a range
9d71a83
just the template
mtojekSep 5, 2024
7fc0b02
Bobby
mtojekSep 5, 2024
1ff2a24
golden
mtojekSep 5, 2024
15ede21
WIP
mtojekSep 5, 2024
380c81d
generator
mtojekSep 6, 2024
8aa1d9a
lock
mtojekSep 6, 2024
fcd6d61
notif data
mtojekSep 6, 2024
1a941f8
fix
mtojekSep 6, 2024
be24cbd
fixmes
mtojekSep 6, 2024
2fc383e
NoopEnqueuer
mtojekSep 6, 2024
96c4062
fixme helpers
mtojekSep 6, 2024
b89f484
Run generator
mtojekSep 6, 2024
c9f99c5
fix
mtojekSep 6, 2024
a4f4868
TODO
mtojekSep 6, 2024
630c024
naming
mtojekSep 6, 2024
9a414f0
fix lint
mtojekSep 6, 2024
aef1287
TODO
mtojekSep 9, 2024
f0f6df2
fix dbmock
mtojekSep 9, 2024
f4e34a7
WIP
mtojekSep 9, 2024
968bd24
TODOs
mtojekSep 9, 2024
e771c05
WIP
mtojekSep 10, 2024
33b1e99
fix
mtojekSep 10, 2024
f614080
WIP
mtojekSep 10, 2024
4d7a304
WIP
mtojekSep 10, 2024
d5c212e
WIP
mtojekSep 10, 2024
0ab35f1
WIP
mtojekSep 10, 2024
fc804bd
another WIP
mtojekSep 10, 2024
c25155d
WIP
mtojekSep 10, 2024
6eb6794
WIP
mtojekSep 10, 2024
0afbd56
WIP
mtojekSep 10, 2024
d0331af
before input data
mtojekSep 10, 2024
3d65010
Last TODO
mtojekSep 10, 2024
3490c57
WIP
mtojekSep 10, 2024
aafed7c
rebuild model
mtojekSep 10, 2024
78ecccf
Merge branch 'main' into 40-failure-summary
mtojekSep 10, 2024
2d0299a
WIP
mtojekSep 10, 2024
38a3a50
WIP
mtojekSep 10, 2024
4c65295
WIP
mtojekSep 10, 2024
ef51c9a
WIP
mtojekSep 10, 2024
007bad6
Fixed
mtojekSep 10, 2024
73bb5bd
dbauthz
mtojekSep 11, 2024
7a7bb85
fix
mtojekSep 11, 2024
e02d271
fix
mtojekSep 11, 2024
0b21a95
excluded
mtojekSep 11, 2024
34c44b5
makegen
mtojekSep 11, 2024
f63a06b
wIP
mtojekSep 11, 2024
3b60a27
fix
mtojekSep 11, 2024
774c4b0
fix
mtojekSep 11, 2024
5d56c4d
makegen
mtojekSep 11, 2024
e8214e9
dbmem
mtojekSep 11, 2024
6ba2c29
makegen
mtojekSep 11, 2024
2962735
last dbmem
mtojekSep 11, 2024
d48a8ba
fix
mtojekSep 11, 2024
0bf4748
fix
mtojekSep 11, 2024
29d4a15
fix
mtojekSep 11, 2024
a9580a5
wip
mtojekSep 11, 2024
cf4609d
fix
mtojekSep 11, 2024
8e8ab49
stub internal test
mtojekSep 12, 2024
afad1c1
WIP
mtojekSep 12, 2024
8b49d55
makegen
mtojekSep 12, 2024
87d40cb
WIP
mtojekSep 12, 2024
c352822
WIP: tests
mtojekSep 12, 2024
22b1482
cleanup
mtojekSep 12, 2024
44b1bba
InitialState_NoBuilds_NoReport
mtojekSep 12, 2024
121eef5
first semi test
mtojekSep 12, 2024
bc92fc4
fix: created_by
mtojekSep 12, 2024
ccc6803
fix: created_by tv
mtojekSep 12, 2024
f7826d6
fix: build number
mtojekSep 12, 2024
36644b2
expanding
mtojekSep 13, 2024
52aafac
fix: snapshot
mtojekSep 13, 2024
8909bb6
test done
mtojekSep 13, 2024
0cceede
more tests
mtojekSep 13, 2024
1f06b86
WIP
mtojekSep 13, 2024
a1c89ec
tests done
mtojekSep 13, 2024
34cc4c3
cleanup
mtojekSep 13, 2024
159e6c7
Merge branch 'main' into 40-failure-summary
mtojekSep 13, 2024
5911ca9
fix: LockIDNotificationsReportGenerator
mtojekSep 13, 2024
dda9bf5
Address Mathias' feedback
mtojekSep 16, 2024
15f83c0
makegen
mtojekSep 16, 2024
6306407
fmt
mtojekSep 16, 2024
e258035
more
mtojekSep 16, 2024
48da1cd
reports
mtojekSep 16, 2024
309c600
payload
mtojekSep 16, 2024
8211ee6
nil-omitted
mtojekSep 16, 2024
a8aea9f
failed-lock
mtojekSep 16, 2024
da6b0a3
xerrors
mtojekSep 16, 2024
4afc23b
c=0
mtojekSep 16, 2024
bf7737d
log-debug
mtojekSep 16, 2024
102a245
enqueue with data
mtojekSep 16, 2024
2c9fc46
remove logger
mtojekSep 16, 2024
cb7ca0e
makegen
mtojekSep 16, 2024
6582a48
sort
mtojekSep 16, 2024
c933511
makegen
mtojekSep 16, 2024
0cdf3ea
GetFailedWorkspaceBuildsByTemplateID
mtojekSep 16, 2024
6126e6b
usersByIDs
mtojekSep 16, 2024
1000a50
makegen
mtojekSep 16, 2024
314f080
fix
mtojekSep 16, 2024
498b89b
processedUsers
mtojekSep 17, 2024
f115973
comment
mtojekSep 17, 2024
01409ca
WIP
mtojekSep 17, 2024
832bf38
notifications
mtojekSep 17, 2024
4cacf4d
WIP
mtojekSep 17, 2024
f23e837
WIP
mtojekSep 17, 2024
359416c
notifications
mtojekSep 17, 2024
68ed60f
fmt
mtojekSep 17, 2024
fdad745
rephrase
mtojekSep 17, 2024
9ba4c04
WIP
mtojekSep 17, 2024
8f634a4
WIP
mtojekSep 17, 2024
5215c92
WIP
mtojekSep 17, 2024
2edc7d5
fix
mtojekSep 17, 2024
53f6c63
refactored
mtojekSep 17, 2024
6405f3c
WIP
mtojekSep 17, 2024
d96a34a
refactored
mtojekSep 17, 2024
06a79f4
adjust tests
mtojekSep 17, 2024
3e60198
Merge branch 'main' into 40-failure-summary
mtojekSep 17, 2024
0a05a40
duplicate migration
mtojekSep 17, 2024
65cf4a8
dbauthz
mtojekSep 17, 2024
898856d
fix
mtojekSep 17, 2024
a5e42da
makegen
mtojekSep 17, 2024
72724b3
fix
mtojekSep 17, 2024
20abd69
fix: migration down
mtojekSep 17, 2024
b2df714
xerrors.Is
mtojekSep 17, 2024
65992f6
limit builds
mtojekSep 17, 2024
af67873
context cancelled
mtojekSep 17, 2024
6436489
Merge branch 'main' into 40-failure-summary
mtojekSep 18, 2024
6bd772c
fix migration
mtojekSep 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletionscli/server.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -56,6 +56,7 @@ import (
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/coder/v2/coderd/entitlements"
"github.com/coder/coder/v2/coderd/notifications/reports"
"github.com/coder/coder/v2/coderd/runtimeconfig"
"github.com/coder/pretty"
"github.com/coder/quartz"
Expand DownExpand Up@@ -1018,6 +1019,10 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.

// nolint:gocritic // TODO: create own role.
notificationsManager.Run(dbauthz.AsSystemRestricted(ctx))

// Run report generator to distribute periodic reports.
notificationReportGenerator := reports.NewReportGenerator(ctx, logger, options.Database, options.NotificationsEnqueuer, quartz.NewReal())
defer notificationReportGenerator.Close()
}

// Wrap the server in middleware that redirects to the access URL if
Expand Down
28 changes: 28 additions & 0 deletionscoderd/database/dbauthz/dbauthz.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1459,6 +1459,13 @@ func (q *querier) GetExternalAuthLinksByUserID(ctx context.Context, userID uuid.
return fetchWithPostFilter(q.auth, policy.ActionReadPersonal, q.db.GetExternalAuthLinksByUserID)(ctx, userID)
}

func (q *querier) GetFailedWorkspaceBuildsByTemplateID(ctx context.Context, arg database.GetFailedWorkspaceBuildsByTemplateIDParams) ([]database.GetFailedWorkspaceBuildsByTemplateIDRow, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
return nil, err
}
return q.db.GetFailedWorkspaceBuildsByTemplateID(ctx, arg)
}

func (q *querier) GetFileByHashAndCreator(ctx context.Context, arg database.GetFileByHashAndCreatorParams) (database.File, error) {
file, err := q.db.GetFileByHashAndCreator(ctx, arg)
if err != nil {
Expand DownExpand Up@@ -1628,6 +1635,13 @@ func (q *querier) GetNotificationMessagesByStatus(ctx context.Context, arg datab
return q.db.GetNotificationMessagesByStatus(ctx, arg)
}

func (q *querier) GetNotificationReportGeneratorLogByTemplate(ctx context.Context, arg uuid.UUID) (database.NotificationReportGeneratorLog, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
return database.NotificationReportGeneratorLog{}, err
}
return q.db.GetNotificationReportGeneratorLogByTemplate(ctx, arg)
}

func (q *querier) GetNotificationTemplateByID(ctx context.Context, id uuid.UUID) (database.NotificationTemplate, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceNotificationTemplate); err != nil {
return database.NotificationTemplate{}, err
Expand DownExpand Up@@ -2510,6 +2524,13 @@ func (q *querier) GetWorkspaceBuildParameters(ctx context.Context, workspaceBuil
return q.db.GetWorkspaceBuildParameters(ctx, workspaceBuildID)
}

func (q *querier) GetWorkspaceBuildStatsByTemplates(ctx context.Context, since time.Time) ([]database.GetWorkspaceBuildStatsByTemplatesRow, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil {
return nil, err
}
return q.db.GetWorkspaceBuildStatsByTemplates(ctx, since)
}

func (q *querier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg database.GetWorkspaceBuildsByWorkspaceIDParams) ([]database.WorkspaceBuild, error) {
if _, err := q.GetWorkspaceByID(ctx, arg.WorkspaceID); err != nil {
return nil, err
Expand DownExpand Up@@ -3966,6 +3987,13 @@ func (q *querier) UpsertLogoURL(ctx context.Context, value string) error {
return q.db.UpsertLogoURL(ctx, value)
}

func (q *querier) UpsertNotificationReportGeneratorLog(ctx context.Context, arg database.UpsertNotificationReportGeneratorLogParams) error {
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil {
return err
}
return q.db.UpsertNotificationReportGeneratorLog(ctx, arg)
}

func (q *querier) UpsertNotificationsSettings(ctx context.Context, value string) error {
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceDeploymentConfig); err != nil {
return err
Expand Down
22 changes: 22 additions & 0 deletionscoderd/database/dbauthz/dbauthz_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2819,6 +2819,28 @@ func (s *MethodTestSuite) TestSystemFunctions() {
Value: "value",
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
}))
s.Run("GetFailedWorkspaceBuildsByTemplateID", s.Subtest(func(db database.Store, check *expects) {
check.Args(database.GetFailedWorkspaceBuildsByTemplateIDParams{
TemplateID: uuid.New(),
Since: dbtime.Now(),
}).Asserts(rbac.ResourceSystem, policy.ActionRead)
}))
s.Run("GetNotificationReportGeneratorLogByTemplate", s.Subtest(func(db database.Store, check *expects) {
_ = db.UpsertNotificationReportGeneratorLog(context.Background(), database.UpsertNotificationReportGeneratorLogParams{
NotificationTemplateID: notifications.TemplateWorkspaceBuildsFailedReport,
LastGeneratedAt: dbtime.Now(),
})
check.Args(notifications.TemplateWorkspaceBuildsFailedReport).Asserts(rbac.ResourceSystem, policy.ActionRead)
}))
s.Run("GetWorkspaceBuildStatsByTemplates", s.Subtest(func(db database.Store, check *expects) {
check.Args(dbtime.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead)
}))
s.Run("UpsertNotificationReportGeneratorLog", s.Subtest(func(db database.Store, check *expects) {
check.Args(database.UpsertNotificationReportGeneratorLogParams{
NotificationTemplateID: uuid.New(),
LastGeneratedAt: dbtime.Now(),
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
}))
}

func (s *MethodTestSuite) TestNotifications() {
Expand Down
258 changes: 211 additions & 47 deletionscoderd/database/dbmem/dbmem.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -187,53 +187,54 @@ type data struct {
userLinks []database.UserLink

// New tables
workspaceAgentStats []database.WorkspaceAgentStat
auditLogs []database.AuditLog
cryptoKeys []database.CryptoKey
dbcryptKeys []database.DBCryptKey
files []database.File
externalAuthLinks []database.ExternalAuthLink
gitSSHKey []database.GitSSHKey
groupMembers []database.GroupMemberTable
groups []database.Group
jfrogXRayScans []database.JfrogXrayScan
licenses []database.License
notificationMessages []database.NotificationMessage
notificationPreferences []database.NotificationPreference
oauth2ProviderApps []database.OAuth2ProviderApp
oauth2ProviderAppSecrets []database.OAuth2ProviderAppSecret
oauth2ProviderAppCodes []database.OAuth2ProviderAppCode
oauth2ProviderAppTokens []database.OAuth2ProviderAppToken
parameterSchemas []database.ParameterSchema
provisionerDaemons []database.ProvisionerDaemon
provisionerJobLogs []database.ProvisionerJobLog
provisionerJobs []database.ProvisionerJob
provisionerKeys []database.ProvisionerKey
replicas []database.Replica
templateVersions []database.TemplateVersionTable
templateVersionParameters []database.TemplateVersionParameter
templateVersionVariables []database.TemplateVersionVariable
templateVersionWorkspaceTags []database.TemplateVersionWorkspaceTag
templates []database.TemplateTable
templateUsageStats []database.TemplateUsageStat
workspaceAgents []database.WorkspaceAgent
workspaceAgentMetadata []database.WorkspaceAgentMetadatum
workspaceAgentLogs []database.WorkspaceAgentLog
workspaceAgentLogSources []database.WorkspaceAgentLogSource
workspaceAgentScripts []database.WorkspaceAgentScript
workspaceAgentPortShares []database.WorkspaceAgentPortShare
workspaceApps []database.WorkspaceApp
workspaceAppStatsLastInsertID int64
workspaceAppStats []database.WorkspaceAppStat
workspaceBuilds []database.WorkspaceBuild
workspaceBuildParameters []database.WorkspaceBuildParameter
workspaceResourceMetadata []database.WorkspaceResourceMetadatum
workspaceResources []database.WorkspaceResource
workspaces []database.Workspace
workspaceProxies []database.WorkspaceProxy
customRoles []database.CustomRole
provisionerJobTimings []database.ProvisionerJobTiming
runtimeConfig map[string]string
auditLogs []database.AuditLog
cryptoKeys []database.CryptoKey
dbcryptKeys []database.DBCryptKey
files []database.File
externalAuthLinks []database.ExternalAuthLink
gitSSHKey []database.GitSSHKey
groupMembers []database.GroupMemberTable
groups []database.Group
jfrogXRayScans []database.JfrogXrayScan
licenses []database.License
notificationMessages []database.NotificationMessage
notificationPreferences []database.NotificationPreference
notificationReportGeneratorLogs []database.NotificationReportGeneratorLog
oauth2ProviderApps []database.OAuth2ProviderApp
oauth2ProviderAppSecrets []database.OAuth2ProviderAppSecret
oauth2ProviderAppCodes []database.OAuth2ProviderAppCode
oauth2ProviderAppTokens []database.OAuth2ProviderAppToken
parameterSchemas []database.ParameterSchema
provisionerDaemons []database.ProvisionerDaemon
provisionerJobLogs []database.ProvisionerJobLog
provisionerJobs []database.ProvisionerJob
provisionerKeys []database.ProvisionerKey
replicas []database.Replica
templateVersions []database.TemplateVersionTable
templateVersionParameters []database.TemplateVersionParameter
templateVersionVariables []database.TemplateVersionVariable
templateVersionWorkspaceTags []database.TemplateVersionWorkspaceTag
templates []database.TemplateTable
templateUsageStats []database.TemplateUsageStat
workspaceAgents []database.WorkspaceAgent
workspaceAgentMetadata []database.WorkspaceAgentMetadatum
workspaceAgentLogs []database.WorkspaceAgentLog
workspaceAgentLogSources []database.WorkspaceAgentLogSource
workspaceAgentPortShares []database.WorkspaceAgentPortShare
workspaceAgentScripts []database.WorkspaceAgentScript
workspaceAgentStats []database.WorkspaceAgentStat
workspaceApps []database.WorkspaceApp
workspaceAppStatsLastInsertID int64
workspaceAppStats []database.WorkspaceAppStat
workspaceBuilds []database.WorkspaceBuild
workspaceBuildParameters []database.WorkspaceBuildParameter
workspaceResourceMetadata []database.WorkspaceResourceMetadatum
workspaceResources []database.WorkspaceResource
workspaces []database.Workspace
workspaceProxies []database.WorkspaceProxy
customRoles []database.CustomRole
provisionerJobTimings []database.ProvisionerJobTiming
runtimeConfig map[string]string
// Locks is a map of lock names. Any keys within the map are currently
// locked.
locks map[int64]struct{}
Expand DownExpand Up@@ -2621,6 +2622,75 @@ func (q *FakeQuerier) GetExternalAuthLinksByUserID(_ context.Context, userID uui
return gals, nil
}

func (q *FakeQuerier) GetFailedWorkspaceBuildsByTemplateID(ctx context.Context, arg database.GetFailedWorkspaceBuildsByTemplateIDParams) ([]database.GetFailedWorkspaceBuildsByTemplateIDRow, error) {
err := validateDatabaseType(arg)
if err != nil {
return nil, err
}

q.mutex.RLock()
defer q.mutex.RUnlock()

workspaceBuildStats := []database.GetFailedWorkspaceBuildsByTemplateIDRow{}
for _, wb := range q.workspaceBuilds {
job, err := q.getProvisionerJobByIDNoLock(ctx, wb.JobID)
if err != nil {
return nil, xerrors.Errorf("get provisioner job by ID: %w", err)
}

if job.JobStatus != database.ProvisionerJobStatusFailed {
continue
}

if !job.CompletedAt.Valid {
continue
}

if wb.CreatedAt.Before(arg.Since) {
continue
}

w, err := q.getWorkspaceByIDNoLock(ctx, wb.WorkspaceID)
if err != nil {
return nil, xerrors.Errorf("get workspace by ID: %w", err)
}

t, err := q.getTemplateByIDNoLock(ctx, w.TemplateID)
if err != nil {
return nil, xerrors.Errorf("get template by ID: %w", err)
}

if t.ID != arg.TemplateID {
continue
}

workspaceOwner, err := q.getUserByIDNoLock(w.OwnerID)
if err != nil {
return nil, xerrors.Errorf("get user by ID: %w", err)
}

templateVersion, err := q.getTemplateVersionByIDNoLock(ctx, wb.TemplateVersionID)
if err != nil {
return nil, xerrors.Errorf("get template version by ID: %w", err)
}

workspaceBuildStats = append(workspaceBuildStats, database.GetFailedWorkspaceBuildsByTemplateIDRow{
WorkspaceName: w.Name,
WorkspaceOwnerUsername: workspaceOwner.Username,
TemplateVersionName: templateVersion.Name,
WorkspaceBuildNumber: wb.BuildNumber,
})
}

sort.Slice(workspaceBuildStats, func(i, j int) bool {
if workspaceBuildStats[i].TemplateVersionName != workspaceBuildStats[j].TemplateVersionName {
return workspaceBuildStats[i].TemplateVersionName < workspaceBuildStats[j].TemplateVersionName
}
return workspaceBuildStats[i].WorkspaceBuildNumber > workspaceBuildStats[j].WorkspaceBuildNumber
})
return workspaceBuildStats, nil
}

func (q *FakeQuerier) GetFileByHashAndCreator(_ context.Context, arg database.GetFileByHashAndCreatorParams) (database.File, error) {
if err := validateDatabaseType(arg); err != nil {
return database.File{}, err
Expand DownExpand Up@@ -3044,6 +3114,23 @@ func (q *FakeQuerier) GetNotificationMessagesByStatus(_ context.Context, arg dat
return out, nil
}

func (q *FakeQuerier) GetNotificationReportGeneratorLogByTemplate(_ context.Context, templateID uuid.UUID) (database.NotificationReportGeneratorLog, error) {
err := validateDatabaseType(templateID)
if err != nil {
return database.NotificationReportGeneratorLog{}, err
}

q.mutex.RLock()
defer q.mutex.RUnlock()

for _, record := range q.notificationReportGeneratorLogs {
if record.NotificationTemplateID == templateID {
return record, nil
}
}
return database.NotificationReportGeneratorLog{}, sql.ErrNoRows
}

func (*FakeQuerier) GetNotificationTemplateByID(_ context.Context, _ uuid.UUID) (database.NotificationTemplate, error) {
// Not implementing this function because it relies on state in the database which is created with migrations.
// We could consider using code-generation to align the database state and dbmem, but it's not worth it right now.
Expand DownExpand Up@@ -5964,6 +6051,63 @@ func (q *FakeQuerier) GetWorkspaceBuildParameters(_ context.Context, workspaceBu
return params, nil
}

func (q *FakeQuerier) GetWorkspaceBuildStatsByTemplates(ctx context.Context, since time.Time) ([]database.GetWorkspaceBuildStatsByTemplatesRow, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

templateStats := map[uuid.UUID]database.GetWorkspaceBuildStatsByTemplatesRow{}
for _, wb := range q.workspaceBuilds {
job, err := q.getProvisionerJobByIDNoLock(ctx, wb.JobID)
if err != nil {
return nil, xerrors.Errorf("get provisioner job by ID: %w", err)
}

if !job.CompletedAt.Valid {
continue
}

if wb.CreatedAt.Before(since) {
continue
}

w, err := q.getWorkspaceByIDNoLock(ctx, wb.WorkspaceID)
if err != nil {
return nil, xerrors.Errorf("get workspace by ID: %w", err)
}

if _, ok := templateStats[w.TemplateID]; !ok {
t, err := q.getTemplateByIDNoLock(ctx, w.TemplateID)
if err != nil {
return nil, xerrors.Errorf("get template by ID: %w", err)
}

templateStats[w.TemplateID] = database.GetWorkspaceBuildStatsByTemplatesRow{
TemplateID: w.TemplateID,
TemplateName: t.Name,
TemplateDisplayName: t.DisplayName,
TemplateOrganizationID: w.OrganizationID,
}
}

s := templateStats[w.TemplateID]
s.TotalBuilds++
if job.JobStatus == database.ProvisionerJobStatusFailed {
s.FailedBuilds++
}
templateStats[w.TemplateID] = s
}

rows := make([]database.GetWorkspaceBuildStatsByTemplatesRow, 0, len(templateStats))
for _, ts := range templateStats {
rows = append(rows, ts)
}

sort.Slice(rows, func(i, j int) bool {
return rows[i].TemplateName < rows[j].TemplateName
})
return rows, nil
}

func (q *FakeQuerier) GetWorkspaceBuildsByWorkspaceID(_ context.Context,
params database.GetWorkspaceBuildsByWorkspaceIDParams,
) ([]database.WorkspaceBuild, error) {
Expand DownExpand Up@@ -9440,6 +9584,26 @@ func (q *FakeQuerier) UpsertLogoURL(_ context.Context, data string) error {
return nil
}

func (q *FakeQuerier) UpsertNotificationReportGeneratorLog(_ context.Context, arg database.UpsertNotificationReportGeneratorLogParams) error {
err := validateDatabaseType(arg)
if err != nil {
return err
}

q.mutex.Lock()
defer q.mutex.Unlock()

for i, record := range q.notificationReportGeneratorLogs {
if arg.NotificationTemplateID == record.NotificationTemplateID {
q.notificationReportGeneratorLogs[i].LastGeneratedAt = arg.LastGeneratedAt
return nil
}
}

q.notificationReportGeneratorLogs = append(q.notificationReportGeneratorLogs, database.NotificationReportGeneratorLog(arg))
return nil
}

func (q *FakeQuerier) UpsertNotificationsSettings(_ context.Context, data string) error {
q.mutex.Lock()
defer q.mutex.Unlock()
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp