feat: persist app groups in the database (#17977)

This commit is contained in:
ケイラ
2025-05-27 13:13:08 -06:00
committed by GitHub
parent 513a468a3a
commit 9fc3329575
27 changed files with 398 additions and 322 deletions

3
coderd/apidoc/docs.go generated
View File

@ -17570,6 +17570,9 @@ const docTemplate = `{
"description": "External specifies whether the URL should be opened externally on\nthe client or not.",
"type": "boolean"
},
"group": {
"type": "string"
},
"health": {
"$ref": "#/definitions/codersdk.WorkspaceAppHealth"
},

View File

@ -16048,6 +16048,9 @@
"description": "External specifies whether the URL should be opened externally on\nthe client or not.",
"type": "boolean"
},
"group": {
"type": "string"
},
"health": {
"$ref": "#/definitions/codersdk.WorkspaceAppHealth"
},

View File

@ -525,6 +525,7 @@ func Apps(dbApps []database.WorkspaceApp, statuses []database.WorkspaceAppStatus
Threshold: dbApp.HealthcheckThreshold,
},
Health: codersdk.WorkspaceAppHealth(dbApp.Health),
Group: dbApp.DisplayGroup.String,
Hidden: dbApp.Hidden,
OpenIn: codersdk.WorkspaceAppOpenIn(dbApp.OpenIn),
Statuses: WorkspaceAppStatuses(statuses),

View File

@ -748,6 +748,7 @@ func WorkspaceApp(t testing.TB, db database.Store, orig database.WorkspaceApp) d
HealthcheckThreshold: takeFirst(orig.HealthcheckThreshold, 60),
Health: takeFirst(orig.Health, database.WorkspaceAppHealthHealthy),
DisplayOrder: takeFirst(orig.DisplayOrder, 1),
DisplayGroup: orig.DisplayGroup,
Hidden: orig.Hidden,
OpenIn: takeFirst(orig.OpenIn, database.WorkspaceAppOpenInSlimWindow),
})

View File

@ -1991,7 +1991,8 @@ CREATE TABLE workspace_apps (
external boolean DEFAULT false NOT NULL,
display_order integer DEFAULT 0 NOT NULL,
hidden boolean DEFAULT false NOT NULL,
open_in workspace_app_open_in DEFAULT 'slim-window'::workspace_app_open_in NOT NULL
open_in workspace_app_open_in DEFAULT 'slim-window'::workspace_app_open_in NOT NULL,
display_group text
);
COMMENT ON COLUMN workspace_apps.display_order IS 'Specifies the order in which to display agent app in user interfaces.';

View File

@ -0,0 +1 @@
alter table workspace_apps drop column display_group;

View File

@ -0,0 +1 @@
alter table workspace_apps add column display_group text;

View File

@ -3677,8 +3677,9 @@ type WorkspaceApp struct {
// Specifies the order in which to display agent app in user interfaces.
DisplayOrder int32 `db:"display_order" json:"display_order"`
// Determines if the app is not shown in user interfaces.
Hidden bool `db:"hidden" json:"hidden"`
OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
Hidden bool `db:"hidden" json:"hidden"`
OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
DisplayGroup sql.NullString `db:"display_group" json:"display_group"`
}
// Audit sessions for workspace apps, the data in this table is ephemeral and is used to deduplicate audit log entries for workspace apps. While a session is active, the same data will not be logged again. This table does not store historical data.

View File

@ -16218,7 +16218,7 @@ func (q *sqlQuerier) GetLatestWorkspaceAppStatusesByWorkspaceIDs(ctx context.Con
}
const getWorkspaceAppByAgentIDAndSlug = `-- name: GetWorkspaceAppByAgentIDAndSlug :one
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 AND slug = $2
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, display_group FROM workspace_apps WHERE agent_id = $1 AND slug = $2
`
type GetWorkspaceAppByAgentIDAndSlugParams struct {
@ -16248,6 +16248,7 @@ func (q *sqlQuerier) GetWorkspaceAppByAgentIDAndSlug(ctx context.Context, arg Ge
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
&i.DisplayGroup,
)
return i, err
}
@ -16289,7 +16290,7 @@ func (q *sqlQuerier) GetWorkspaceAppStatusesByAppIDs(ctx context.Context, ids []
}
const getWorkspaceAppsByAgentID = `-- name: GetWorkspaceAppsByAgentID :many
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, display_group FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid.UUID) ([]WorkspaceApp, error) {
@ -16320,6 +16321,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
&i.DisplayGroup,
); err != nil {
return nil, err
}
@ -16335,7 +16337,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid
}
const getWorkspaceAppsByAgentIDs = `-- name: GetWorkspaceAppsByAgentIDs :many
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = ANY($1 :: uuid [ ]) ORDER BY slug ASC
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, display_group FROM workspace_apps WHERE agent_id = ANY($1 :: uuid [ ]) ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceApp, error) {
@ -16366,6 +16368,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
&i.DisplayGroup,
); err != nil {
return nil, err
}
@ -16381,7 +16384,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.
}
const getWorkspaceAppsCreatedAfter = `-- name: GetWorkspaceAppsCreatedAfter :many
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, display_group FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceApp, error) {
@ -16412,6 +16415,7 @@ func (q *sqlQuerier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
&i.DisplayGroup,
); err != nil {
return nil, err
}
@ -16446,10 +16450,11 @@ INSERT INTO
health,
display_order,
hidden,
open_in
open_in,
display_group
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) RETURNING id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in, display_group
`
type InsertWorkspaceAppParams struct {
@ -16471,6 +16476,7 @@ type InsertWorkspaceAppParams struct {
DisplayOrder int32 `db:"display_order" json:"display_order"`
Hidden bool `db:"hidden" json:"hidden"`
OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
DisplayGroup sql.NullString `db:"display_group" json:"display_group"`
}
func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error) {
@ -16493,6 +16499,7 @@ func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspace
arg.DisplayOrder,
arg.Hidden,
arg.OpenIn,
arg.DisplayGroup,
)
var i WorkspaceApp
err := row.Scan(
@ -16514,6 +16521,7 @@ func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspace
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
&i.DisplayGroup,
)
return i, err
}

View File

@ -30,10 +30,11 @@ INSERT INTO
health,
display_order,
hidden,
open_in
open_in,
display_group
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) RETURNING *;
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RETURNING *;
-- name: UpdateWorkspaceAppHealthByID :exec
UPDATE

View File

@ -2419,6 +2419,11 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
sharingLevel = database.AppSharingLevelPublic
}
displayGroup := sql.NullString{
Valid: app.Group != "",
String: app.Group,
}
openIn := database.WorkspaceAppOpenInSlimWindow
switch app.OpenIn {
case sdkproto.AppOpenIn_TAB:
@ -2451,6 +2456,7 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
Health: health,
// #nosec G115 - Order represents a display order value that's always small and fits in int32
DisplayOrder: int32(app.Order),
DisplayGroup: displayGroup,
Hidden: app.Hidden,
OpenIn: openIn,
})