Skip to content

Restructure nullkomma as flake-parts modules (dendritic layout) - #154

Open
maxheld83 wants to merge 6 commits into
mainfrom
maxheld83-nullkomma-composability-design-review
Open

maxheld83 wants to merge 6 commits into
mainfrom
maxheld83-nullkomma-composability-design-review

Conversation

@maxheld83

Copy link
Copy Markdown
Contributor

nullkomma's goal is to hold all the non-project-specific boilerplate (devshells, formatting, checks, docs, CI, deploys), so that adopting repos carry just a short flake.nix and a flake.lock. The Makefile and template approach couldn't compose: a language couldn't extend a shared concern (for example, R adding air to treefmt), consumers had no typed knobs, and upgrades meant re-copying files. This PR rebuilds nullkomma as flake-parts modules that consumers import.

Fixes: #113

Approach

  • Modules consumers import: flakeModules.default, plus optional r, quarto and cloudflare-pages. A consumer's flake.nix is a nullkomma.lib.mkFlake call with imports = [ ... ] plus whatever nullkomma.* options it sets. A module extends shared concerns only when it is imported. For example, r adds air to treefmt, R to the devshell, *.Rcheck/ to .gitignore and R CMD check to checks.
  • Dendritic layout as a file convention only: every file under modules/ is a flake-parts module, collected by a small in-house lib/import-tree.nix. The layout adds no flake inputs.
  • Small consumer locks: nullkomma's own inputs are just nixpkgs, flake-parts and treefmt-nix, so a consumer lock has 5 nodes. Tools come from nixpkgs, not from extra flake inputs.
  • Typed knobs: for example nullkomma.r.extraPackages, nullkomma.r.check.errorOn, nullkomma.quarto.site.enable, nullkomma.cloudflare-pages.project and nullkomma.editor.vscode.*. R packages are read from DESCRIPTION.
  • Tasks replace the Makefile: nix run .#<task> for check, update, write-files, preview, render and deploy. Bare nix run lists them.
  • Generated files with a drift check: nix run .#write-files writes .gitignore, .envrc, .github/workflows/{push,cron}.yml and .vscode/*.json. checks.files fails when they're out of date. The workflows are thin stubs that call the reusable ci.yml and maintenance.yml in this repo.
  • Dev partition: flake-schemas, dogfooding and tests live in dev/ (a separate input flake, loaded through flake-parts partitions), so they never reach consumer locks.
  • Contract tests: checks.unit evaluates the md, R and Quarto test repos under tests/fixtures/ and the templates, and checks what each produces, for example that markdown-only repos get no R. Each test repo's devshell, treefmt, R CMD check and site are also built as checks.

Worth a careful look

  • Breaking for existing consumers:
    • templates/base and the Makefile are gone.
    • CI option ci.with is now ci.inputs, because with is a Nix keyword.
  • Dropped default formatters: prettier, beautysh, black, isort, cmake-format, hclfmt and sqlfluff.
  • jarl is opt-in: its tests fail to build on aarch64-darwin.
  • New option nullkomma.r.root: the default is self. A subpath like dirOf (self + "/DESCRIPTION") can't be used as a build source under lazy trees, so the source path is configurable.
  • The generated .gitignore re-includes the files nullkomma manages (!/.vscode/settings.json etc.). A global excludes file would otherwise hide them from the flake and break checks.files.
  • The CI stubs reference @main of nullkomma's reusable workflows.
  • nix-unit is removed in favour of lib.debug.runTests, which makes unpin nix-unit once nixpkgs has nixComponents_2_35聽#148 and remove nested list evaluation warning聽#143 obsolete. The Makefile replacement covers expose nicer task runner聽#136 and complete and add documentation for makefile聽#122.
  • Deferred: Python, and automatically running write-files during maintenance updates.

Verification

  • This repo: nix flake check passes on aarch64-darwin. That covers the unit and contract tests, R CMD check (Status: OK), the Quarto site with an executed R chunk, and the root site.
  • New consumer repo: I created a repo outside nullkomma from the r template. It locks to 5 nodes, and write-files, nix flake check and the devshell all work.
  • Not verified:
    • Linux systems;
    • building or running the wrangler deploy task;
    • the reusable workflows on GitHub (they first run on this PR).

maxheld83 and others added 6 commits October 8, 2026 18:39
Replace the Makefile and base template with flake-parts modules that
consumers import as aspects (flakeModules.{default,r,quarto,cloudflare-pages}),
discovered via an in-house import-tree (no extra inputs).

- core: devshell, treefmt, tasks (apps), generated files with drift
  check (.gitignore, .envrc, CI stubs, VS Code settings), site, github
- lang/r: R env from DESCRIPTION, air (jarl opt-in), R CMD check
- lang/quarto: quartoMinimal, site package, preview/render tasks, R composition
- deploy/cloudflare-pages: wrangler deploy task and CI wiring
- reusable ci.yml / maintenance.yml workflows called by generated stubs
- dev partition (flake-schemas, dogfooding) keeps consumer locks at 5 nodes
- contract tests: unit tests plus md/r/quarto fixtures and templates
- templates default/r/quarto; README rewritten

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Remove generated-file banners, preserve existing files when initializing, and keep scheduled maintenance only in nullkomma. Test downstream initialization and preservation of user edits.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Move flake-schemas into shared inputs and the default aspect. Test schema inventories for fixtures and templates, retain dev partitioning, and remove the now-empty dev input flake.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Per-system options are declared via mkPerSystemOption so they can be
documented; the reference is rendered into the Quarto site.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Dependencies come from read.dcf and tools::package_dependencies in a small
derivation; base packages are derived from the pinned R. Removes lib.r
parseDCF/depNames/depsFromDescription/basePackages and exposes
perSystem nullkomma.r.dependencies.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Read DESCRIPTION constraints with R, reuse nixpkgs package recipes, and initialize a user-owned PPM profile. Append dated snapshot pins during maintenance and test the snapshot/remote consumer contract. Document the initial resolver limits and transitive locking model.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

adopt configurable (flake?) derivations

1 participant