Files
coder/agent/agentcontainers/devcontainer.go

92 lines
3.2 KiB
Go

package agentcontainers
import (
"context"
"os"
"path/filepath"
"github.com/google/uuid"
"cdr.dev/slog"
"github.com/coder/coder/v2/codersdk"
)
const (
// DevcontainerLocalFolderLabel is the label that contains the path to
// the local workspace folder for a devcontainer.
DevcontainerLocalFolderLabel = "devcontainer.local_folder"
// DevcontainerConfigFileLabel is the label that contains the path to
// the devcontainer.json configuration file.
DevcontainerConfigFileLabel = "devcontainer.config_file"
// DevcontainerIsTestRunLabel is set if the devcontainer is part of a test
// and should be excluded.
DevcontainerIsTestRunLabel = "devcontainer.is_test_run"
// The default workspace folder inside the devcontainer.
DevcontainerDefaultContainerWorkspaceFolder = "/workspaces"
)
func ExtractDevcontainerScripts(
devcontainers []codersdk.WorkspaceAgentDevcontainer,
scripts []codersdk.WorkspaceAgentScript,
) (filteredScripts []codersdk.WorkspaceAgentScript, devcontainerScripts map[uuid.UUID]codersdk.WorkspaceAgentScript) {
devcontainerScripts = make(map[uuid.UUID]codersdk.WorkspaceAgentScript)
ScriptLoop:
for _, script := range scripts {
for _, dc := range devcontainers {
// The devcontainer scripts match the devcontainer ID for
// identification.
if script.ID == dc.ID {
devcontainerScripts[dc.ID] = script
continue ScriptLoop
}
}
filteredScripts = append(filteredScripts, script)
}
return filteredScripts, devcontainerScripts
}
// ExpandAllDevcontainerPaths expands all devcontainer paths in the given
// devcontainers. This is required by the devcontainer CLI, which requires
// absolute paths for the workspace folder and config path.
func ExpandAllDevcontainerPaths(logger slog.Logger, expandPath func(string) (string, error), devcontainers []codersdk.WorkspaceAgentDevcontainer) []codersdk.WorkspaceAgentDevcontainer {
expanded := make([]codersdk.WorkspaceAgentDevcontainer, 0, len(devcontainers))
for _, dc := range devcontainers {
expanded = append(expanded, expandDevcontainerPaths(logger, expandPath, dc))
}
return expanded
}
func expandDevcontainerPaths(logger slog.Logger, expandPath func(string) (string, error), dc codersdk.WorkspaceAgentDevcontainer) codersdk.WorkspaceAgentDevcontainer {
logger = logger.With(slog.F("devcontainer", dc.Name), slog.F("workspace_folder", dc.WorkspaceFolder), slog.F("config_path", dc.ConfigPath))
if wf, err := expandPath(dc.WorkspaceFolder); err != nil {
logger.Warn(context.Background(), "expand devcontainer workspace folder failed", slog.Error(err))
} else {
dc.WorkspaceFolder = wf
}
if dc.ConfigPath != "" {
// Let expandPath handle home directory, otherwise assume relative to
// workspace folder or absolute.
if dc.ConfigPath[0] == '~' {
if cp, err := expandPath(dc.ConfigPath); err != nil {
logger.Warn(context.Background(), "expand devcontainer config path failed", slog.Error(err))
} else {
dc.ConfigPath = cp
}
} else {
dc.ConfigPath = relativePathToAbs(dc.WorkspaceFolder, dc.ConfigPath)
}
}
return dc
}
func relativePathToAbs(workdir, path string) string {
path = os.ExpandEnv(path)
if !filepath.IsAbs(path) {
path = filepath.Join(workdir, path)
}
return path
}