workspace

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: 13 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNoDevContainer = errors.New("no devcontainer configuration found")

ErrNoDevContainer is returned when no devcontainer configuration is found walking up from the start directory.

View Source
var ErrWorkspaceNotFound = errors.New("workspace not found")

ErrWorkspaceNotFound is returned when a workspace does not exist in the store.

Functions

func GenerateID added in v0.7.0

func GenerateID(projectRoot string) string

GenerateID creates a workspace ID from the project root's absolute path. Format: {slugified-basename}-{7-char-sha256-of-full-path}. The hash suffix guarantees uniqueness across directories with the same name.

func InferID added in v0.8.0

func InferID(configDir, dir, cwd string) (string, error)

InferID derives a workspace ID from the given directories without requiring workspace state to exist. It first tries normal devcontainer resolution (which walks up to find .devcontainer/), and falls back to slugifying the directory name if no devcontainer config is found. This allows cache commands to work even if the project was deleted or was never set up with crib.

Precedence: configDir > dir > cwd. When all three are empty, os.Getwd() is used as a fallback. Pass the working directory explicitly to avoid that call.

func Slugify

func Slugify(name string) string

Slugify converts a project directory name into a valid slug. Rules: lowercase, replace non-alphanumeric with hyphens, trim hyphens, truncate to 48 chars with hash suffix if longer.

Types

type LifecycleHook added in v0.7.1

type LifecycleHook map[string][]string

LifecycleHook is a map of named command entries. String/array hooks use the "" key; object hooks use named keys that run in parallel. This mirrors config.LifecycleHook but is redeclared here to avoid a dependency on the config package from workspace.

type Lock added in v0.8.0

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

Lock is a workspace file lock. Call Unlock to release it.

func (*Lock) Unlock added in v0.8.0

func (l *Lock) Unlock() error

Unlock releases the workspace lock.

type LookupOptions added in v0.8.0

type LookupOptions struct {
	ConfigDir string // explicit devcontainer config directory (from --config or .cribrc)
	Dir       string // explicit project directory (from --dir)
	Cwd       string // working directory fallback when ConfigDir and Dir are both empty
	Version   string // crib binary version recorded in the workspace CribVersion field
	Create    bool   // create the workspace if it does not exist in the store
}

LookupOptions controls how Lookup resolves and (optionally) creates a workspace.

type ResolveResult

type ResolveResult struct {
	// ProjectRoot is the absolute path to the project root directory.
	ProjectRoot string

	// ConfigPath is the absolute path to the devcontainer.json file.
	ConfigPath string

	// RelativeConfigPath is the config path relative to ProjectRoot.
	RelativeConfigPath string

	// WorkspaceID is the derived workspace identifier.
	WorkspaceID string
}

ResolveResult holds the outcome of workspace resolution.

func Resolve

func Resolve(startDir string) (*ResolveResult, error)

Resolve walks up from startDir looking for a .devcontainer/ directory or .devcontainer.json file. Returns the project root, config path, and derived workspace ID.

func ResolveConfigDir

func ResolveConfigDir(configDir string) (*ResolveResult, error)

ResolveConfigDir resolves workspace info when the devcontainer config directory is explicitly given (bypasses the walk-up). The config directory must contain a devcontainer.json directly. The project root is the parent of configDir.

type Result

type Result struct {
	// ContainerID is the Docker/Podman container ID.
	ContainerID string `json:"containerID"`

	// ImageName is the name of the built/pulled image.
	ImageName string `json:"imageName"`

	// MergedConfig is the devcontainer config after merging with image metadata.
	// Stored as raw JSON to avoid a dependency on the config package.
	MergedConfig json.RawMessage `json:"mergedConfig"`

	// WorkspaceFolder is the path inside the container where the project is mounted.
	WorkspaceFolder string `json:"workspaceFolder"`

	// RemoteEnv holds the resolved remoteEnv variables from devcontainer.json.
	// ${containerEnv:VAR} references are already substituted.
	// These should be injected via -e flags when running docker/podman exec.
	RemoteEnv map[string]string `json:"remoteEnv,omitempty"`

	// RemoteUser is the user to run commands as inside the container.
	// Passed as -u to docker/podman exec.
	RemoteUser string `json:"remoteUser,omitempty"`

	// SnapshotImage is the name of the snapshot image created after create-time
	// hooks completed. Used by restart to skip re-running those hooks.
	SnapshotImage string `json:"snapshotImage,omitempty"`

	// SnapshotHookHash is a hash of the create-time hook definitions at the time
	// the snapshot was taken. If hooks change, the snapshot is stale.
	SnapshotHookHash string `json:"snapshotHookHash,omitempty"`

	// HasFeatureEntrypoints is true when the image was built with features
	// that declare entrypoints (e.g. docker-in-docker). Used by restart
	// paths to know whether to override the container entrypoint.
	HasFeatureEntrypoints bool `json:"hasFeatureEntrypoints,omitempty"`

	// ComposeFilesHash is a short fingerprint (truncated SHA-256) of the
	// compose file contents at the time the result was saved. Used by restart
	// to detect changes inside compose files (volumes, ports, etc.) that are
	// invisible to devcontainer.json config comparison.
	ComposeFilesHash string `json:"composeFilesHash,omitempty"`

	// Feature lifecycle hooks, stored so the resume/restart path can dispatch
	// them without re-resolving features from OCI registries. These are the
	// hooks declared in devcontainer-feature.json files, NOT the user's hooks
	// from devcontainer.json. Per the spec, feature hooks run before user hooks.
	FeatureOnCreateCommands      []LifecycleHook `json:"featureOnCreateCommands,omitempty"`
	FeatureUpdateContentCommands []LifecycleHook `json:"featureUpdateContentCommands,omitempty"`
	FeaturePostCreateCommands    []LifecycleHook `json:"featurePostCreateCommands,omitempty"`
	FeaturePostStartCommands     []LifecycleHook `json:"featurePostStartCommands,omitempty"`
	FeaturePostAttachCommands    []LifecycleHook `json:"featurePostAttachCommands,omitempty"`
}

