feature

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// FeatureFileName is the expected name for feature metadata files.
	FeatureFileName = "devcontainer-feature.json"

	// ContextFeatureFolder is the directory name used within the build context
	// for feature installation files.
	ContextFeatureFolder = ".crib-features"
)

Variables

This section is empty.

Functions

func FeatureEnvVars

func FeatureEnvVars(fc *FeatureConfig, userOptions any) []string

FeatureEnvVars converts feature options to sorted environment variable lines in the form SAFE_ID="value". User-provided options override defaults from the feature config.

func GenerateDockerfile

func GenerateDockerfile(features []*FeatureSet, containerUser, remoteUser string, cacheMounts []string) (content, prefix string)

GenerateDockerfile produces the Dockerfile content and prefix for installing features into the container image.

content is the main Dockerfile body (FROM, COPY, RUN layers). prefix is the syntax directive and base image ARG that must appear at the top of the final Dockerfile.

cacheMounts are BuildKit cache mount targets (e.g. "/var/cache/apt") to attach to each feature install RUN instruction. Pass nil to disable.

func PrepareContext

func PrepareContext(contextPath string, features []*FeatureSet, containerUser, remoteUser string) (string, error)

PrepareContext creates the feature installation directory within the build context. It copies feature folders as numbered directories (0, 1, 2, ...), writes environment files, and generates wrapper installation scripts. Returns the path to the features folder within the context.

Types

type BuildInfo

type BuildInfo struct {
	FeaturesFolder          string
	DockerfileContent       string
	DockerfilePrefixContent string
	OverrideTarget          string
	BuildArgs               map[string]string
}

BuildInfo holds the generated Dockerfile content and metadata for feature installation during the image build.

type CompositeResolver

type CompositeResolver struct {
	Local *LocalResolver
	OCI   *OCIResolver
	HTTP  *HTTPResolver
}

CompositeResolver dispatches to the appropriate resolver based on the feature reference format.

func NewCompositeResolver

func NewCompositeResolver(cache *FeatureCache) *CompositeResolver

NewCompositeResolver creates a CompositeResolver backed by the given cache.

func (*CompositeResolver) Resolve

func (r *CompositeResolver) Resolve(ref, configDir string) (string, error)

Resolve dispatches to the correct resolver based on the ref format.

type DependsOn

type DependsOn map[string]any

DependsOn holds hard dependencies as a map of feature IDs to their options. It rejects JSON arrays and strings, accepting only objects.

func (*DependsOn) UnmarshalJSON

func (d *DependsOn) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It accepts only JSON objects (or null), rejecting arrays and other types.

type FeatureCache

type FeatureCache struct {
	// contains filtered or unexported fields
}

FeatureCache is a disk cache for resolved features stored under ~/.crib/feature-cache/ (or $CRIB_HOME/feature-cache/).

Not safe for concurrent use. crib resolves features sequentially.

func NewFeatureCache

func NewFeatureCache() (*FeatureCache, error)

NewFeatureCache creates a FeatureCache at the default location. The CRIB_HOME env var overrides the base directory: $CRIB_HOME/feature-cache.

func NewFeatureCacheAt

func NewFeatureCacheAt(dir string) *FeatureCache

NewFeatureCacheAt creates a FeatureCache at a custom directory. Useful for testing.

func (*FeatureCache) BaseDir added in v0.7.1

func (c *FeatureCache) BaseDir() string

BaseDir returns the absolute path to the feature cache directory.

func (*FeatureCache) Clean added in v0.7.1

func (c *FeatureCache) Clean() error

Clean removes all cached feature entries.

func (*FeatureCache) Get

func (c *FeatureCache) Get(key string) (string, bool)

Get checks if a cached entry exists for the given key. Returns the path and true if the entry exists, or empty string and false if not.

func (*FeatureCache) IsEmpty added in v0.7.1

func (c *FeatureCache) IsEmpty() bool

IsEmpty returns true if the cache directory contains no entries.

func (*FeatureCache) Path

func (c *FeatureCache) Path(key string) string

Path returns the absolute path for a given cache key (may not exist).

func (*FeatureCache) Store

func (c *FeatureCache) Store(key string, populate func(dir string) error) (string, error)

Store creates the cache directory for the given key, calls populate to fill it, and rolls back by removing the directory on error.

type FeatureConfig

