feat: add name to workspace agent devcontainers (#17089)

In the presence of multiple devcontainers, it would be nice to
differentiate them by name. This change inherits the resource name from
terraform.

Refs #17076
This commit is contained in:
Mathias Fredriksson
2025-03-25 14:59:20 +02:00
committed by GitHub
parent 56082f3b83
commit 5c8cac9fb7
22 changed files with 808 additions and 748 deletions

View File

@ -244,6 +244,7 @@ func dbAgentDevcontainersToProto(devcontainers []database.WorkspaceAgentDevconta
for i, dc := range devcontainers {
ret[i] = &agentproto.WorkspaceAgentDevcontainer{
Id: dc.ID[:],
Name: dc.Name,
WorkspaceFolder: dc.WorkspaceFolder,
ConfigPath: dc.ConfigPath,
}

View File

@ -159,11 +159,13 @@ func TestGetManifest(t *testing.T) {
devcontainers = []database.WorkspaceAgentDevcontainer{
{
ID: uuid.New(),
Name: "cool",
WorkspaceAgentID: agent.ID,
WorkspaceFolder: "/cool/folder",
},
{
ID: uuid.New(),
Name: "another",
WorkspaceAgentID: agent.ID,
WorkspaceFolder: "/another/cool/folder",
ConfigPath: "/another/cool/folder/.devcontainer/devcontainer.json",
@ -283,10 +285,12 @@ func TestGetManifest(t *testing.T) {
protoDevcontainers = []*agentproto.WorkspaceAgentDevcontainer{
{
Id: devcontainers[0].ID[:],
Name: devcontainers[0].Name,
WorkspaceFolder: devcontainers[0].WorkspaceFolder,
},
{
Id: devcontainers[1].ID[:],
Name: devcontainers[1].Name,
WorkspaceFolder: devcontainers[1].WorkspaceFolder,
ConfigPath: devcontainers[1].ConfigPath,
},

View File

@ -260,6 +260,7 @@ func WorkspaceAgentDevcontainer(t testing.TB, db database.Store, orig database.W
WorkspaceAgentID: takeFirst(orig.WorkspaceAgentID, uuid.New()),
CreatedAt: takeFirst(orig.CreatedAt, dbtime.Now()),
ID: []uuid.UUID{takeFirst(orig.ID, uuid.New())},
Name: []string{takeFirst(orig.Name, testutil.GetRandomName(t))},
WorkspaceFolder: []string{takeFirst(orig.WorkspaceFolder, "/workspace")},
ConfigPath: []string{takeFirst(orig.ConfigPath, "")},
})

View File

@ -9171,6 +9171,7 @@ func (q *FakeQuerier) InsertWorkspaceAgentDevcontainers(_ context.Context, arg d
WorkspaceAgentID: arg.WorkspaceAgentID,
CreatedAt: arg.CreatedAt,
ID: id,
Name: arg.Name[i],
WorkspaceFolder: arg.WorkspaceFolder[i],
ConfigPath: arg.ConfigPath[i],
})

View File

@ -1600,7 +1600,8 @@ CREATE TABLE workspace_agent_devcontainers (
workspace_agent_id uuid NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
workspace_folder text NOT NULL,
config_path text NOT NULL
config_path text NOT NULL,
name text NOT NULL
);
COMMENT ON TABLE workspace_agent_devcontainers IS 'Workspace agent devcontainer configuration';
@ -1615,6 +1616,8 @@ COMMENT ON COLUMN workspace_agent_devcontainers.workspace_folder IS 'Workspace f
COMMENT ON COLUMN workspace_agent_devcontainers.config_path IS 'Path to devcontainer.json.';
COMMENT ON COLUMN workspace_agent_devcontainers.name IS 'The name of the Dev Container.';
CREATE TABLE workspace_agent_log_sources (
workspace_agent_id uuid NOT NULL,
id uuid NOT NULL,

View File

@ -0,0 +1 @@
ALTER TABLE workspace_agent_devcontainers DROP COLUMN name;

View File

@ -0,0 +1,4 @@
ALTER TABLE workspace_agent_devcontainers ADD COLUMN name TEXT NOT NULL DEFAULT '';
ALTER TABLE workspace_agent_devcontainers ALTER COLUMN name DROP DEFAULT;
COMMENT ON COLUMN workspace_agent_devcontainers.name IS 'The name of the Dev Container.';

View File

@ -3327,6 +3327,8 @@ type WorkspaceAgentDevcontainer struct {
WorkspaceFolder string `db:"workspace_folder" json:"workspace_folder"`
// Path to devcontainer.json.
ConfigPath string `db:"config_path" json:"config_path"`
// The name of the Dev Container.
Name string `db:"name" json:"name"`
}
type WorkspaceAgentLog struct {

View File

@ -12369,7 +12369,7 @@ func (q *sqlQuerier) UpdateUserStatus(ctx context.Context, arg UpdateUserStatusP
const getWorkspaceAgentDevcontainersByAgentID = `-- name: GetWorkspaceAgentDevcontainersByAgentID :many
SELECT
id, workspace_agent_id, created_at, workspace_folder, config_path
id, workspace_agent_id, created_at, workspace_folder, config_path, name
FROM
workspace_agent_devcontainers
WHERE
@ -12393,6 +12393,7 @@ func (q *sqlQuerier) GetWorkspaceAgentDevcontainersByAgentID(ctx context.Context
&i.CreatedAt,
&i.WorkspaceFolder,
&i.ConfigPath,
&i.Name,
); err != nil {
return nil, err
}
@ -12409,20 +12410,22 @@ func (q *sqlQuerier) GetWorkspaceAgentDevcontainersByAgentID(ctx context.Context
const insertWorkspaceAgentDevcontainers = `-- name: InsertWorkspaceAgentDevcontainers :many
INSERT INTO
workspace_agent_devcontainers (workspace_agent_id, created_at, id, workspace_folder, config_path)
workspace_agent_devcontainers (workspace_agent_id, created_at, id, name, workspace_folder, config_path)
SELECT
$1::uuid AS workspace_agent_id,
$2::timestamptz AS created_at,
unnest($3::uuid[]) AS id,
unnest($4::text[]) AS workspace_folder,
unnest($5::text[]) AS config_path
RETURNING workspace_agent_devcontainers.id, workspace_agent_devcontainers.workspace_agent_id, workspace_agent_devcontainers.created_at, workspace_agent_devcontainers.workspace_folder, workspace_agent_devcontainers.config_path
unnest($4::text[]) AS name,
unnest($5::text[]) AS workspace_folder,
unnest($6::text[]) AS config_path
RETURNING workspace_agent_devcontainers.id, workspace_agent_devcontainers.workspace_agent_id, workspace_agent_devcontainers.created_at, workspace_agent_devcontainers.workspace_folder, workspace_agent_devcontainers.config_path, workspace_agent_devcontainers.name
`
type InsertWorkspaceAgentDevcontainersParams struct {
WorkspaceAgentID uuid.UUID `db:"workspace_agent_id" json:"workspace_agent_id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
ID []uuid.UUID `db:"id" json:"id"`
Name []string `db:"name" json:"name"`
WorkspaceFolder []string `db:"workspace_folder" json:"workspace_folder"`
ConfigPath []string `db:"config_path" json:"config_path"`
}
@ -12432,6 +12435,7 @@ func (q *sqlQuerier) InsertWorkspaceAgentDevcontainers(ctx context.Context, arg
arg.WorkspaceAgentID,
arg.CreatedAt,
pq.Array(arg.ID),
pq.Array(arg.Name),
pq.Array(arg.WorkspaceFolder),
pq.Array(arg.ConfigPath),
)
@ -12448,6 +12452,7 @@ func (q *sqlQuerier) InsertWorkspaceAgentDevcontainers(ctx context.Context, arg
&i.CreatedAt,
&i.WorkspaceFolder,
&i.ConfigPath,
&i.Name,
); err != nil {
return nil, err
}

View File

@ -1,10 +1,11 @@
-- name: InsertWorkspaceAgentDevcontainers :many
INSERT INTO
workspace_agent_devcontainers (workspace_agent_id, created_at, id, workspace_folder, config_path)
workspace_agent_devcontainers (workspace_agent_id, created_at, id, name, workspace_folder, config_path)
SELECT
@workspace_agent_id::uuid AS workspace_agent_id,
@created_at::timestamptz AS created_at,
unnest(@id::uuid[]) AS id,
unnest(@name::text[]) AS name,
unnest(@workspace_folder::text[]) AS workspace_folder,
unnest(@config_path::text[]) AS config_path
RETURNING workspace_agent_devcontainers.*;

View File

@ -2110,22 +2110,25 @@ func InsertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
if devcontainers := prAgent.GetDevcontainers(); len(devcontainers) > 0 {
var (
devContainerIDs = make([]uuid.UUID, 0, len(devcontainers))
devContainerWorkspaceFolders = make([]string, 0, len(devcontainers))
devContainerConfigPaths = make([]string, 0, len(devcontainers))
devcontainerIDs = make([]uuid.UUID, 0, len(devcontainers))
devcontainerNames = make([]string, 0, len(devcontainers))
devcontainerWorkspaceFolders = make([]string, 0, len(devcontainers))
devcontainerConfigPaths = make([]string, 0, len(devcontainers))
)
for _, dc := range devcontainers {
devContainerIDs = append(devContainerIDs, uuid.New())
devContainerWorkspaceFolders = append(devContainerWorkspaceFolders, dc.WorkspaceFolder)
devContainerConfigPaths = append(devContainerConfigPaths, dc.ConfigPath)
devcontainerIDs = append(devcontainerIDs, uuid.New())
devcontainerNames = append(devcontainerNames, dc.Name)
devcontainerWorkspaceFolders = append(devcontainerWorkspaceFolders, dc.WorkspaceFolder)
devcontainerConfigPaths = append(devcontainerConfigPaths, dc.ConfigPath)
}
_, err = db.InsertWorkspaceAgentDevcontainers(ctx, database.InsertWorkspaceAgentDevcontainersParams{
WorkspaceAgentID: agentID,
CreatedAt: dbtime.Now(),
ID: devContainerIDs,
WorkspaceFolder: devContainerWorkspaceFolders,
ConfigPath: devContainerConfigPaths,
ID: devcontainerIDs,
Name: devcontainerNames,
WorkspaceFolder: devcontainerWorkspaceFolders,
ConfigPath: devcontainerConfigPaths,
})
if err != nil {
return xerrors.Errorf("insert agent devcontainer: %w", err)

View File

@ -2204,8 +2204,8 @@ func TestInsertWorkspaceResource(t *testing.T) {
Agents: []*sdkproto.Agent{{
Name: "dev",
Devcontainers: []*sdkproto.Devcontainer{
{WorkspaceFolder: "/workspace1"},
{WorkspaceFolder: "/workspace2", ConfigPath: "/workspace2/.devcontainer/devcontainer.json"},
{Name: "foo", WorkspaceFolder: "/workspace1"},
{Name: "bar", WorkspaceFolder: "/workspace2", ConfigPath: "/workspace2/.devcontainer/devcontainer.json"},
},
}},
})
@ -2220,7 +2220,10 @@ func TestInsertWorkspaceResource(t *testing.T) {
devcontainers, err := db.GetWorkspaceAgentDevcontainersByAgentID(ctx, agent.ID)
require.NoError(t, err)
require.Len(t, devcontainers, 2)
require.Equal(t, "foo", devcontainers[0].Name)
require.Equal(t, "/workspace1", devcontainers[0].WorkspaceFolder)
require.Equal(t, "", devcontainers[0].ConfigPath)
require.Equal(t, "bar", devcontainers[1].Name)
require.Equal(t, "/workspace2", devcontainers[1].WorkspaceFolder)
require.Equal(t, "/workspace2/.devcontainer/devcontainer.json", devcontainers[1].ConfigPath)
})