Result stores the outcome of a successful `crib up` run.

type Store

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

Store manages workspace state on disk at a base directory.

func NewStore

func NewStore() (*Store, error)

NewStore creates a Store at the default location (~/.crib/workspaces). The CRIB_HOME env var overrides the base directory: $CRIB_HOME/workspaces.

func NewStoreAt

func NewStoreAt(baseDir string) *Store

NewStoreAt creates a Store with a custom base directory. Useful for testing.

func (*Store) BaseDir added in v0.8.0

func (s *Store) BaseDir() string

BaseDir returns the store's base directory (e.g. ~/.crib/workspaces).

func (*Store) ClearHookMarkers

func (s *Store) ClearHookMarkers(id string) error

ClearHookMarkers removes all lifecycle hook markers for a workspace, allowing hooks to run again (used on recreate).

func (*Store) Delete

func (s *Store) Delete(id string) error

Delete removes a workspace directory from disk.

func (*Store) Exists

func (s *Store) Exists(id string) bool

Exists checks if a workspace exists on disk.

func (*Store) IsExplicitHome added in v0.8.0

func (s *Store) IsExplicitHome() bool

IsExplicitHome reports whether the store's base directory was set via the CRIB_HOME environment variable (as opposed to the default ~/.crib path).

func (*Store) IsHookDone

func (s *Store) IsHookDone(id, hookName string) bool

IsHookDone checks whether a lifecycle hook has already been executed.

func (*Store) List

func (s *Store) List() ([]string, error)

List returns all known workspace IDs.

func (*Store) Load

func (s *Store) Load(id string) (*Workspace, error)

Load reads a workspace config from disk.

func (*Store) LoadResult

func (s *Store) LoadResult(id string) (*Result, error)

LoadResult reads a build result from disk. Returns nil, nil if not found.

func (*Store) Lock added in v0.8.0

func (s *Store) Lock(ctx context.Context, id string) (*Lock, error)

Lock acquires an exclusive file lock for a workspace, preventing concurrent mutations (up, down, rebuild, restart, remove) from racing. The caller must defer lock.Unlock() to release it. The lock respects context cancellation so Ctrl+C works while waiting for a competing process.

func (*Store) MarkHookDone

func (s *Store) MarkHookDone(id, hookName string) error

MarkHookDone records that a lifecycle hook has been executed for a workspace.

func (*Store) Save

func (s *Store) Save(ws *Workspace) error

Save writes a workspace config to disk.

func (*Store) SaveResult

func (s *Store) SaveResult(id string, result *Result) error

SaveResult writes a build result to disk.

func (*Store) WorkspaceDir added in v0.4.0

func (s *Store) WorkspaceDir(id string) string

WorkspaceDir returns the on-disk directory for a workspace.

type Workspace

type Workspace struct {
	// ID is the workspace identifier, derived from the project directory name.
	ID string `json:"id"`

	// Source is the absolute path to the project root directory.
	Source string `json:"source"`

	// DevContainerPath is the relative path to the devcontainer config
	// from the project root (e.g., ".devcontainer/devcontainer.json").
	DevContainerPath string `json:"devContainerPath,omitempty"`

	// CribVersion is the version of crib that last touched this workspace.
	CribVersion string `json:"cribVersion,omitempty"`

	// CreatedAt is when this workspace was first created.
	CreatedAt time.Time `json:"createdAt"`

	// LastUsedAt is when this workspace was last accessed.
	LastUsedAt time.Time `json:"lastUsedAt"`
}

Workspace represents a crib workspace, which maps a local project directory to a devcontainer.

func Lookup added in v0.8.0

func Lookup(store *Store, opts LookupOptions, logger *slog.Logger) (*Workspace, error)

Lookup resolves a workspace from the given options. It checks ConfigDir, Dir, and Cwd (in that order) to locate the devcontainer config, then loads the workspace from the store. If the workspace does not exist and Create is true, it creates a new one. If Create is false, it returns ErrWorkspaceNotFound.

Jump to

Keyboard shortcuts

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