type FeatureConfig struct {
	ID            string                   `json:"id"`
	Name          string                   `json:"name,omitempty"`
	Version       string                   `json:"version,omitempty"`
	Description   string                   `json:"description,omitempty"`
	Entrypoint    string                   `json:"entrypoint,omitempty"`
	Deprecated    bool                     `json:"deprecated,omitempty"`
	Options       map[string]FeatureOption `json:"options,omitempty"`
	DependsOn     DependsOn                `json:"dependsOn,omitempty"`
	InstallsAfter []string                 `json:"installsAfter,omitempty"`
	CapAdd        []string                 `json:"capAdd,omitempty"`
	Init          *bool                    `json:"init,omitempty"`
	Privileged    *bool                    `json:"privileged,omitempty"`
	SecurityOpt   []string                 `json:"securityOpt,omitempty"`
	Mounts        []config.Mount           `json:"mounts,omitempty"`
	ContainerEnv  map[string]string        `json:"containerEnv,omitempty"`

	// Lifecycle hooks.
	OnCreateCommand      config.LifecycleHook `json:"onCreateCommand,omitempty"`
	UpdateContentCommand config.LifecycleHook `json:"updateContentCommand,omitempty"`
	PostCreateCommand    config.LifecycleHook `json:"postCreateCommand,omitempty"`
	PostStartCommand     config.LifecycleHook `json:"postStartCommand,omitempty"`
	PostAttachCommand    config.LifecycleHook `json:"postAttachCommand,omitempty"`
}

FeatureConfig represents a parsed devcontainer-feature.json file.

func ParseFeatureConfig

func ParseFeatureConfig(folder string) (*FeatureConfig, error)

ParseFeatureConfig reads and parses a devcontainer-feature.json from the given folder. The file is parsed as JSONC (JSON with comments).

type FeatureOption

type FeatureOption struct {
	Default     config.StrBool `json:"default,omitempty"`
	Description string         `json:"description,omitempty"`
	Type        string         `json:"type,omitempty"`
	Enum        []string       `json:"enum,omitempty"`
	Proposals   []string       `json:"proposals,omitempty"`
}

FeatureOption describes a single option that a feature accepts.

type FeatureSet

type FeatureSet struct {
	ConfigID string
	Folder   string
	Config   *FeatureConfig
	Options  any
}

FeatureSet pairs a feature's configuration with its resolved location and user-provided options from devcontainer.json.

func OrderFeatures

func OrderFeatures(features []*FeatureSet, overrideOrder []string) ([]*FeatureSet, error)

OrderFeatures sorts features respecting hard dependencies (DependsOn) and soft dependencies (InstallsAfter). Features listed in overrideOrder are moved to the front in that order, while still respecting hard dependencies.

type Graph

type Graph[T any] struct {
	// contains filtered or unexported fields
}

Graph is a generic directed acyclic graph that supports topological sorting via Kahn's algorithm. Node keys are strings, values are of type T.

func NewGraph

func NewGraph[T any]() *Graph[T]

NewGraph creates an empty graph.

func (*Graph[T]) AddEdge

func (g *Graph[T]) AddEdge(from, to string) error

AddEdge adds a directed edge from -> to, meaning "from" must come before "to" in the sorted output. Both nodes must already exist in the graph.

func (*Graph[T]) AddNode

func (g *Graph[T]) AddNode(key string, value T)

AddNode adds a node to the graph. If the node already exists, its value is updated.

func (*Graph[T]) HasNode

func (g *Graph[T]) HasNode(key string) bool

HasNode returns true if the graph contains a node with the given key.

func (*Graph[T]) Sort

func (g *Graph[T]) Sort() ([]T, error)

Sort returns nodes in topological order using Kahn's algorithm. When multiple nodes have zero in-degree, they are processed in sorted key order for deterministic output. Returns an error if the graph contains a cycle.

type HTTPResolver

type HTTPResolver struct {
	Cache  *FeatureCache
	Client *http.Client // nil uses http.DefaultClient
}

HTTPResolver resolves features from HTTPS URLs pointing to tar.gz archives.

func (*HTTPResolver) Resolve

func (r *HTTPResolver) Resolve(url, _ string) (string, error)

Resolve downloads and caches the feature tarball at the given HTTPS URL. configDir is unused for HTTP refs but kept for interface compatibility.

type LocalResolver

type LocalResolver struct{}

LocalResolver resolves features specified as relative paths (./ or ../).

func (*LocalResolver) Resolve

func (r *LocalResolver) Resolve(featureID, configDir string) (string, error)

Resolve handles feature IDs that are relative paths. It resolves them relative to the configDir and verifies the directory exists.

type OCIResolver

type OCIResolver struct {
	Cache *FeatureCache
}

OCIResolver resolves features from OCI registries. It caches resolved features to avoid redundant pulls.

func (*OCIResolver) Resolve

func (r *OCIResolver) Resolve(ref, configDir string) (string, error)

Resolve downloads and caches the feature at the given OCI ref. configDir is unused for OCI refs but kept for interface compatibility.

type Resolver

type Resolver interface {
	// Resolve returns the local folder path for the given feature ID.
	// configDir is the directory containing the devcontainer.json that
	// references this feature.
	Resolve(featureID, configDir string) (string, error)
}

Resolver resolves a feature ID to a local folder path containing the feature's files (devcontainer-feature.json, install.sh, etc.).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL