Replace the stub dev-env with the real, working implementation that grew
in the reference machine config — de-identified for the public scaffold.
Nix layer:
- options.nix: full project schema (url/upstream/fork/category/
worktreeRoot/worktrees{branch,path,remote}/isClone/deployFlakeInput),
deploy.targets, github.forkUser, writeDirenvHints. Drops the
forgejo-URL block + deploy-flake auto-derivation (incoherent in a
scaffold that uses explicit per-project urls).
- lib.nix: mkProject + worktreePath/bareRepoPath/projectRemotes,
generalized to the explicit-url model (origin falls back to upstream).
- config.nix: renders /etc/dev-env/{config.sh,projects.json,
tmux-sessions.json}, installs helpers via writeShellScriptBin, loads
shell functions into interactive shells, wires the git pre-commit hook.
Scripts (config-driven, read /etc/dev-env at runtime):
- bootstrap.sh, nav.sh, worktree.sh, pr-helpers.sh, rebase.sh,
status.sh, deploy.sh, regtest.sh, tmux-launch.sh.
- Stripped aiolabs/forgejo/bitspire/lamassu/webapp hardcoding; the
github-fork remote is renamed 'fork' to match git.remotes vocabulary.
- Removes the dev.sh stub (the matured impl uses discrete commands +
shell functions, not a unified 'dev' CLI).
presets/example.nix: a worked, generic project list replacing the
identity-specific aiolabs preset. tests/smoke.nix + flake checks
exercise the schema; 'nix flake check' is green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
121 lines
3.4 KiB
Nix
121 lines
3.4 KiB
Nix
# lnbits-sensei dev-env — helpers.
|
|
#
|
|
# dev-env-internal helpers scoped to this module (project path
|
|
# resolution, worktree-path expansion, remote construction) rather than
|
|
# the global `lnbits-sensei.lib` namespace. Exposed as
|
|
# `config.lnbits-sensei.devEnv.lib` so config.nix and the example preset
|
|
# can build project entries with less boilerplate.
|
|
{ config, lib, ... }:
|
|
|
|
let
|
|
inherit (lib) mkOption types;
|
|
cfg = config.lnbits-sensei.devEnv;
|
|
|
|
# mkProject: shorthand constructor for `devEnv.projects.<name>`.
|
|
#
|
|
# Fills in conventional defaults so consumers write less boilerplate.
|
|
# The returned attrset matches the `projectType` submodule schema.
|
|
#
|
|
# mkProject {
|
|
# name = "lnbits";
|
|
# url = "git@git.example.com:you/lnbits.git";
|
|
# upstream = "https://github.com/lnbits/lnbits";
|
|
# worktrees = { main.branch = "main"; dev.branch = "dev"; };
|
|
# }
|
|
mkProject =
|
|
{
|
|
name ? null,
|
|
category ? null,
|
|
url ? null, # origin remote URL
|
|
upstream ? null,
|
|
fork ? null, # defaults from github.forkUser when upstream is set
|
|
worktrees ? { },
|
|
isClone ? false,
|
|
deployFlakeInput ? null,
|
|
worktreeRoot ? null, # defaults to name
|
|
}:
|
|
{
|
|
inherit
|
|
url
|
|
upstream
|
|
category
|
|
isClone
|
|
deployFlakeInput
|
|
;
|
|
fork =
|
|
if fork != null then
|
|
fork
|
|
else if upstream != null && cfg.github.forkUser != null && name != null then
|
|
"git@github.com:${cfg.github.forkUser}/${name}.git"
|
|
else
|
|
null;
|
|
worktreeRoot =
|
|
if worktreeRoot != null then
|
|
worktreeRoot
|
|
else if name != null then
|
|
name
|
|
else
|
|
"";
|
|
inherit worktrees;
|
|
};
|
|
|
|
# Resolve worktree filesystem paths. Projects with a category live
|
|
# under ${root}/${category}/${worktreeRoot}/<worktree>; otherwise
|
|
# ${root}/${worktreeRoot}/<worktree>.
|
|
worktreePath =
|
|
_projectName: project: worktreeName:
|
|
let
|
|
root = cfg.root;
|
|
sub =
|
|
if project.category != null then
|
|
"${project.category}/${project.worktreeRoot}"
|
|
else
|
|
project.worktreeRoot;
|
|
leaf =
|
|
let
|
|
wt = project.worktrees.${worktreeName} or null;
|
|
in
|
|
if wt != null && wt.path != null then wt.path else worktreeName;
|
|
in
|
|
"${root}/${sub}/${leaf}";
|
|
|
|
# Bare repo path (always ${root}/repos/<basename>.git). The basename
|
|
# is derived from the project name; the bare object DB is shared by
|
|
# every worktree of the project.
|
|
bareRepoPath = projectName: _project: "${cfg.root}/repos/${projectName}.git";
|
|
|
|
# Construct the remotes for a project. `origin` is `url` if set,
|
|
# otherwise falls back to `upstream` (pure-upstream tracking repo).
|
|
# Projects with neither end up with no origin (filtered out).
|
|
projectRemotes =
|
|
project:
|
|
lib.filterAttrs (_: v: v != null) {
|
|
origin =
|
|
if project.url != null then
|
|
project.url
|
|
else
|
|
project.upstream;
|
|
upstream = project.upstream;
|
|
fork = project.fork;
|
|
};
|
|
|
|
helpers = {
|
|
inherit
|
|
mkProject
|
|
worktreePath
|
|
bareRepoPath
|
|
projectRemotes
|
|
;
|
|
};
|
|
in
|
|
{
|
|
options.lnbits-sensei.devEnv.lib = mkOption {
|
|
type = types.attrs;
|
|
internal = true;
|
|
description = "dev-env-internal helpers (see modules/dev-env/lib.nix).";
|
|
};
|
|
|
|
config = {
|
|
lnbits-sensei.devEnv.lib = helpers;
|
|
};
|
|
}
|