devstack

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Jul 16, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

forge:exclude-contract devstack is CLI-internal dev-stack orchestration glue (dev-block wiring, git-facts, lockfile) for `forge up`, not a contract-shaped service the bootstrap wires. Opt out of the require-contract rule.

Package devstack owns forge's parallel-dev-stack primitives: the raw git facts that distinguish one working tree from another, and a memoized port-block allocator. Together they let N dev stacks (one per git worktree) run in parallel against shared clusters without colliding — DECLARATIVELY: forge supplies the facts + the allocator, KCL composes them.

There is deliberately NO "instance" abstraction and NO user-visible index. forge exposes two raw git facts as KCL options and lets the KCL author decide which to key on:

option("worktree") -> the LINKED-worktree directory basename, or "" on
                      the PRIMARY checkout (any branch).
option("branch")   -> the current git branch, sanitized DNS-safe, always.

and one resolved builtin that hides the port arithmetic entirely:

forge.allocate_port(base, key) -> base + block(key)*100

where block(key) is a small int forge assigns the first time it sees key and persists (see blocks.go). The default — primary checkout, key "" — renders byte-identically to a stack with no dev-stack parameterization.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ActiveDArgs

func ActiveDArgs() []string

ActiveDArgs is the convenience the render paths call: the `-D` bindings to push the active git facts into KCL (nil for the default stack).

func AllocateBlock

func AllocateBlock(projectDir, key string) (int, error)

AllocateBlock returns the stable block index for key, assigning the next free one (≥1) on first use. key == "" is block 0 (the default stack) and is never stored or locked. Atomic under the registry lock.

func AllocatePort

func AllocatePort(projectDir string, base int, key string) (int, error)

AllocatePort is the engine behind the forge.allocate_port(base, key) KCL builtin. It returns base + block(key)*100, where block(key) is the small integer forge assigns the FIRST time it sees key and MEMOIZES in the lock-guarded registry. The block index is INTERNAL — it never surfaces in KCL; KCL only ever sees the final port.

Semantics (the contract):

  • key == "" ⇒ block 0 ⇒ returns base UNCHANGED, with no registry/lock touch (the byte-identical default-stack path).
  • One block PER KEY: every allocate_port(*, key) call for the same key shares that key's block, so all of a stack's ports shift by the SAME offset.
  • DETERMINISTIC: base + block*100, NO availability stepping. A port that must equal an externally-fixed value (a k3d pre-mapped host port; the host reliant's LISTEN port) must never step off a held port, so up and deploy — and the external mapping — always agree.

The registry read-modify-write happens entirely under the file lock, so a concurrent first-`up` of two worktrees cannot race two keys to the same block. Persistence makes the block stable across runs AND identical under both `forge up` and `forge deploy` (both call this through the same builtin), which is the permanent up-vs-deploy port fix.

func Branch

func Branch(projectDir string) string

Branch returns the current git branch for projectDir, sanitized DNS-safe, or "" outside a repo or on a detached HEAD. Unlike Worktree, Branch is reported for the primary checkout too — a consumer that WANTS to key on branch (e.g. a stack-per-branch workflow) can; one that wants the primary checkout to stay default keys on Worktree instead. The author chooses.

func Sanitize

func Sanitize(s string) string

Sanitize lowercases s and reduces it to a DNS-safe label: [a-z0-9-], collapsed dash runs, no leading/trailing dash, bounded length. Returns "" when nothing survives (e.g. an all-symbol branch name).

func SetActive

func SetActive(o Options)

SetActive records the git facts for this process's subsequent renders. Call once, before the first render, on the up/deploy path only.

func Worktree

func Worktree(projectDir string) string

Worktree returns the LINKED-worktree directory basename for projectDir, or "" on the PRIMARY checkout (regardless of branch) and outside any git repo. This is the fact a consumer keys on when it wants the primary checkout to stay the DEFAULT stack on every branch — the everyday dev loop is then byte-identical to today, and only a `git worktree add`'ed checkout gets its own stack.

The parallelism unit here is the WORKTREE, never the branch: branches change constantly and the primary checkout must always render default.

Detection: a linked worktree's per-worktree git dir (`git rev-parse --absolute-git-dir` → …/.git/worktrees/<name>) differs from the repo's common dir (`--git-common-dir` → the primary's …/.git). The primary checkout has them equal. This is git's own authoritative distinction — far more robust than sniffing whether `.git` is a file vs a directory (which submodules and some tooling also make a file). The returned value is sanitized DNS-safe.

Types

type Block

type Block struct {
	Key   string
	Index int
}

Block is one {key: block} registry entry, for diagnostics.

func List

func List(projectDir string) ([]Block, error)

List returns the block registry sorted by block index — for diagnostics / a future `forge stacks` command.

type Options

type Options struct {
	Worktree string // option("worktree"): linked-worktree basename, "" on primary
	Branch   string // option("branch"): sanitized current branch, always
}

Options are the raw git facts pushed INTO KCL as options for this forge command. The zero value (both fields "") is the default stack — it emits NO -D args, so a plain render sees option("worktree") == None (KCL default "") and option("branch") == None, rendering byte-identically to a stack with no dev-stack parameterization.

func Active

func Active() Options

Active returns the options set by SetActive (zero value when unset).

func Resolve

func Resolve(projectDir string) Options

Resolve gathers the git facts for projectDir. Cheap and side-effect-free (no files, no lock): the durable state lives in the block registry, which allocate_port touches lazily. Outside a repo both facts are "".

func (Options) DArgs

func (o Options) DArgs() []string

DArgs returns the `-D key=value` KCL option bindings that push these git facts into the render — the extension of the existing namespace/image_tag option seam. An empty fact is OMITTED (not emitted as ""), so the default stack returns NO args and renders byte-identically. Values are QUOTED KCL string literals so an all-digit worktree/branch name stays str, never an int (the same coercion fix as image_tag).

Jump to

Keyboard shortcuts

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