feat(coderd): add has_external_agent flag to template_versions and workspace_builds (#19285)

This pull request introduces support for external workspace management, allowing users to register and manage workspaces that are provisioned and managed outside of the Coder.

* Added has_external_agent field to workspace builds and template versions
This commit is contained in:
Kacper Sawicki
2025-08-19 10:29:51 +02:00
committed by GitHub
parent e67f0f6f52
commit 5e4aa79a9d
19 changed files with 522 additions and 267 deletions
+40 -40
View File
@@ -4733,28 +4733,6 @@ func (q *querier) UpdateTemplateScheduleByID(ctx context.Context, arg database.U
return update(q.log, q.auth, fetch, q.db.UpdateTemplateScheduleByID)(ctx, arg)
}
func (q *querier) UpdateTemplateVersionAITaskByJobID(ctx context.Context, arg database.UpdateTemplateVersionAITaskByJobIDParams) error {
// An actor is allowed to update the template version AI task flag if they are authorized to update the template.
tv, err := q.db.GetTemplateVersionByJobID(ctx, arg.JobID)
if err != nil {
return err
}
var obj rbac.Objecter
if !tv.TemplateID.Valid {
obj = rbac.ResourceTemplate.InOrg(tv.OrganizationID)
} else {
tpl, err := q.db.GetTemplateByID(ctx, tv.TemplateID.UUID)
if err != nil {
return err
}
obj = tpl
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, obj); err != nil {
return err
}
return q.db.UpdateTemplateVersionAITaskByJobID(ctx, arg)
}
func (q *querier) UpdateTemplateVersionByID(ctx context.Context, arg database.UpdateTemplateVersionByIDParams) error {
// An actor is allowed to update the template version if they are authorized to update the template.
tv, err := q.db.GetTemplateVersionByID(ctx, arg.ID)
@@ -4821,6 +4799,28 @@ func (q *querier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context.
return q.db.UpdateTemplateVersionExternalAuthProvidersByJobID(ctx, arg)
}
func (q *querier) UpdateTemplateVersionFlagsByJobID(ctx context.Context, arg database.UpdateTemplateVersionFlagsByJobIDParams) error {
// An actor is allowed to update the template version ai task and external agent flag if they are authorized to update the template.
tv, err := q.db.GetTemplateVersionByJobID(ctx, arg.JobID)
if err != nil {
return err
}
var obj rbac.Objecter
if !tv.TemplateID.Valid {
obj = rbac.ResourceTemplate.InOrg(tv.OrganizationID)
} else {
tpl, err := q.db.GetTemplateByID(ctx, tv.TemplateID.UUID)
if err != nil {
return err
}
obj = tpl
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, obj); err != nil {
return err
}
return q.db.UpdateTemplateVersionFlagsByJobID(ctx, arg)
}
func (q *querier) UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg database.UpdateTemplateWorkspacesLastUsedAtParams) error {
fetch := func(ctx context.Context, arg database.UpdateTemplateWorkspacesLastUsedAtParams) (database.Template, error) {
return q.db.GetTemplateByID(ctx, arg.TemplateID)
@@ -5143,24 +5143,6 @@ func (q *querier) UpdateWorkspaceAutostart(ctx context.Context, arg database.Upd
return update(q.log, q.auth, fetch, q.db.UpdateWorkspaceAutostart)(ctx, arg)
}
func (q *querier) UpdateWorkspaceBuildAITaskByID(ctx context.Context, arg database.UpdateWorkspaceBuildAITaskByIDParams) error {
build, err := q.db.GetWorkspaceBuildByID(ctx, arg.ID)
if err != nil {
return err
}
workspace, err := q.db.GetWorkspaceByID(ctx, build.WorkspaceID)
if err != nil {
return err
}
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.RBACObject())
if err != nil {
return err
}
return q.db.UpdateWorkspaceBuildAITaskByID(ctx, arg)
}
// UpdateWorkspaceBuildCostByID is used by the provisioning system to update the cost of a workspace build.
func (q *querier) UpdateWorkspaceBuildCostByID(ctx context.Context, arg database.UpdateWorkspaceBuildCostByIDParams) error {
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
@@ -5187,6 +5169,24 @@ func (q *querier) UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg data
return q.db.UpdateWorkspaceBuildDeadlineByID(ctx, arg)
}
func (q *querier) UpdateWorkspaceBuildFlagsByID(ctx context.Context, arg database.UpdateWorkspaceBuildFlagsByIDParams) error {
build, err := q.db.GetWorkspaceBuildByID(ctx, arg.ID)
if err != nil {
return err
}
workspace, err := q.db.GetWorkspaceByID(ctx, build.WorkspaceID)
if err != nil {
return err
}
err = q.authorizeContext(ctx, policy.ActionUpdate, workspace.RBACObject())
if err != nil {
return err
}
return q.db.UpdateWorkspaceBuildFlagsByID(ctx, arg)
}
func (q *querier) UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg database.UpdateWorkspaceBuildProvisionerStateByIDParams) error {
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceSystem); err != nil {
return err
+24 -18
View File
@@ -1355,13 +1355,13 @@ func (s *MethodTestSuite) TestTemplate() {
dbm.EXPECT().UpdateTemplateScheduleByID(gomock.Any(), arg).Return(nil).AnyTimes()
check.Args(arg).Asserts(t1, policy.ActionUpdate)
}))
s.Run("UpdateTemplateVersionAITaskByJobID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
s.Run("UpdateTemplateVersionFlagsByJobID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
t := testutil.Fake(s.T(), faker, database.Template{})
tv := testutil.Fake(s.T(), faker, database.TemplateVersion{TemplateID: uuid.NullUUID{UUID: t.ID, Valid: true}})
arg := database.UpdateTemplateVersionAITaskByJobIDParams{JobID: tv.JobID, HasAITask: sql.NullBool{Bool: true, Valid: true}}
arg := database.UpdateTemplateVersionFlagsByJobIDParams{JobID: tv.JobID, HasAITask: sql.NullBool{Bool: true, Valid: true}, HasExternalAgent: sql.NullBool{Bool: true, Valid: true}}
dbm.EXPECT().GetTemplateVersionByJobID(gomock.Any(), tv.JobID).Return(tv, nil).AnyTimes()
dbm.EXPECT().GetTemplateByID(gomock.Any(), t.ID).Return(t, nil).AnyTimes()
dbm.EXPECT().UpdateTemplateVersionAITaskByJobID(gomock.Any(), arg).Return(nil).AnyTimes()
dbm.EXPECT().UpdateTemplateVersionFlagsByJobID(gomock.Any(), arg).Return(nil).AnyTimes()
check.Args(arg).Asserts(t, policy.ActionUpdate)
}))
s.Run("UpdateTemplateWorkspacesLastUsedAt", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
@@ -2955,38 +2955,44 @@ func (s *MethodTestSuite) TestWorkspace() {
Deadline: b.Deadline,
}).Asserts(w, policy.ActionUpdate)
}))
s.Run("UpdateWorkspaceBuildAITaskByID", s.Subtest(func(db database.Store, check *expects) {
u := dbgen.User(s.T(), db, database.User{})
o := dbgen.Organization(s.T(), db, database.Organization{})
tpl := dbgen.Template(s.T(), db, database.Template{
s.Run("UpdateWorkspaceBuildFlagsByID", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
u := testutil.Fake(s.T(), faker, database.User{})
o := testutil.Fake(s.T(), faker, database.Organization{})
tpl := testutil.Fake(s.T(), faker, database.Template{
OrganizationID: o.ID,
CreatedBy: u.ID,
})
tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{
tv := testutil.Fake(s.T(), faker, database.TemplateVersion{
TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true},
OrganizationID: o.ID,
CreatedBy: u.ID,
})
w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{
w := testutil.Fake(s.T(), faker, database.Workspace{
TemplateID: tpl.ID,
OrganizationID: o.ID,
OwnerID: u.ID,
})
j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{
j := testutil.Fake(s.T(), faker, database.ProvisionerJob{
Type: database.ProvisionerJobTypeWorkspaceBuild,
})
b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{
b := testutil.Fake(s.T(), faker, database.WorkspaceBuild{
JobID: j.ID,
WorkspaceID: w.ID,
TemplateVersionID: tv.ID,
})
res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID})
agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID})
app := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: agt.ID})
check.Args(database.UpdateWorkspaceBuildAITaskByIDParams{
HasAITask: sql.NullBool{Bool: true, Valid: true},
SidebarAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
ID: b.ID,
res := testutil.Fake(s.T(), faker, database.WorkspaceResource{JobID: b.JobID})
agt := testutil.Fake(s.T(), faker, database.WorkspaceAgent{ResourceID: res.ID})
app := testutil.Fake(s.T(), faker, database.WorkspaceApp{AgentID: agt.ID})
dbm.EXPECT().GetWorkspaceByID(gomock.Any(), w.ID).Return(w, nil).AnyTimes()
dbm.EXPECT().GetWorkspaceBuildByID(gomock.Any(), b.ID).Return(b, nil).AnyTimes()
dbm.EXPECT().UpdateWorkspaceBuildFlagsByID(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
check.Args(database.UpdateWorkspaceBuildFlagsByIDParams{
ID: b.ID,
HasAITask: sql.NullBool{Bool: true, Valid: true},
HasExternalAgent: sql.NullBool{Bool: true, Valid: true},
SidebarAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
UpdatedAt: b.UpdatedAt,
}).Asserts(w, policy.ActionUpdate)
}))
s.Run("SoftDeleteWorkspaceByID", s.Subtest(func(db database.Store, check *expects) {
+15 -11
View File
@@ -437,6 +437,7 @@ func WorkspaceBuild(t testing.TB, db database.Store, orig database.WorkspaceBuil
jobID := takeFirst(orig.JobID, uuid.New())
hasAITask := takeFirst(orig.HasAITask, sql.NullBool{})
sidebarAppID := takeFirst(orig.AITaskSidebarAppID, uuid.NullUUID{})
hasExternalAgent := takeFirst(orig.HasExternalAgent, sql.NullBool{})
var build database.WorkspaceBuild
err := db.InTx(func(db database.Store) error {
err := db.InsertWorkspaceBuild(genCtx, database.InsertWorkspaceBuildParams{
@@ -470,12 +471,13 @@ func WorkspaceBuild(t testing.TB, db database.Store, orig database.WorkspaceBuil
require.NoError(t, err)
}
if hasAITask.Valid {
require.NoError(t, db.UpdateWorkspaceBuildAITaskByID(genCtx, database.UpdateWorkspaceBuildAITaskByIDParams{
HasAITask: hasAITask,
SidebarAppID: sidebarAppID,
UpdatedAt: dbtime.Now(),
ID: buildID,
if hasAITask.Valid || hasExternalAgent.Valid {
require.NoError(t, db.UpdateWorkspaceBuildFlagsByID(genCtx, database.UpdateWorkspaceBuildFlagsByIDParams{
ID: buildID,
HasAITask: hasAITask,
HasExternalAgent: hasExternalAgent,
SidebarAppID: sidebarAppID,
UpdatedAt: dbtime.Now(),
}))
}
@@ -1028,6 +1030,7 @@ func ExternalAuthLink(t testing.TB, db database.Store, orig database.ExternalAut
func TemplateVersion(t testing.TB, db database.Store, orig database.TemplateVersion) database.TemplateVersion {
var version database.TemplateVersion
hasAITask := takeFirst(orig.HasAITask, sql.NullBool{})
hasExternalAgent := takeFirst(orig.HasExternalAgent, sql.NullBool{})
jobID := takeFirst(orig.JobID, uuid.New())
err := db.InTx(func(db database.Store) error {
versionID := takeFirst(orig.ID, uuid.New())
@@ -1048,11 +1051,12 @@ func TemplateVersion(t testing.TB, db database.Store, orig database.TemplateVers
return err
}
if hasAITask.Valid {
require.NoError(t, db.UpdateTemplateVersionAITaskByJobID(genCtx, database.UpdateTemplateVersionAITaskByJobIDParams{
JobID: jobID,
HasAITask: hasAITask,
UpdatedAt: dbtime.Now(),
if hasAITask.Valid || hasExternalAgent.Valid {
require.NoError(t, db.UpdateTemplateVersionFlagsByJobID(genCtx, database.UpdateTemplateVersionFlagsByJobIDParams{
JobID: jobID,
HasAITask: hasAITask,
HasExternalAgent: hasExternalAgent,
UpdatedAt: dbtime.Now(),
}))
}
+14 -14
View File
@@ -2917,13 +2917,6 @@ func (m queryMetricsStore) UpdateTemplateScheduleByID(ctx context.Context, arg d
return err
}
func (m queryMetricsStore) UpdateTemplateVersionAITaskByJobID(ctx context.Context, arg database.UpdateTemplateVersionAITaskByJobIDParams) error {
start := time.Now()
r0 := m.s.UpdateTemplateVersionAITaskByJobID(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateTemplateVersionAITaskByJobID").Observe(time.Since(start).Seconds())
return r0
}
func (m queryMetricsStore) UpdateTemplateVersionByID(ctx context.Context, arg database.UpdateTemplateVersionByIDParams) error {
start := time.Now()
err := m.s.UpdateTemplateVersionByID(ctx, arg)
@@ -2945,6 +2938,13 @@ func (m queryMetricsStore) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx
return err
}
func (m queryMetricsStore) UpdateTemplateVersionFlagsByJobID(ctx context.Context, arg database.UpdateTemplateVersionFlagsByJobIDParams) error {
start := time.Now()
r0 := m.s.UpdateTemplateVersionFlagsByJobID(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateTemplateVersionFlagsByJobID").Observe(time.Since(start).Seconds())
return r0
}
func (m queryMetricsStore) UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg database.UpdateTemplateWorkspacesLastUsedAtParams) error {
start := time.Now()
r0 := m.s.UpdateTemplateWorkspacesLastUsedAt(ctx, arg)
@@ -3148,13 +3148,6 @@ func (m queryMetricsStore) UpdateWorkspaceAutostart(ctx context.Context, arg dat
return err
}
func (m queryMetricsStore) UpdateWorkspaceBuildAITaskByID(ctx context.Context, arg database.UpdateWorkspaceBuildAITaskByIDParams) error {
start := time.Now()
r0 := m.s.UpdateWorkspaceBuildAITaskByID(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspaceBuildAITaskByID").Observe(time.Since(start).Seconds())
return r0
}
func (m queryMetricsStore) UpdateWorkspaceBuildCostByID(ctx context.Context, arg database.UpdateWorkspaceBuildCostByIDParams) error {
start := time.Now()
err := m.s.UpdateWorkspaceBuildCostByID(ctx, arg)
@@ -3169,6 +3162,13 @@ func (m queryMetricsStore) UpdateWorkspaceBuildDeadlineByID(ctx context.Context,
return r0
}
func (m queryMetricsStore) UpdateWorkspaceBuildFlagsByID(ctx context.Context, arg database.UpdateWorkspaceBuildFlagsByIDParams) error {
start := time.Now()
r0 := m.s.UpdateWorkspaceBuildFlagsByID(ctx, arg)
m.queryLatencies.WithLabelValues("UpdateWorkspaceBuildFlagsByID").Observe(time.Since(start).Seconds())
return r0
}
func (m queryMetricsStore) UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg database.UpdateWorkspaceBuildProvisionerStateByIDParams) error {
start := time.Now()
r0 := m.s.UpdateWorkspaceBuildProvisionerStateByID(ctx, arg)
+28 -28
View File
@@ -6229,20 +6229,6 @@ func (mr *MockStoreMockRecorder) UpdateTemplateScheduleByID(ctx, arg any) *gomoc
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTemplateScheduleByID", reflect.TypeOf((*MockStore)(nil).UpdateTemplateScheduleByID), ctx, arg)
}
// UpdateTemplateVersionAITaskByJobID mocks base method.
func (m *MockStore) UpdateTemplateVersionAITaskByJobID(ctx context.Context, arg database.UpdateTemplateVersionAITaskByJobIDParams) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateTemplateVersionAITaskByJobID", ctx, arg)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateTemplateVersionAITaskByJobID indicates an expected call of UpdateTemplateVersionAITaskByJobID.
func (mr *MockStoreMockRecorder) UpdateTemplateVersionAITaskByJobID(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTemplateVersionAITaskByJobID", reflect.TypeOf((*MockStore)(nil).UpdateTemplateVersionAITaskByJobID), ctx, arg)
}
// UpdateTemplateVersionByID mocks base method.
func (m *MockStore) UpdateTemplateVersionByID(ctx context.Context, arg database.UpdateTemplateVersionByIDParams) error {
m.ctrl.T.Helper()
@@ -6285,6 +6271,20 @@ func (mr *MockStoreMockRecorder) UpdateTemplateVersionExternalAuthProvidersByJob
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTemplateVersionExternalAuthProvidersByJobID", reflect.TypeOf((*MockStore)(nil).UpdateTemplateVersionExternalAuthProvidersByJobID), ctx, arg)
}
// UpdateTemplateVersionFlagsByJobID mocks base method.
func (m *MockStore) UpdateTemplateVersionFlagsByJobID(ctx context.Context, arg database.UpdateTemplateVersionFlagsByJobIDParams) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateTemplateVersionFlagsByJobID", ctx, arg)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateTemplateVersionFlagsByJobID indicates an expected call of UpdateTemplateVersionFlagsByJobID.
func (mr *MockStoreMockRecorder) UpdateTemplateVersionFlagsByJobID(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTemplateVersionFlagsByJobID", reflect.TypeOf((*MockStore)(nil).UpdateTemplateVersionFlagsByJobID), ctx, arg)
}
// UpdateTemplateWorkspacesLastUsedAt mocks base method.
func (m *MockStore) UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg database.UpdateTemplateWorkspacesLastUsedAtParams) error {
m.ctrl.T.Helper()
@@ -6704,20 +6704,6 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceAutostart(ctx, arg any) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWorkspaceAutostart", reflect.TypeOf((*MockStore)(nil).UpdateWorkspaceAutostart), ctx, arg)
}
// UpdateWorkspaceBuildAITaskByID mocks base method.
func (m *MockStore) UpdateWorkspaceBuildAITaskByID(ctx context.Context, arg database.UpdateWorkspaceBuildAITaskByIDParams) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateWorkspaceBuildAITaskByID", ctx, arg)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateWorkspaceBuildAITaskByID indicates an expected call of UpdateWorkspaceBuildAITaskByID.
func (mr *MockStoreMockRecorder) UpdateWorkspaceBuildAITaskByID(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWorkspaceBuildAITaskByID", reflect.TypeOf((*MockStore)(nil).UpdateWorkspaceBuildAITaskByID), ctx, arg)
}
// UpdateWorkspaceBuildCostByID mocks base method.
func (m *MockStore) UpdateWorkspaceBuildCostByID(ctx context.Context, arg database.UpdateWorkspaceBuildCostByIDParams) error {
m.ctrl.T.Helper()
@@ -6746,6 +6732,20 @@ func (mr *MockStoreMockRecorder) UpdateWorkspaceBuildDeadlineByID(ctx, arg any)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWorkspaceBuildDeadlineByID", reflect.TypeOf((*MockStore)(nil).UpdateWorkspaceBuildDeadlineByID), ctx, arg)
}
// UpdateWorkspaceBuildFlagsByID mocks base method.
func (m *MockStore) UpdateWorkspaceBuildFlagsByID(ctx context.Context, arg database.UpdateWorkspaceBuildFlagsByIDParams) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateWorkspaceBuildFlagsByID", ctx, arg)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateWorkspaceBuildFlagsByID indicates an expected call of UpdateWorkspaceBuildFlagsByID.
func (mr *MockStoreMockRecorder) UpdateWorkspaceBuildFlagsByID(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateWorkspaceBuildFlagsByID", reflect.TypeOf((*MockStore)(nil).UpdateWorkspaceBuildFlagsByID), ctx, arg)
}
// UpdateWorkspaceBuildProvisionerStateByID mocks base method.
func (m *MockStore) UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg database.UpdateWorkspaceBuildProvisionerStateByIDParams) error {
m.ctrl.T.Helper()
+5 -1
View File
@@ -1691,7 +1691,8 @@ CREATE TABLE template_versions (
message character varying(1048576) DEFAULT ''::character varying NOT NULL,
archived boolean DEFAULT false NOT NULL,
source_example_id text,
has_ai_task boolean
has_ai_task boolean,
has_external_agent boolean
);
COMMENT ON COLUMN template_versions.external_auth_providers IS 'IDs of External auth providers for a specific template version';
@@ -1722,6 +1723,7 @@ CREATE VIEW template_version_with_user AS
template_versions.archived,
template_versions.source_example_id,
template_versions.has_ai_task,
template_versions.has_external_agent,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username,
COALESCE(visible_users.name, ''::text) AS created_by_name
@@ -2264,6 +2266,7 @@ CREATE TABLE workspace_builds (
template_version_preset_id uuid,
has_ai_task boolean,
ai_task_sidebar_app_id uuid,
has_external_agent boolean,
CONSTRAINT workspace_builds_ai_task_sidebar_app_id_required CHECK (((((has_ai_task IS NULL) OR (has_ai_task = false)) AND (ai_task_sidebar_app_id IS NULL)) OR ((has_ai_task = true) AND (ai_task_sidebar_app_id IS NOT NULL)))),
CONSTRAINT workspace_builds_deadline_below_max_deadline CHECK ((((deadline <> '0001-01-01 00:00:00+00'::timestamp with time zone) AND (deadline <= max_deadline)) OR (max_deadline = '0001-01-01 00:00:00+00'::timestamp with time zone)))
);
@@ -2286,6 +2289,7 @@ CREATE VIEW workspace_build_with_user AS
workspace_builds.template_version_preset_id,
workspace_builds.has_ai_task,
workspace_builds.ai_task_sidebar_app_id,
workspace_builds.has_external_agent,
COALESCE(visible_users.avatar_url, ''::text) AS initiator_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS initiator_by_username,
COALESCE(visible_users.name, ''::text) AS initiator_by_name
@@ -0,0 +1,77 @@
DROP VIEW template_version_with_user;
DROP VIEW workspace_build_with_user;
ALTER TABLE template_versions DROP COLUMN has_external_agent;
ALTER TABLE workspace_builds DROP COLUMN has_external_agent;
-- Recreate `template_version_with_user` as defined in dump.sql
CREATE VIEW template_version_with_user AS
SELECT
template_versions.id,
template_versions.template_id,
template_versions.organization_id,
template_versions.created_at,
template_versions.updated_at,
template_versions.name,
template_versions.readme,
template_versions.job_id,
template_versions.created_by,
template_versions.external_auth_providers,
template_versions.message,
template_versions.archived,
template_versions.source_example_id,
template_versions.has_ai_task,
COALESCE(visible_users.avatar_url, '' :: text) AS created_by_avatar_url,
COALESCE(visible_users.username, '' :: text) AS created_by_username,
COALESCE(visible_users.name, '' :: text) AS created_by_name
FROM
(
template_versions
LEFT JOIN visible_users ON (
(template_versions.created_by = visible_users.id)
)
);
COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.';
-- Recreate `workspace_build_with_user` as defined in dump.sql
CREATE VIEW workspace_build_with_user AS
SELECT
workspace_builds.id,
workspace_builds.created_at,
workspace_builds.updated_at,
workspace_builds.workspace_id,
workspace_builds.template_version_id,
workspace_builds.build_number,
workspace_builds.transition,
workspace_builds.initiator_id,
workspace_builds.provisioner_state,
workspace_builds.job_id,
workspace_builds.deadline,
workspace_builds.reason,
workspace_builds.daily_cost,
workspace_builds.max_deadline,
workspace_builds.template_version_preset_id,
workspace_builds.has_ai_task,
workspace_builds.ai_task_sidebar_app_id,
COALESCE(
visible_users.avatar_url,
'' :: text
) AS initiator_by_avatar_url,
COALESCE(
visible_users.username,
'' :: text
) AS initiator_by_username,
COALESCE(visible_users.name, '' :: text) AS initiator_by_name
FROM
(
workspace_builds
LEFT JOIN visible_users ON (
(
workspace_builds.initiator_id = visible_users.id
)
)
);
COMMENT ON VIEW workspace_build_with_user IS 'Joins in the username + avatar url of the initiated by user.';
@@ -0,0 +1,89 @@
-- Determines if a coder_external_agent resource is defined in a template version.
ALTER TABLE
template_versions
ADD
COLUMN has_external_agent BOOLEAN;
DROP VIEW template_version_with_user;
-- We're adding the external_agents column.
CREATE VIEW template_version_with_user AS
SELECT
template_versions.id,
template_versions.template_id,
template_versions.organization_id,
template_versions.created_at,
template_versions.updated_at,
template_versions.name,
template_versions.readme,
template_versions.job_id,
template_versions.created_by,
template_versions.external_auth_providers,
template_versions.message,
template_versions.archived,
template_versions.source_example_id,
template_versions.has_ai_task,
template_versions.has_external_agent,
COALESCE(visible_users.avatar_url, '' :: text) AS created_by_avatar_url,
COALESCE(visible_users.username, '' :: text) AS created_by_username,
COALESCE(visible_users.name, '' :: text) AS created_by_name
FROM
(
template_versions
LEFT JOIN visible_users ON (
(template_versions.created_by = visible_users.id)
)
);
COMMENT ON VIEW template_version_with_user IS 'Joins in the username + avatar url of the created by user.';
-- Determines if a coder_external_agent resource was included in a
-- workspace build.
ALTER TABLE
workspace_builds
ADD
COLUMN has_external_agent BOOLEAN;
DROP VIEW workspace_build_with_user;
-- We're adding the has_external_agent column.
CREATE VIEW workspace_build_with_user AS
SELECT
workspace_builds.id,
workspace_builds.created_at,
workspace_builds.updated_at,
workspace_builds.workspace_id,
workspace_builds.template_version_id,
workspace_builds.build_number,
workspace_builds.transition,
workspace_builds.initiator_id,
workspace_builds.provisioner_state,
workspace_builds.job_id,
workspace_builds.deadline,
workspace_builds.reason,
workspace_builds.daily_cost,
workspace_builds.max_deadline,
workspace_builds.template_version_preset_id,
workspace_builds.has_ai_task,
workspace_builds.ai_task_sidebar_app_id,
workspace_builds.has_external_agent,
COALESCE(
visible_users.avatar_url,
'' :: text
) AS initiator_by_avatar_url,
COALESCE(
visible_users.username,
'' :: text
) AS initiator_by_username,
COALESCE(visible_users.name, '' :: text) AS initiator_by_name
FROM
(
workspace_builds
LEFT JOIN visible_users ON (
(
workspace_builds.initiator_id = visible_users.id
)
)
);
COMMENT ON VIEW workspace_build_with_user IS 'Joins in the username + avatar url of the initiated by user.';
+3
View File
@@ -84,6 +84,7 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate
arg.HasAITask,
arg.AuthorID,
arg.AuthorUsername,
arg.HasExternalAgent,
)
if err != nil {
return nil, err
@@ -271,6 +272,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
arg.LastUsedAfter,
arg.UsingActive,
arg.HasAITask,
arg.HasExternalAgent,
arg.RequesterID,
arg.Offset,
arg.Limit,
@@ -321,6 +323,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
&i.LatestBuildTransition,
&i.LatestBuildStatus,
&i.LatestBuildHasAITask,
&i.LatestBuildHasExternalAgent,
&i.Count,
); err != nil {
return nil, err
+8 -4
View File
@@ -3634,6 +3634,7 @@ type TemplateVersion struct {
Archived bool `db:"archived" json:"archived"`
SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"`
CreatedByUsername string `db:"created_by_username" json:"created_by_username"`
CreatedByName string `db:"created_by_name" json:"created_by_name"`
@@ -3720,10 +3721,11 @@ type TemplateVersionTable struct {
// IDs of External auth providers for a specific template version
ExternalAuthProviders json.RawMessage `db:"external_auth_providers" json:"external_auth_providers"`
// Message describing the changes in this version of the template, similar to a Git commit message. Like a commit message, this should be a short, high-level description of the changes in this version of the template. This message is immutable and should not be updated after the fact.
Message string `db:"message" json:"message"`
Archived bool `db:"archived" json:"archived"`
SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
Message string `db:"message" json:"message"`
Archived bool `db:"archived" json:"archived"`
SourceExampleID sql.NullString `db:"source_example_id" json:"source_example_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
}
type TemplateVersionTerraformValue struct {
@@ -4173,6 +4175,7 @@ type WorkspaceBuild struct {
TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
AITaskSidebarAppID uuid.NullUUID `db:"ai_task_sidebar_app_id" json:"ai_task_sidebar_app_id"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
InitiatorByAvatarUrl string `db:"initiator_by_avatar_url" json:"initiator_by_avatar_url"`
InitiatorByUsername string `db:"initiator_by_username" json:"initiator_by_username"`
InitiatorByName string `db:"initiator_by_name" json:"initiator_by_name"`
@@ -4204,6 +4207,7 @@ type WorkspaceBuildTable struct {
TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
AITaskSidebarAppID uuid.NullUUID `db:"ai_task_sidebar_app_id" json:"ai_task_sidebar_app_id"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
}
type WorkspaceLatestBuild struct {
+2 -2
View File
@@ -617,10 +617,10 @@ type sqlcQuerier interface {
UpdateTemplateDeletedByID(ctx context.Context, arg UpdateTemplateDeletedByIDParams) error
UpdateTemplateMetaByID(ctx context.Context, arg UpdateTemplateMetaByIDParams) error
UpdateTemplateScheduleByID(ctx context.Context, arg UpdateTemplateScheduleByIDParams) error
UpdateTemplateVersionAITaskByJobID(ctx context.Context, arg UpdateTemplateVersionAITaskByJobIDParams) error
UpdateTemplateVersionByID(ctx context.Context, arg UpdateTemplateVersionByIDParams) error
UpdateTemplateVersionDescriptionByJobID(ctx context.Context, arg UpdateTemplateVersionDescriptionByJobIDParams) error
UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context.Context, arg UpdateTemplateVersionExternalAuthProvidersByJobIDParams) error
UpdateTemplateVersionFlagsByJobID(ctx context.Context, arg UpdateTemplateVersionFlagsByJobIDParams) error
UpdateTemplateWorkspacesLastUsedAt(ctx context.Context, arg UpdateTemplateWorkspacesLastUsedAtParams) error
UpdateUsageEventsPostPublish(ctx context.Context, arg UpdateUsageEventsPostPublishParams) error
UpdateUserDeletedByID(ctx context.Context, id uuid.UUID) error
@@ -650,9 +650,9 @@ type sqlcQuerier interface {
UpdateWorkspaceAppHealthByID(ctx context.Context, arg UpdateWorkspaceAppHealthByIDParams) error
UpdateWorkspaceAutomaticUpdates(ctx context.Context, arg UpdateWorkspaceAutomaticUpdatesParams) error
UpdateWorkspaceAutostart(ctx context.Context, arg UpdateWorkspaceAutostartParams) error
UpdateWorkspaceBuildAITaskByID(ctx context.Context, arg UpdateWorkspaceBuildAITaskByIDParams) error
UpdateWorkspaceBuildCostByID(ctx context.Context, arg UpdateWorkspaceBuildCostByIDParams) error
UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg UpdateWorkspaceBuildDeadlineByIDParams) error
UpdateWorkspaceBuildFlagsByID(ctx context.Context, arg UpdateWorkspaceBuildFlagsByIDParams) error
UpdateWorkspaceBuildProvisionerStateByID(ctx context.Context, arg UpdateWorkspaceBuildProvisionerStateByIDParams) error
UpdateWorkspaceDeletedByID(ctx context.Context, arg UpdateWorkspaceDeletedByIDParams) error
UpdateWorkspaceDormantDeletingAt(ctx context.Context, arg UpdateWorkspaceDormantDeletingAtParams) (WorkspaceTable, error)
+169 -122
View File
@@ -12141,21 +12141,28 @@ WHERE
ELSE true
END
-- Filter by has_external_agent in latest version
AND CASE
WHEN $10 :: boolean IS NOT NULL THEN
tv.has_external_agent = $10 :: boolean
ELSE true
END
-- Authorize Filter clause will be injected below in GetAuthorizedTemplates
-- @authorize_filter
ORDER BY (t.name, t.id) ASC
`
type GetTemplatesWithFilterParams struct {
Deleted bool `db:"deleted" json:"deleted"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
ExactName string `db:"exact_name" json:"exact_name"`
FuzzyName string `db:"fuzzy_name" json:"fuzzy_name"`
IDs []uuid.UUID `db:"ids" json:"ids"`
Deprecated sql.NullBool `db:"deprecated" json:"deprecated"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
AuthorID uuid.UUID `db:"author_id" json:"author_id"`
AuthorUsername string `db:"author_username" json:"author_username"`
Deleted bool `db:"deleted" json:"deleted"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
ExactName string `db:"exact_name" json:"exact_name"`
FuzzyName string `db:"fuzzy_name" json:"fuzzy_name"`
IDs []uuid.UUID `db:"ids" json:"ids"`
Deprecated sql.NullBool `db:"deprecated" json:"deprecated"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
AuthorID uuid.UUID `db:"author_id" json:"author_id"`
AuthorUsername string `db:"author_username" json:"author_username"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
}
func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplatesWithFilterParams) ([]Template, error) {
@@ -12169,6 +12176,7 @@ func (q *sqlQuerier) GetTemplatesWithFilter(ctx context.Context, arg GetTemplate
arg.HasAITask,
arg.AuthorID,
arg.AuthorUsername,
arg.HasExternalAgent,
)
if err != nil {
return nil, err
@@ -12653,7 +12661,7 @@ FROM
-- Scope an archive to a single template and ignore already archived template versions
(
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent
FROM
template_versions
WHERE
@@ -12754,7 +12762,7 @@ func (q *sqlQuerier) ArchiveUnusedTemplateVersions(ctx context.Context, arg Arch
const getPreviousTemplateVersion = `-- name: GetPreviousTemplateVersion :one
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name
FROM
template_version_with_user AS template_versions
WHERE
@@ -12793,6 +12801,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -12802,7 +12811,7 @@ func (q *sqlQuerier) GetPreviousTemplateVersion(ctx context.Context, arg GetPrev
const getTemplateVersionByID = `-- name: GetTemplateVersionByID :one
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name
FROM
template_version_with_user AS template_versions
WHERE
@@ -12827,6 +12836,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -12836,7 +12846,7 @@ func (q *sqlQuerier) GetTemplateVersionByID(ctx context.Context, id uuid.UUID) (
const getTemplateVersionByJobID = `-- name: GetTemplateVersionByJobID :one
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name
FROM
template_version_with_user AS template_versions
WHERE
@@ -12861,6 +12871,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -12870,7 +12881,7 @@ func (q *sqlQuerier) GetTemplateVersionByJobID(ctx context.Context, jobID uuid.U
const getTemplateVersionByTemplateIDAndName = `-- name: GetTemplateVersionByTemplateIDAndName :one
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name
FROM
template_version_with_user AS template_versions
WHERE
@@ -12901,6 +12912,7 @@ func (q *sqlQuerier) GetTemplateVersionByTemplateIDAndName(ctx context.Context,
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -12925,7 +12937,7 @@ func (q *sqlQuerier) GetTemplateVersionHasAITask(ctx context.Context, id uuid.UU
const getTemplateVersionsByIDs = `-- name: GetTemplateVersionsByIDs :many
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name
FROM
template_version_with_user AS template_versions
WHERE
@@ -12956,6 +12968,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -12975,7 +12988,7 @@ func (q *sqlQuerier) GetTemplateVersionsByIDs(ctx context.Context, ids []uuid.UU
const getTemplateVersionsByTemplateID = `-- name: GetTemplateVersionsByTemplateID :many
SELECT
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name
id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name
FROM
template_version_with_user AS template_versions
WHERE
@@ -13053,6 +13066,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -13071,7 +13085,7 @@ func (q *sqlQuerier) GetTemplateVersionsByTemplateID(ctx context.Context, arg Ge
}
const getTemplateVersionsCreatedAfter = `-- name: GetTemplateVersionsCreatedAfter :many
SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE created_at > $1
SELECT id, template_id, organization_id, created_at, updated_at, name, readme, job_id, created_by, external_auth_providers, message, archived, source_example_id, has_ai_task, has_external_agent, created_by_avatar_url, created_by_username, created_by_name FROM template_version_with_user AS template_versions WHERE created_at > $1
`
func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, createdAt time.Time) ([]TemplateVersion, error) {
@@ -13098,6 +13112,7 @@ func (q *sqlQuerier) GetTemplateVersionsCreatedAfter(ctx context.Context, create
&i.Archived,
&i.SourceExampleID,
&i.HasAITask,
&i.HasExternalAgent,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -13186,27 +13201,6 @@ func (q *sqlQuerier) UnarchiveTemplateVersion(ctx context.Context, arg Unarchive
return err
}
const updateTemplateVersionAITaskByJobID = `-- name: UpdateTemplateVersionAITaskByJobID :exec
UPDATE
template_versions
SET
has_ai_task = $2,
updated_at = $3
WHERE
job_id = $1
`
type UpdateTemplateVersionAITaskByJobIDParams struct {
JobID uuid.UUID `db:"job_id" json:"job_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
func (q *sqlQuerier) UpdateTemplateVersionAITaskByJobID(ctx context.Context, arg UpdateTemplateVersionAITaskByJobIDParams) error {
_, err := q.db.ExecContext(ctx, updateTemplateVersionAITaskByJobID, arg.JobID, arg.HasAITask, arg.UpdatedAt)
return err
}
const updateTemplateVersionByID = `-- name: UpdateTemplateVersionByID :exec
UPDATE
template_versions
@@ -13280,6 +13274,34 @@ func (q *sqlQuerier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx conte
return err
}
const updateTemplateVersionFlagsByJobID = `-- name: UpdateTemplateVersionFlagsByJobID :exec
UPDATE
template_versions
SET
has_ai_task = $2,
has_external_agent = $3,
updated_at = $4
WHERE
job_id = $1
`
type UpdateTemplateVersionFlagsByJobIDParams struct {
JobID uuid.UUID `db:"job_id" json:"job_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
}
func (q *sqlQuerier) UpdateTemplateVersionFlagsByJobID(ctx context.Context, arg UpdateTemplateVersionFlagsByJobIDParams) error {
_, err := q.db.ExecContext(ctx, updateTemplateVersionFlagsByJobID,
arg.JobID,
arg.HasAITask,
arg.HasExternalAgent,
arg.UpdatedAt,
)
return err
}
const getTemplateVersionTerraformValues = `-- name: GetTemplateVersionTerraformValues :one
SELECT
template_version_terraform_values.template_version_id, template_version_terraform_values.updated_at, template_version_terraform_values.cached_plan, template_version_terraform_values.cached_module_files, template_version_terraform_values.provisionerd_version
@@ -15910,7 +15932,7 @@ const getWorkspaceAgentAndLatestBuildByAuthToken = `-- name: GetWorkspaceAgentAn
SELECT
workspaces.id, workspaces.created_at, workspaces.updated_at, workspaces.owner_id, workspaces.organization_id, workspaces.template_id, workspaces.deleted, workspaces.name, workspaces.autostart_schedule, workspaces.ttl, workspaces.last_used_at, workspaces.dormant_at, workspaces.deleting_at, workspaces.automatic_updates, workspaces.favorite, workspaces.next_start_at, workspaces.group_acl, workspaces.user_acl,
workspace_agents.id, workspace_agents.created_at, workspace_agents.updated_at, workspace_agents.name, workspace_agents.first_connected_at, workspace_agents.last_connected_at, workspace_agents.disconnected_at, workspace_agents.resource_id, workspace_agents.auth_token, workspace_agents.auth_instance_id, workspace_agents.architecture, workspace_agents.environment_variables, workspace_agents.operating_system, workspace_agents.instance_metadata, workspace_agents.resource_metadata, workspace_agents.directory, workspace_agents.version, workspace_agents.last_connected_replica_id, workspace_agents.connection_timeout_seconds, workspace_agents.troubleshooting_url, workspace_agents.motd_file, workspace_agents.lifecycle_state, workspace_agents.expanded_directory, workspace_agents.logs_length, workspace_agents.logs_overflowed, workspace_agents.started_at, workspace_agents.ready_at, workspace_agents.subsystems, workspace_agents.display_apps, workspace_agents.api_version, workspace_agents.display_order, workspace_agents.parent_id, workspace_agents.api_key_scope, workspace_agents.deleted,
workspace_build_with_user.id, workspace_build_with_user.created_at, workspace_build_with_user.updated_at, workspace_build_with_user.workspace_id, workspace_build_with_user.template_version_id, workspace_build_with_user.build_number, workspace_build_with_user.transition, workspace_build_with_user.initiator_id, workspace_build_with_user.provisioner_state, workspace_build_with_user.job_id, workspace_build_with_user.deadline, workspace_build_with_user.reason, workspace_build_with_user.daily_cost, workspace_build_with_user.max_deadline, workspace_build_with_user.template_version_preset_id, workspace_build_with_user.has_ai_task, workspace_build_with_user.ai_task_sidebar_app_id, workspace_build_with_user.initiator_by_avatar_url, workspace_build_with_user.initiator_by_username, workspace_build_with_user.initiator_by_name
workspace_build_with_user.id, workspace_build_with_user.created_at, workspace_build_with_user.updated_at, workspace_build_with_user.workspace_id, workspace_build_with_user.template_version_id, workspace_build_with_user.build_number, workspace_build_with_user.transition, workspace_build_with_user.initiator_id, workspace_build_with_user.provisioner_state, workspace_build_with_user.job_id, workspace_build_with_user.deadline, workspace_build_with_user.reason, workspace_build_with_user.daily_cost, workspace_build_with_user.max_deadline, workspace_build_with_user.template_version_preset_id, workspace_build_with_user.has_ai_task, workspace_build_with_user.ai_task_sidebar_app_id, workspace_build_with_user.has_external_agent, workspace_build_with_user.initiator_by_avatar_url, workspace_build_with_user.initiator_by_username, workspace_build_with_user.initiator_by_name
FROM
workspace_agents
JOIN
@@ -16023,6 +16045,7 @@ func (q *sqlQuerier) GetWorkspaceAgentAndLatestBuildByAuthToken(ctx context.Cont
&i.WorkspaceBuild.TemplateVersionPresetID,
&i.WorkspaceBuild.HasAITask,
&i.WorkspaceBuild.AITaskSidebarAppID,
&i.WorkspaceBuild.HasExternalAgent,
&i.WorkspaceBuild.InitiatorByAvatarUrl,
&i.WorkspaceBuild.InitiatorByUsername,
&i.WorkspaceBuild.InitiatorByName,
@@ -18677,7 +18700,7 @@ func (q *sqlQuerier) InsertWorkspaceBuildParameters(ctx context.Context, arg Ins
}
const getActiveWorkspaceBuildsByTemplateID = `-- name: GetActiveWorkspaceBuildsByTemplateID :many
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_task_sidebar_app_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_task_sidebar_app_id, wb.has_external_agent, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
@@ -18734,6 +18757,7 @@ func (q *sqlQuerier) GetActiveWorkspaceBuildsByTemplateID(ctx context.Context, t
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -18833,7 +18857,7 @@ func (q *sqlQuerier) GetFailedWorkspaceBuildsByTemplateID(ctx context.Context, a
const getLatestWorkspaceBuildByWorkspaceID = `-- name: GetLatestWorkspaceBuildByWorkspaceID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, has_external_agent, initiator_by_avatar_url, initiator_by_username, initiator_by_name
FROM
workspace_build_with_user AS workspace_builds
WHERE
@@ -18865,6 +18889,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -18873,7 +18898,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildByWorkspaceID(ctx context.Context, w
}
const getLatestWorkspaceBuildsByWorkspaceIDs = `-- name: GetLatestWorkspaceBuildsByWorkspaceIDs :many
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_task_sidebar_app_id, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name
SELECT wb.id, wb.created_at, wb.updated_at, wb.workspace_id, wb.template_version_id, wb.build_number, wb.transition, wb.initiator_id, wb.provisioner_state, wb.job_id, wb.deadline, wb.reason, wb.daily_cost, wb.max_deadline, wb.template_version_preset_id, wb.has_ai_task, wb.ai_task_sidebar_app_id, wb.has_external_agent, wb.initiator_by_avatar_url, wb.initiator_by_username, wb.initiator_by_name
FROM (
SELECT
workspace_id, MAX(build_number) as max_build_number
@@ -18916,6 +18941,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -18935,7 +18961,7 @@ func (q *sqlQuerier) GetLatestWorkspaceBuildsByWorkspaceIDs(ctx context.Context,
const getWorkspaceBuildByID = `-- name: GetWorkspaceBuildByID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, has_external_agent, initiator_by_avatar_url, initiator_by_username, initiator_by_name
FROM
workspace_build_with_user AS workspace_builds
WHERE
@@ -18965,6 +18991,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -18974,7 +19001,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByID(ctx context.Context, id uuid.UUID) (W
const getWorkspaceBuildByJobID = `-- name: GetWorkspaceBuildByJobID :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, has_external_agent, initiator_by_avatar_url, initiator_by_username, initiator_by_name
FROM
workspace_build_with_user AS workspace_builds
WHERE
@@ -19004,6 +19031,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -19013,7 +19041,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByJobID(ctx context.Context, jobID uuid.UU
const getWorkspaceBuildByWorkspaceIDAndBuildNumber = `-- name: GetWorkspaceBuildByWorkspaceIDAndBuildNumber :one
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, has_external_agent, initiator_by_avatar_url, initiator_by_username, initiator_by_name
FROM
workspace_build_with_user AS workspace_builds
WHERE
@@ -19047,6 +19075,7 @@ func (q *sqlQuerier) GetWorkspaceBuildByWorkspaceIDAndBuildNumber(ctx context.Co
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -19123,7 +19152,7 @@ func (q *sqlQuerier) GetWorkspaceBuildStatsByTemplates(ctx context.Context, sinc
const getWorkspaceBuildsByWorkspaceID = `-- name: GetWorkspaceBuildsByWorkspaceID :many
SELECT
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name
id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, has_external_agent, initiator_by_avatar_url, initiator_by_username, initiator_by_name
FROM
workspace_build_with_user AS workspace_builds
WHERE
@@ -19196,6 +19225,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -19214,7 +19244,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsByWorkspaceID(ctx context.Context, arg Ge
}
const getWorkspaceBuildsCreatedAfter = `-- name: GetWorkspaceBuildsCreatedAfter :many
SELECT id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user WHERE created_at > $1
SELECT id, created_at, updated_at, workspace_id, template_version_id, build_number, transition, initiator_id, provisioner_state, job_id, deadline, reason, daily_cost, max_deadline, template_version_preset_id, has_ai_task, ai_task_sidebar_app_id, has_external_agent, initiator_by_avatar_url, initiator_by_username, initiator_by_name FROM workspace_build_with_user WHERE created_at > $1
`
func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceBuild, error) {
@@ -19244,6 +19274,7 @@ func (q *sqlQuerier) GetWorkspaceBuildsCreatedAfter(ctx context.Context, created
&i.TemplateVersionPresetID,
&i.HasAITask,
&i.AITaskSidebarAppID,
&i.HasExternalAgent,
&i.InitiatorByAvatarUrl,
&i.InitiatorByUsername,
&i.InitiatorByName,
@@ -19320,33 +19351,6 @@ func (q *sqlQuerier) InsertWorkspaceBuild(ctx context.Context, arg InsertWorkspa
return err
}
const updateWorkspaceBuildAITaskByID = `-- name: UpdateWorkspaceBuildAITaskByID :exec
UPDATE
workspace_builds
SET
has_ai_task = $1,
ai_task_sidebar_app_id = $2,
updated_at = $3::timestamptz
WHERE id = $4::uuid
`
type UpdateWorkspaceBuildAITaskByIDParams struct {
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
SidebarAppID uuid.NullUUID `db:"sidebar_app_id" json:"sidebar_app_id"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
ID uuid.UUID `db:"id" json:"id"`
}
func (q *sqlQuerier) UpdateWorkspaceBuildAITaskByID(ctx context.Context, arg UpdateWorkspaceBuildAITaskByIDParams) error {
_, err := q.db.ExecContext(ctx, updateWorkspaceBuildAITaskByID,
arg.HasAITask,
arg.SidebarAppID,
arg.UpdatedAt,
arg.ID,
)
return err
}
const updateWorkspaceBuildCostByID = `-- name: UpdateWorkspaceBuildCostByID :exec
UPDATE
workspace_builds
@@ -19401,6 +19405,36 @@ func (q *sqlQuerier) UpdateWorkspaceBuildDeadlineByID(ctx context.Context, arg U
return err
}
const updateWorkspaceBuildFlagsByID = `-- name: UpdateWorkspaceBuildFlagsByID :exec
UPDATE
workspace_builds
SET
has_ai_task = $1,
ai_task_sidebar_app_id = $2,
has_external_agent = $3,
updated_at = $4::timestamptz
WHERE id = $5::uuid
`
type UpdateWorkspaceBuildFlagsByIDParams struct {
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
SidebarAppID uuid.NullUUID `db:"sidebar_app_id" json:"sidebar_app_id"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
ID uuid.UUID `db:"id" json:"id"`
}
func (q *sqlQuerier) UpdateWorkspaceBuildFlagsByID(ctx context.Context, arg UpdateWorkspaceBuildFlagsByIDParams) error {
_, err := q.db.ExecContext(ctx, updateWorkspaceBuildFlagsByID,
arg.HasAITask,
arg.SidebarAppID,
arg.HasExternalAgent,
arg.UpdatedAt,
arg.ID,
)
return err
}
const updateWorkspaceBuildProvisionerStateByID = `-- name: UpdateWorkspaceBuildProvisionerStateByID :exec
UPDATE
workspace_builds
@@ -20368,7 +20402,8 @@ SELECT
latest_build.error as latest_build_error,
latest_build.transition as latest_build_transition,
latest_build.job_status as latest_build_status,
latest_build.has_ai_task as latest_build_has_ai_task
latest_build.has_ai_task as latest_build_has_ai_task,
latest_build.has_external_agent as latest_build_has_external_agent
FROM
workspaces_expanded as workspaces
JOIN
@@ -20381,6 +20416,7 @@ LEFT JOIN LATERAL (
workspace_builds.transition,
workspace_builds.template_version_id,
workspace_builds.has_ai_task,
workspace_builds.has_external_agent,
template_versions.name AS template_version_name,
provisioner_jobs.id AS provisioner_job_id,
provisioner_jobs.started_at,
@@ -20621,16 +20657,22 @@ WHERE
)) = ($19 :: boolean)
ELSE true
END
-- Filter by has_external_agent in latest build
AND CASE
WHEN $20 :: boolean IS NOT NULL THEN
latest_build.has_external_agent = $20 :: boolean
ELSE true
END
-- Authorize Filter clause will be injected below in GetAuthorizedWorkspaces
-- @authorize_filter
), filtered_workspaces_order AS (
SELECT
fw.id, fw.created_at, fw.updated_at, fw.owner_id, fw.organization_id, fw.template_id, fw.deleted, fw.name, fw.autostart_schedule, fw.ttl, fw.last_used_at, fw.dormant_at, fw.deleting_at, fw.automatic_updates, fw.favorite, fw.next_start_at, fw.group_acl, fw.user_acl, fw.owner_avatar_url, fw.owner_username, fw.owner_name, fw.organization_name, fw.organization_display_name, fw.organization_icon, fw.organization_description, fw.template_name, fw.template_display_name, fw.template_icon, fw.template_description, fw.template_version_id, fw.template_version_name, fw.latest_build_completed_at, fw.latest_build_canceled_at, fw.latest_build_error, fw.latest_build_transition, fw.latest_build_status, fw.latest_build_has_ai_task
fw.id, fw.created_at, fw.updated_at, fw.owner_id, fw.organization_id, fw.template_id, fw.deleted, fw.name, fw.autostart_schedule, fw.ttl, fw.last_used_at, fw.dormant_at, fw.deleting_at, fw.automatic_updates, fw.favorite, fw.next_start_at, fw.group_acl, fw.user_acl, fw.owner_avatar_url, fw.owner_username, fw.owner_name, fw.organization_name, fw.organization_display_name, fw.organization_icon, fw.organization_description, fw.template_name, fw.template_display_name, fw.template_icon, fw.template_description, fw.template_version_id, fw.template_version_name, fw.latest_build_completed_at, fw.latest_build_canceled_at, fw.latest_build_error, fw.latest_build_transition, fw.latest_build_status, fw.latest_build_has_ai_task, fw.latest_build_has_external_agent
FROM
filtered_workspaces fw
ORDER BY
-- To ensure that 'favorite' workspaces show up first in the list only for their owner.
CASE WHEN owner_id = $20 AND favorite THEN 0 ELSE 1 END ASC,
CASE WHEN owner_id = $21 AND favorite THEN 0 ELSE 1 END ASC,
(latest_build_completed_at IS NOT NULL AND
latest_build_canceled_at IS NULL AND
latest_build_error IS NULL AND
@@ -20639,14 +20681,14 @@ WHERE
LOWER(name) ASC
LIMIT
CASE
WHEN $22 :: integer > 0 THEN
$22
WHEN $23 :: integer > 0 THEN
$23
END
OFFSET
$21
$22
), filtered_workspaces_order_with_summary AS (
SELECT
fwo.id, fwo.created_at, fwo.updated_at, fwo.owner_id, fwo.organization_id, fwo.template_id, fwo.deleted, fwo.name, fwo.autostart_schedule, fwo.ttl, fwo.last_used_at, fwo.dormant_at, fwo.deleting_at, fwo.automatic_updates, fwo.favorite, fwo.next_start_at, fwo.group_acl, fwo.user_acl, fwo.owner_avatar_url, fwo.owner_username, fwo.owner_name, fwo.organization_name, fwo.organization_display_name, fwo.organization_icon, fwo.organization_description, fwo.template_name, fwo.template_display_name, fwo.template_icon, fwo.template_description, fwo.template_version_id, fwo.template_version_name, fwo.latest_build_completed_at, fwo.latest_build_canceled_at, fwo.latest_build_error, fwo.latest_build_transition, fwo.latest_build_status, fwo.latest_build_has_ai_task
fwo.id, fwo.created_at, fwo.updated_at, fwo.owner_id, fwo.organization_id, fwo.template_id, fwo.deleted, fwo.name, fwo.autostart_schedule, fwo.ttl, fwo.last_used_at, fwo.dormant_at, fwo.deleting_at, fwo.automatic_updates, fwo.favorite, fwo.next_start_at, fwo.group_acl, fwo.user_acl, fwo.owner_avatar_url, fwo.owner_username, fwo.owner_name, fwo.organization_name, fwo.organization_display_name, fwo.organization_icon, fwo.organization_description, fwo.template_name, fwo.template_display_name, fwo.template_icon, fwo.template_description, fwo.template_version_id, fwo.template_version_name, fwo.latest_build_completed_at, fwo.latest_build_canceled_at, fwo.latest_build_error, fwo.latest_build_transition, fwo.latest_build_status, fwo.latest_build_has_ai_task, fwo.latest_build_has_external_agent
FROM
filtered_workspaces_order fwo
-- Return a technical summary row with total count of workspaces.
@@ -20690,9 +20732,10 @@ WHERE
'', -- latest_build_error
'start'::workspace_transition, -- latest_build_transition
'unknown'::provisioner_job_status, -- latest_build_status
false -- latest_build_has_ai_task
false, -- latest_build_has_ai_task
false -- latest_build_has_external_agent
WHERE
$23 :: boolean = true
$24 :: boolean = true
), total_count AS (
SELECT
count(*) AS count
@@ -20700,7 +20743,7 @@ WHERE
filtered_workspaces
)
SELECT
fwos.id, fwos.created_at, fwos.updated_at, fwos.owner_id, fwos.organization_id, fwos.template_id, fwos.deleted, fwos.name, fwos.autostart_schedule, fwos.ttl, fwos.last_used_at, fwos.dormant_at, fwos.deleting_at, fwos.automatic_updates, fwos.favorite, fwos.next_start_at, fwos.group_acl, fwos.user_acl, fwos.owner_avatar_url, fwos.owner_username, fwos.owner_name, fwos.organization_name, fwos.organization_display_name, fwos.organization_icon, fwos.organization_description, fwos.template_name, fwos.template_display_name, fwos.template_icon, fwos.template_description, fwos.template_version_id, fwos.template_version_name, fwos.latest_build_completed_at, fwos.latest_build_canceled_at, fwos.latest_build_error, fwos.latest_build_transition, fwos.latest_build_status, fwos.latest_build_has_ai_task,
fwos.id, fwos.created_at, fwos.updated_at, fwos.owner_id, fwos.organization_id, fwos.template_id, fwos.deleted, fwos.name, fwos.autostart_schedule, fwos.ttl, fwos.last_used_at, fwos.dormant_at, fwos.deleting_at, fwos.automatic_updates, fwos.favorite, fwos.next_start_at, fwos.group_acl, fwos.user_acl, fwos.owner_avatar_url, fwos.owner_username, fwos.owner_name, fwos.organization_name, fwos.organization_display_name, fwos.organization_icon, fwos.organization_description, fwos.template_name, fwos.template_display_name, fwos.template_icon, fwos.template_description, fwos.template_version_id, fwos.template_version_name, fwos.latest_build_completed_at, fwos.latest_build_canceled_at, fwos.latest_build_error, fwos.latest_build_transition, fwos.latest_build_status, fwos.latest_build_has_ai_task, fwos.latest_build_has_external_agent,
tc.count
FROM
filtered_workspaces_order_with_summary fwos
@@ -20728,6 +20771,7 @@ type GetWorkspacesParams struct {
LastUsedAfter time.Time `db:"last_used_after" json:"last_used_after"`
UsingActive sql.NullBool `db:"using_active" json:"using_active"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
RequesterID uuid.UUID `db:"requester_id" json:"requester_id"`
Offset int32 `db:"offset_" json:"offset_"`
Limit int32 `db:"limit_" json:"limit_"`
@@ -20735,44 +20779,45 @@ type GetWorkspacesParams struct {
}
type GetWorkspacesRow struct {
ID uuid.UUID `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
Deleted bool `db:"deleted" json:"deleted"`
Name string `db:"name" json:"name"`
AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"`
Ttl sql.NullInt64 `db:"ttl" json:"ttl"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"`
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
Favorite bool `db:"favorite" json:"favorite"`
NextStartAt sql.NullTime `db:"next_start_at" json:"next_start_at"`
GroupACL json.RawMessage `db:"group_acl" json:"group_acl"`
UserACL json.RawMessage `db:"user_acl" json:"user_acl"`
OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OwnerName string `db:"owner_name" json:"owner_name"`
OrganizationName string `db:"organization_name" json:"organization_name"`
OrganizationDisplayName string `db:"organization_display_name" json:"organization_display_name"`
OrganizationIcon string `db:"organization_icon" json:"organization_icon"`
OrganizationDescription string `db:"organization_description" json:"organization_description"`
TemplateName string `db:"template_name" json:"template_name"`
TemplateDisplayName string `db:"template_display_name" json:"template_display_name"`
TemplateIcon string `db:"template_icon" json:"template_icon"`
TemplateDescription string `db:"template_description" json:"template_description"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateVersionName sql.NullString `db:"template_version_name" json:"template_version_name"`
LatestBuildCompletedAt sql.NullTime `db:"latest_build_completed_at" json:"latest_build_completed_at"`
LatestBuildCanceledAt sql.NullTime `db:"latest_build_canceled_at" json:"latest_build_canceled_at"`
LatestBuildError sql.NullString `db:"latest_build_error" json:"latest_build_error"`
LatestBuildTransition WorkspaceTransition `db:"latest_build_transition" json:"latest_build_transition"`
LatestBuildStatus ProvisionerJobStatus `db:"latest_build_status" json:"latest_build_status"`
LatestBuildHasAITask sql.NullBool `db:"latest_build_has_ai_task" json:"latest_build_has_ai_task"`
Count int64 `db:"count" json:"count"`
ID uuid.UUID `db:"id" json:"id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
TemplateID uuid.UUID `db:"template_id" json:"template_id"`
Deleted bool `db:"deleted" json:"deleted"`
Name string `db:"name" json:"name"`
AutostartSchedule sql.NullString `db:"autostart_schedule" json:"autostart_schedule"`
Ttl sql.NullInt64 `db:"ttl" json:"ttl"`
LastUsedAt time.Time `db:"last_used_at" json:"last_used_at"`
DormantAt sql.NullTime `db:"dormant_at" json:"dormant_at"`
DeletingAt sql.NullTime `db:"deleting_at" json:"deleting_at"`
AutomaticUpdates AutomaticUpdates `db:"automatic_updates" json:"automatic_updates"`
Favorite bool `db:"favorite" json:"favorite"`
NextStartAt sql.NullTime `db:"next_start_at" json:"next_start_at"`
GroupACL json.RawMessage `db:"group_acl" json:"group_acl"`
UserACL json.RawMessage `db:"user_acl" json:"user_acl"`
OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OwnerName string `db:"owner_name" json:"owner_name"`
OrganizationName string `db:"organization_name" json:"organization_name"`
OrganizationDisplayName string `db:"organization_display_name" json:"organization_display_name"`
OrganizationIcon string `db:"organization_icon" json:"organization_icon"`
OrganizationDescription string `db:"organization_description" json:"organization_description"`
TemplateName string `db:"template_name" json:"template_name"`
TemplateDisplayName string `db:"template_display_name" json:"template_display_name"`
TemplateIcon string `db:"template_icon" json:"template_icon"`
TemplateDescription string `db:"template_description" json:"template_description"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateVersionName sql.NullString `db:"template_version_name" json:"template_version_name"`
LatestBuildCompletedAt sql.NullTime `db:"latest_build_completed_at" json:"latest_build_completed_at"`
LatestBuildCanceledAt sql.NullTime `db:"latest_build_canceled_at" json:"latest_build_canceled_at"`
LatestBuildError sql.NullString `db:"latest_build_error" json:"latest_build_error"`
LatestBuildTransition WorkspaceTransition `db:"latest_build_transition" json:"latest_build_transition"`
LatestBuildStatus ProvisionerJobStatus `db:"latest_build_status" json:"latest_build_status"`
LatestBuildHasAITask sql.NullBool `db:"latest_build_has_ai_task" json:"latest_build_has_ai_task"`
LatestBuildHasExternalAgent sql.NullBool `db:"latest_build_has_external_agent" json:"latest_build_has_external_agent"`
Count int64 `db:"count" json:"count"`
}
// build_params is used to filter by build parameters if present.
@@ -20799,6 +20844,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
arg.LastUsedAfter,
arg.UsingActive,
arg.HasAITask,
arg.HasExternalAgent,
arg.RequesterID,
arg.Offset,
arg.Limit,
@@ -20849,6 +20895,7 @@ func (q *sqlQuerier) GetWorkspaces(ctx context.Context, arg GetWorkspacesParams)
&i.LatestBuildTransition,
&i.LatestBuildStatus,
&i.LatestBuildHasAITask,
&i.LatestBuildHasExternalAgent,
&i.Count,
); err != nil {
return nil, err
+6
View File
@@ -72,6 +72,12 @@ WHERE
ELSE true
END
-- Filter by has_external_agent in latest version
AND CASE
WHEN sqlc.narg('has_external_agent') :: boolean IS NOT NULL THEN
tv.has_external_agent = sqlc.narg('has_external_agent') :: boolean
ELSE true
END
-- Authorize Filter clause will be injected below in GetAuthorizedTemplates
-- @authorize_filter
ORDER BY (t.name, t.id) ASC
+10 -9
View File
@@ -122,15 +122,6 @@ SET
WHERE
job_id = $1;
-- name: UpdateTemplateVersionAITaskByJobID :exec
UPDATE
template_versions
SET
has_ai_task = $2,
updated_at = $3
WHERE
job_id = $1;
-- name: GetPreviousTemplateVersion :one
SELECT
*
@@ -241,3 +232,13 @@ SELECT EXISTS (
FROM template_versions
WHERE id = $1 AND has_ai_task = TRUE
);
-- name: UpdateTemplateVersionFlagsByJobID :exec
UPDATE
template_versions
SET
has_ai_task = $2,
has_external_agent = $3,
updated_at = $4
WHERE
job_id = $1;
+10 -9
View File
@@ -145,15 +145,6 @@ SET
updated_at = @updated_at::timestamptz
WHERE id = @id::uuid;
-- name: UpdateWorkspaceBuildAITaskByID :exec
UPDATE
workspace_builds
SET
has_ai_task = @has_ai_task,
ai_task_sidebar_app_id = @sidebar_app_id,
updated_at = @updated_at::timestamptz
WHERE id = @id::uuid;
-- name: GetActiveWorkspaceBuildsByTemplateID :many
SELECT wb.*
FROM (
@@ -247,3 +238,13 @@ WHERE
AND pj.job_status = 'failed'
ORDER BY
tv.name ASC, wb.build_number DESC;
-- name: UpdateWorkspaceBuildFlagsByID :exec
UPDATE
workspace_builds
SET
has_ai_task = @has_ai_task,
ai_task_sidebar_app_id = @sidebar_app_id,
has_external_agent = @has_external_agent,
updated_at = @updated_at::timestamptz
WHERE id = @id::uuid;
+11 -2
View File
@@ -117,7 +117,8 @@ SELECT
latest_build.error as latest_build_error,
latest_build.transition as latest_build_transition,
latest_build.job_status as latest_build_status,
latest_build.has_ai_task as latest_build_has_ai_task
latest_build.has_ai_task as latest_build_has_ai_task,
latest_build.has_external_agent as latest_build_has_external_agent
FROM
workspaces_expanded as workspaces
JOIN
@@ -130,6 +131,7 @@ LEFT JOIN LATERAL (
workspace_builds.transition,
workspace_builds.template_version_id,
workspace_builds.has_ai_task,
workspace_builds.has_external_agent,
template_versions.name AS template_version_name,
provisioner_jobs.id AS provisioner_job_id,
provisioner_jobs.started_at,
@@ -370,6 +372,12 @@ WHERE
)) = (sqlc.narg('has_ai_task') :: boolean)
ELSE true
END
-- Filter by has_external_agent in latest build
AND CASE
WHEN sqlc.narg('has_external_agent') :: boolean IS NOT NULL THEN
latest_build.has_external_agent = sqlc.narg('has_external_agent') :: boolean
ELSE true
END
-- Authorize Filter clause will be injected below in GetAuthorizedWorkspaces
-- @authorize_filter
), filtered_workspaces_order AS (
@@ -439,7 +447,8 @@ WHERE
'', -- latest_build_error
'start'::workspace_transition, -- latest_build_transition
'unknown'::provisioner_job_status, -- latest_build_status
false -- latest_build_has_ai_task
false, -- latest_build_has_ai_task
false -- latest_build_has_external_agent
WHERE
@with_summary :: boolean = true
), total_count AS (
@@ -1727,13 +1727,14 @@ func (s *server) completeTemplateImportJob(ctx context.Context, job database.Pro
if err != nil {
return xerrors.Errorf("update template version external auth providers: %w", err)
}
err = db.UpdateTemplateVersionAITaskByJobID(ctx, database.UpdateTemplateVersionAITaskByJobIDParams{
err = db.UpdateTemplateVersionFlagsByJobID(ctx, database.UpdateTemplateVersionFlagsByJobIDParams{
JobID: jobID,
HasAITask: sql.NullBool{
Bool: jobType.TemplateImport.HasAiTasks,
Valid: true,
},
UpdatedAt: now,
HasExternalAgent: sql.NullBool{},
UpdatedAt: now,
})
if err != nil {
return xerrors.Errorf("update template version external auth providers: %w", err)
@@ -2028,14 +2029,15 @@ func (s *server) completeWorkspaceBuildJob(ctx context.Context, job database.Pro
// Regardless of whether there is an AI task or not, update the field to indicate one way or the other since it
// always defaults to nil. ONLY if has_ai_task=true MUST ai_task_sidebar_app_id be set.
if err := db.UpdateWorkspaceBuildAITaskByID(ctx, database.UpdateWorkspaceBuildAITaskByIDParams{
if err := db.UpdateWorkspaceBuildFlagsByID(ctx, database.UpdateWorkspaceBuildFlagsByIDParams{
ID: workspaceBuild.ID,
HasAITask: sql.NullBool{
Bool: hasAITask,
Valid: true,
},
SidebarAppID: sidebarAppID,
UpdatedAt: now,
HasExternalAgent: sql.NullBool{},
SidebarAppID: sidebarAppID,
UpdatedAt: now,
}); err != nil {
return xerrors.Errorf("update workspace build ai tasks flag: %w", err)
}
+2 -2
View File
@@ -33,9 +33,9 @@ We track the following resources:
| PrebuildsSettings<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>id</td><td>false</td></tr><tr><td>reconciliation_paused</td><td>true</td></tr></tbody></table> |
| RoleSyncSettings<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>field</td><td>true</td></tr><tr><td>mapping</td><td>true</td></tr></tbody></table> |
| Template<br><i>write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>active_version_id</td><td>true</td></tr><tr><td>activity_bump</td><td>true</td></tr><tr><td>allow_user_autostart</td><td>true</td></tr><tr><td>allow_user_autostop</td><td>true</td></tr><tr><td>allow_user_cancel_workspace_jobs</td><td>true</td></tr><tr><td>autostart_block_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_weeks</td><td>true</td></tr><tr><td>cors_behavior</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_name</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>default_ttl</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deprecated</td><td>true</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>failure_ttl</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>max_port_sharing_level</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_display_name</td><td>false</td></tr><tr><td>organization_icon</td><td>false</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>organization_name</td><td>false</td></tr><tr><td>provisioner</td><td>true</td></tr><tr><td>require_active_version</td><td>true</td></tr><tr><td>time_til_dormant</td><td>true</td></tr><tr><td>time_til_dormant_autodelete</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>use_classic_parameter_flow</td><td>true</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table> |
| TemplateVersion<br><i>create, write</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>archived</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_name</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>external_auth_providers</td><td>false</td></tr><tr><td>has_ai_task</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>message</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>readme</td><td>true</td></tr><tr><td>source_example_id</td><td>false</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
| TemplateVersion<br><i>create, write</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>archived</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_name</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>external_auth_providers</td><td>false</td></tr><tr><td>has_ai_task</td><td>false</td></tr><tr><td>has_external_agent</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>message</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>readme</td><td>true</td></tr><tr><td>source_example_id</td><td>false</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
| User<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>avatar_url</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>email</td><td>true</td></tr><tr><td>github_com_user_id</td><td>false</td></tr><tr><td>hashed_one_time_passcode</td><td>false</td></tr><tr><td>hashed_password</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>is_system</td><td>true</td></tr><tr><td>last_seen_at</td><td>false</td></tr><tr><td>login_type</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>one_time_passcode_expires_at</td><td>true</td></tr><tr><td>quiet_hours_schedule</td><td>true</td></tr><tr><td>rbac_roles</td><td>true</td></tr><tr><td>status</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>username</td><td>true</td></tr></tbody></table> |
| WorkspaceBuild<br><i>start, stop</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>ai_task_sidebar_app_id</td><td>false</td></tr><tr><td>build_number</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>daily_cost</td><td>false</td></tr><tr><td>deadline</td><td>false</td></tr><tr><td>has_ai_task</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>initiator_by_avatar_url</td><td>false</td></tr><tr><td>initiator_by_name</td><td>false</td></tr><tr><td>initiator_by_username</td><td>false</td></tr><tr><td>initiator_id</td><td>false</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>max_deadline</td><td>false</td></tr><tr><td>provisioner_state</td><td>false</td></tr><tr><td>reason</td><td>false</td></tr><tr><td>template_version_id</td><td>true</td></tr><tr><td>template_version_preset_id</td><td>false</td></tr><tr><td>transition</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>workspace_id</td><td>false</td></tr></tbody></table> |
| WorkspaceBuild<br><i>start, stop</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>ai_task_sidebar_app_id</td><td>false</td></tr><tr><td>build_number</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>daily_cost</td><td>false</td></tr><tr><td>deadline</td><td>false</td></tr><tr><td>has_ai_task</td><td>false</td></tr><tr><td>has_external_agent</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>initiator_by_avatar_url</td><td>false</td></tr><tr><td>initiator_by_name</td><td>false</td></tr><tr><td>initiator_by_username</td><td>false</td></tr><tr><td>initiator_id</td><td>false</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>max_deadline</td><td>false</td></tr><tr><td>provisioner_state</td><td>false</td></tr><tr><td>reason</td><td>false</td></tr><tr><td>template_version_id</td><td>true</td></tr><tr><td>template_version_preset_id</td><td>false</td></tr><tr><td>transition</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>workspace_id</td><td>false</td></tr></tbody></table> |
| WorkspaceProxy<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>derp_enabled</td><td>true</td></tr><tr><td>derp_only</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>region_id</td><td>true</td></tr><tr><td>token_hashed_secret</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>url</td><td>true</td></tr><tr><td>version</td><td>true</td></tr><tr><td>wildcard_hostname</td><td>true</td></tr></tbody></table> |
| WorkspaceTable<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>automatic_updates</td><td>true</td></tr><tr><td>autostart_schedule</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deleting_at</td><td>true</td></tr><tr><td>dormant_at</td><td>true</td></tr><tr><td>favorite</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>next_start_at</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>ttl</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table> |
+2
View File
@@ -135,6 +135,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"archived": ActionTrack,
"source_example_id": ActionIgnore, // Never changes.
"has_ai_task": ActionIgnore, // Never changes.
"has_external_agent": ActionIgnore, // Never changes.
},
&database.User{}: {
"id": ActionTrack,
@@ -197,6 +198,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"template_version_preset_id": ActionIgnore, // Never changes.
"has_ai_task": ActionIgnore, // Never changes.
"ai_task_sidebar_app_id": ActionIgnore, // Never changes.
"has_external_agent": ActionIgnore, // Never changes.
},
&database.AuditableGroup{}: {
"id": ActionTrack,