Documentation
¶
Overview ¶
internal/deps/builder.go
internal/deps/dockerfile.go
internal/deps/install.go
internal/deps/registry.go
Package deps provides dependency management for moat containers.
internal/deps/script.go
Index ¶
- Variables
- func AllSpecs() map[string]DepSpec
- func GenerateInstallScript(deps []Dependency) (string, error)
- func ImageTag(deps []Dependency, opts *ImageTagOptions) string
- func List() []string
- func SetVersionCache(c *versions.Cache)
- func Validate(deps []Dependency) error
- type DepSpec
- type Dependency
- type DockerMode
- type DockerfileOptions
- type DockerfileResult
- type HooksConfig
- type ImageTagOptions
- type InstallCommands
- type InstallType
- type ServiceDef
Constants ¶
This section is empty.
Variables ¶
var MoatInitScript string
Functions ¶
func GenerateInstallScript ¶
func GenerateInstallScript(deps []Dependency) (string, error)
GenerateInstallScript creates a bash install script for the given dependencies. The script is designed for Apple containers where Docker's layer caching is not available. Commands are idempotent and safe to re-run.
func ImageTag ¶
func ImageTag(deps []Dependency, opts *ImageTagOptions) string
ImageTag generates a deterministic image tag for a set of dependencies.
func SetVersionCache ¶
SetVersionCache allows tests to inject a custom cache.
func Validate ¶
func Validate(deps []Dependency) error
Validate checks that all dependency requirements are satisfied and versions are valid.
Types ¶
type DepSpec ¶
type DepSpec struct {
Description string `yaml:"description,omitempty"`
Type InstallType `yaml:"type"`
Default string `yaml:"default,omitempty"`
Versions []string `yaml:"versions,omitempty"`
Requires []string `yaml:"requires,omitempty"`
// For github-binary type
Repo string `yaml:"repo,omitempty"`
Asset string `yaml:"asset,omitempty"` // Supports {version}, {arch}, {target} placeholders
Bin string `yaml:"bin,omitempty"` // Supports {version}, {arch}, {target} placeholders
// Targets maps Go architecture names to project-specific target strings.
// Used for {target} placeholder substitution in Asset/Bin fields.
// Example: {"amd64": "x86_64-unknown-linux-musl", "arm64": "aarch64-unknown-linux-gnu"}
// If empty and {arch} is used, standard arch name mapping is applied.
Targets map[string]string `yaml:"targets,omitempty"`
// TagPrefix is the prefix used for release tags. Defaults to "v" if empty.
// Set to "none" for repos that don't use a prefix (e.g., ripgrep uses "14.1.1" not "v14.1.1").
// Set to a custom value for repos with non-standard prefixes (e.g., "bun-v" for bun).
TagPrefix string `yaml:"tag-prefix,omitempty"`
// Command is the name of the installed command if different from the dependency name.
// For example, ripgrep installs as "rg", not "ripgrep".
Command string `yaml:"command,omitempty"`
// Legacy ARM64 support (deprecated, use Targets instead)
AssetARM64 string `yaml:"asset-arm64,omitempty"`
BinARM64 string `yaml:"bin-arm64,omitempty"`
// For apt type
Package string `yaml:"package,omitempty"`
// For go-install type
GoPackage string `yaml:"go-package,omitempty"`
// For service type
Service *ServiceDef `yaml:"service,omitempty"`
// UserInstall indicates the dependency should be installed as the container
// user (moatuser) instead of root. This is needed for tools whose installers
// write to $HOME (e.g., claude-code's native installer).
UserInstall bool `yaml:"user-install,omitempty"`
}
DepSpec defines a dependency in the registry.
type Dependency ¶
type Dependency struct {
Name string // e.g., "node", "eslint"
Version string // e.g., "20" or "" for default
Type InstallType // Set for dynamic deps (npm:, pip:, etc.)
Package string // For dynamic deps: the package name/path
DockerMode DockerMode // For docker deps: "host" or "dind"
}
Dependency represents a parsed dependency from agent.yaml.
func FilterInstallable ¶
func FilterInstallable(deps []Dependency) []Dependency
FilterInstallable returns dependencies excluding services.
func FilterServices ¶
func FilterServices(deps []Dependency) []Dependency
FilterServices returns only service-type dependencies.
func Parse ¶
func Parse(s string) (Dependency, error)
Parse parses a dependency string like "node", "node@20", or "npm:eslint". For docker dependencies, supports "docker", "docker:host", or "docker:dind".
func ParseAll ¶
func ParseAll(specs []string) ([]Dependency, error)
ParseAll parses multiple dependency strings and validates them. Meta dependencies are expanded into their constituent dependencies. Dynamic dependencies (npm:, pip:, etc.) are handled directly.
func ResolveVersions ¶
func ResolveVersions(ctx context.Context, deps []Dependency) ([]Dependency, error)
ResolveVersions resolves partial version specifications to full versions for runtime dependencies (go, node, python). This uses a cache to avoid repeated API calls - resolved versions are cached for 24 hours.
For non-runtime dependencies or those without version resolvers, the original version is preserved unchanged.
Example: "go@1.22" might resolve to "go@1.22.12"
func (Dependency) ImplicitRequires ¶
func (d Dependency) ImplicitRequires() []string
ImplicitRequires returns dependencies that are implicitly required. For example, npm:eslint requires node.
func (Dependency) IsDynamic ¶
func (d Dependency) IsDynamic() bool
IsDynamic returns true if this dependency was parsed from a prefixed spec.
type DockerMode ¶
type DockerMode string
DockerMode defines how Docker is provided to the container.
const ( // DockerModeHost mounts the host Docker socket (fast but full host access). DockerModeHost DockerMode = "host" // DockerModeDind runs an isolated Docker daemon inside the container (privileged but isolated). DockerModeDind DockerMode = "dind" )
type DockerfileOptions ¶
type DockerfileOptions struct {
// NeedsSSH indicates SSH grants are present and the image needs
// openssh-client, socat, and the moat-init entrypoint for agent forwarding.
NeedsSSH bool
// SSHHosts lists the hosts for which SSH access is granted (e.g., "github.com").
// Known host keys will be added to /etc/ssh/ssh_known_hosts for these hosts.
SSHHosts []string
// NeedsClaudeInit indicates Claude Code configuration files need to be
// copied from a staging directory at container startup. This requires
// the moat-init entrypoint script.
NeedsClaudeInit bool
// NeedsCodexInit indicates Codex CLI configuration files need to be
// copied from a staging directory at container startup. This requires
// the moat-init entrypoint script.
NeedsCodexInit bool
// NeedsGeminiInit indicates Gemini CLI configuration files need to be
// copied from a staging directory at container startup. This requires
// the moat-init entrypoint script.
NeedsGeminiInit bool
// UseBuildKit enables BuildKit-specific features like cache mounts.
// When false, generates Dockerfiles compatible with the legacy builder.
// Defaults to true if not explicitly set (checked via useBuildKit method).
UseBuildKit *bool
// ClaudeMarketplaces are plugin marketplaces to register during image build.
ClaudeMarketplaces []claude.MarketplaceConfig
// ClaudePlugins are plugins to install during image build.
// Format: "plugin-name@marketplace-name"
ClaudePlugins []string
// Hooks contains user-defined lifecycle hook commands.
// PostBuild and PostBuildRoot are baked into the image as RUN commands.
// PreRun is passed to the init script to execute on every container start.
Hooks *HooksConfig
}
DockerfileOptions configures Dockerfile generation.
type DockerfileResult ¶
type DockerfileResult struct {
// Dockerfile is the generated Dockerfile content.
Dockerfile string
// ContextFiles maps relative file paths to their contents.
// These files should be written to the build context directory
// alongside the Dockerfile (e.g., "moat-init.sh" → script content).
ContextFiles map[string][]byte
}
DockerfileResult contains the generated Dockerfile and any additional context files that should be placed alongside the Dockerfile in the build context directory.
func GenerateDockerfile ¶
func GenerateDockerfile(deps []Dependency, opts *DockerfileOptions) (*DockerfileResult, error)
GenerateDockerfile creates a Dockerfile for the given dependencies.
type HooksConfig ¶
HooksConfig holds hook commands for Dockerfile generation and image tagging. This mirrors config.HooksConfig to avoid circular imports.
type ImageTagOptions ¶
type ImageTagOptions struct {
// NeedsSSH indicates the image needs SSH packages and init script.
NeedsSSH bool
// NeedsClaudeInit indicates the image needs the init script for Claude setup.
NeedsClaudeInit bool
// NeedsCodexInit indicates the image needs the init script for Codex setup.
NeedsCodexInit bool
// NeedsGeminiInit indicates the image needs the init script for Gemini setup.
NeedsGeminiInit bool
// ClaudePlugins are plugins baked into the image.
// Format: "plugin-name@marketplace-name"
ClaudePlugins []string
// Hooks contains user-defined lifecycle hook commands.
// Different hooks produce different image tags.
Hooks *HooksConfig
}
ImageTagOptions configures image tag generation.
type InstallCommands ¶
type InstallCommands struct {
Commands []string // Shell commands to run
EnvVars map[string]string // Environment variables to set
}
InstallCommands holds the commands needed to install a dependency.
func (InstallCommands) FormatForDockerfile ¶
func (ic InstallCommands) FormatForDockerfile() string
FormatForDockerfile formats install commands as Dockerfile RUN instructions.
func (InstallCommands) FormatForScript ¶
func (ic InstallCommands) FormatForScript() string
FormatForScript formats install commands as shell script lines.
type InstallType ¶
type InstallType string
InstallType defines how a dependency is installed.
const ( // Registry-based types (defined in registry.yaml) TypeRuntime InstallType = "runtime" TypeGithubBinary InstallType = "github-binary" TypeApt InstallType = "apt" TypeNpm InstallType = "npm" TypeGoInstall InstallType = "go-install" TypeCustom InstallType = "custom" TypeMeta InstallType = "meta" TypeUvTool InstallType = "uv-tool" // Tools installed via uv tool install TypeDocker InstallType = "docker" // Docker access via socket mounting or DinD TypeService InstallType = "service" // Service dependencies (databases, caches) // Dynamic types (parsed from prefixes like npm:eslint) TypeDynamicNpm InstallType = "dynamic-npm" // npm:package TypeDynamicPip InstallType = "dynamic-pip" // pip:package TypeDynamicUv InstallType = "dynamic-uv" // uv:package TypeDynamicCargo InstallType = "dynamic-cargo" // cargo:package TypeDynamicGo InstallType = "dynamic-go" // go:package )
func (InstallType) IsDynamic ¶
func (t InstallType) IsDynamic() bool
IsDynamic returns true if this is a dynamic (prefixed) dependency type.
func (InstallType) String ¶
func (t InstallType) String() string
String returns the string representation of an InstallType.
type ServiceDef ¶
type ServiceDef struct {
Image string `yaml:"image"`
Ports map[string]int `yaml:"ports"`
EnvPrefix string `yaml:"env_prefix"`
DefaultUser string `yaml:"default_user,omitempty"`
DefaultDB string `yaml:"default_db,omitempty"`
PasswordEnv string `yaml:"password_env,omitempty"`
ExtraEnv map[string]string `yaml:"extra_env,omitempty"`
ExtraCmd []string `yaml:"extra_cmd,omitempty"`
DBEnv string `yaml:"db_env,omitempty"`
ReadinessCmd string `yaml:"readiness_cmd"`
URLScheme string `yaml:"url_scheme"`
URLFormat string `yaml:"url_format"`
}
ServiceDef holds metadata for service-type dependencies (databases, caches). Parsed from the `service:` block in registry.yaml entries.