mirror of
https://gitlab.com/rensa-nix/core.git
synced 2026-02-02 07:15:08 +01:00
docs: write docs, add README
This commit is contained in:
parent
abe19f9f13
commit
a7e20e203c
8 changed files with 442 additions and 0 deletions
44
README.md
Normal file
44
README.md
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Rensa
|
||||||
|
|
||||||
|
Rensa is a powerful and flexible Nix flake framework designed to organize your Nix projects into logical units called "Cells".
|
||||||
|
It is heavily inspired by [divnix/std](https://github.com/divnix/std) but aims to provide a streamlined experience.
|
||||||
|
Feel free to check out std's awesome [docs](https://std.divnix.com/reference/std.html) too.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Cells**: Organize your code into functional domains (e.g., `backend`, `frontend`, `devops`).
|
||||||
|
- **Blocks**: Define types of outputs within a cell (e.g., `packages`, `devShells`, `nixosConfigurations`).
|
||||||
|
- **Actions**: Integrate with the CLI to run commands defined in your cells.
|
||||||
|
- **Cell Flakes**: Each cell can be its own flake, allowing for modular dependency management.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
1. **Initialize a Flake**: Create a `flake.nix` that uses `rensa`.
|
||||||
|
1. **Define Cells**: Create a `cells/` directory.
|
||||||
|
1. **Add Blocks**: Add `.nix` files in your cells to define outputs.
|
||||||
|
|
||||||
|
### Example `flake.nix`
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
|
ren.url = "gitlab:rensa-nix/core";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {ren, ...}@inputs: ren.buildWith {
|
||||||
|
inherit inputs;
|
||||||
|
cellsFrom = ./cells;
|
||||||
|
cellBlocks = with ren.blocks; [
|
||||||
|
(simple "packages")
|
||||||
|
(simple "devShells")
|
||||||
|
];
|
||||||
|
} {
|
||||||
|
packages = ren.select inputs.self [
|
||||||
|
["my-cell" "packages"]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [docs](https://rensa.projects.tf) for more.
|
||||||
|
|
@ -31,6 +31,11 @@ in
|
||||||
};
|
};
|
||||||
nav = [
|
nav = [
|
||||||
{"Introduction" = "index.md";}
|
{"Introduction" = "index.md";}
|
||||||
|
{"Concepts" = "concepts.md";}
|
||||||
|
{"Tutorial" = "tutorial.md";}
|
||||||
|
{"API Reference" = "api.md";}
|
||||||
|
{"Related Libraries" = "libraries.md";}
|
||||||
|
{"Direnv Integration" = "direnv.md";}
|
||||||
];
|
];
|
||||||
markdown_extensions = [
|
markdown_extensions = [
|
||||||
{
|
{
|
||||||
|
|
@ -41,6 +46,7 @@ in
|
||||||
"pymdownx.superfences"
|
"pymdownx.superfences"
|
||||||
"pymdownx.escapeall"
|
"pymdownx.escapeall"
|
||||||
"fenced_code"
|
"fenced_code"
|
||||||
|
"admonition"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
96
docs/api.md
Normal file
96
docs/api.md
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# API Reference
|
||||||
|
|
||||||
|
## `rensa.buildWith`
|
||||||
|
|
||||||
|
The main entry point for creating a Rensa flake.
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
- `inputs`: The flake inputs.
|
||||||
|
- `cellsFrom`: Path to the directory containing your cells.
|
||||||
|
- `cellBlocks`: A list of blocks to load for each cell.
|
||||||
|
- `transformInputs` (optional): A function to transform inputs before they are passed to cells.
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
A standard Nix flake output set.
|
||||||
|
|
||||||
|
## `rensa.build`
|
||||||
|
|
||||||
|
The underlying builder function used by `buildWith`. It returns the raw Rensa output structure without the recursive update functor.
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
- `inputs`: The flake inputs.
|
||||||
|
- `cellsFrom`: Path to the directory containing your cells.
|
||||||
|
- `cellBlocks`: A list of blocks to load for each cell.
|
||||||
|
- `transformInputs` (optional): A function to transform inputs.
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
|
||||||
|
An attribute set containing:
|
||||||
|
|
||||||
|
- `output`: The generated flake outputs.
|
||||||
|
- `__ren`: Internal metadata about the cells and blocks.
|
||||||
|
|
||||||
|
## `rensa.blocks`
|
||||||
|
|
||||||
|
Helper functions to define blocks.
|
||||||
|
|
||||||
|
### `simple`
|
||||||
|
|
||||||
|
```nix
|
||||||
|
simple "name"
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a block definition where the type matches the name.
|
||||||
|
|
||||||
|
### `dynamic`
|
||||||
|
|
||||||
|
```nix
|
||||||
|
dynamic "name"
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a block definition for dynamic content. This allows integration of the `std` cli
|
||||||
|
by passing through actions etc. from a cell.
|
||||||
|
|
||||||
|
Currently not really used.
|
||||||
|
|
||||||
|
## `rensa.select`
|
||||||
|
|
||||||
|
Helper to select specific outputs from the generated flake.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
select inputs.self [
|
||||||
|
["cellName" "blockName" "outputName"]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `rensa.filter`
|
||||||
|
|
||||||
|
Filters the generated flake outputs based on a predicate and paths.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
filter predicate inputs.self [
|
||||||
|
["cellName" "blockName" "outputName"]
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
- `predicate`: A function or boolean. If `true`, returns the attribute as is. If a function, it's used to filter the attributes of the target.
|
||||||
|
- `target`: The flake outputs (usually `inputs.self`).
|
||||||
|
- `paths`: A list of paths to select. Supports wildcards (`*`).
|
||||||
|
|
||||||
|
## `rensa.get`
|
||||||
|
|
||||||
|
Retrieves a single attribute from the flake outputs.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
get inputs.self ["cellName" "blockName" "outputName"]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Arguments
|
||||||
|
|
||||||
|
- `target`: The flake outputs.
|
||||||
|
- `path`: The path to the attribute to retrieve.
|
||||||
75
docs/concepts.md
Normal file
75
docs/concepts.md
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Concepts
|
||||||
|
|
||||||
|
Rensa is built around a few core concepts that help structure your Nix projects.
|
||||||
|
|
||||||
|
## Cells
|
||||||
|
|
||||||
|
A **Cell** is the fundamental unit of organization in Rensa.
|
||||||
|
It represents a functional domain or a component of your system.
|
||||||
|
For example, you might have cells for:
|
||||||
|
|
||||||
|
- `backend`: Your backend services.
|
||||||
|
- `frontend`: Your frontend applications.
|
||||||
|
|
||||||
|
Cells are directories located in the `cellsFrom` directory (usually `cells/` or `nix/`).
|
||||||
|
|
||||||
|
### Cell Flakes
|
||||||
|
|
||||||
|
A unique feature of Rensa is that each cell can be a self-contained Flake.
|
||||||
|
If a cell directory contains a `flake.nix`, Rensa will treat it as a flake and pass its outputs to the cell's blocks.
|
||||||
|
This allows you to manage dependencies at the cell level, keeping your top-level `flake.nix` clean.
|
||||||
|
|
||||||
|
!!! success "Advantage"
|
||||||
|
|
||||||
|
These nested flakes are also evaluated lazily, so inputs are only fetched if they are actually used.
|
||||||
|
|
||||||
|
## Blocks
|
||||||
|
|
||||||
|
A **Block** defines a specific type of output within a cell. Blocks are typically defined as `.nix` files within a cell directory.
|
||||||
|
Rensa provides different block types to handle various use cases.
|
||||||
|
|
||||||
|
### Simple Blocks
|
||||||
|
|
||||||
|
`rensa.blocks.simple` is the most common block type.
|
||||||
|
Use it to tell Rensa which blocks you have/it should load.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
blocks = with ren.blocks; [
|
||||||
|
(simple "hello")
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
This will tell Rensa to load any `hello.nix` or `hello/default.nix` in the cells.
|
||||||
|
It's required to be able to map these to flake outputs (eg. using `ren.select`).
|
||||||
|
|
||||||
|
### Dynamic Blocks
|
||||||
|
|
||||||
|
`rensa.blocks.dynamic` allows for more complex logic and can generate actions.
|
||||||
|
|
||||||
|
## Actions
|
||||||
|
|
||||||
|
**Actions** are commands that can be executed via the Std CLI.
|
||||||
|
They are defined within blocks and allow you to operationalize your Nix code.
|
||||||
|
For example, a `deploy` action in an `infra` cell could run the necessary commands to deploy your infrastructure.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Actions are also heavily inspired by Std, I added them to Rensa too, but nowadays
|
||||||
|
I don't see any real use cases for them. If you do, feel free to use and/or extend them :)
|
||||||
|
|
||||||
|
## Performance & Best Practices
|
||||||
|
|
||||||
|
### Single Instantiation of Nixpkgs
|
||||||
|
|
||||||
|
Instantiating `nixpkgs` (e.g., `import inputs.nixpkgs { inherit system; }`) is a computationally expensive operation. In a large project with many cells, doing this repeatedly for every cell or block can significantly slow down evaluation.
|
||||||
|
|
||||||
|
The recommended pattern in Rensa is to instantiate `nixpkgs` **once** in your top-level `flake.nix` and pass it down to your cells.
|
||||||
|
|
||||||
|
1. **Instantiate in `transformInputs`**: In your `flake.nix`, use the `transformInputs` argument of `buildWith` to add the instantiated `pkgs` to the inputs passed to cells.
|
||||||
|
1. **Use `i.parent.pkgs`**: In your cell flakes, access this pre-instantiated package set via `inputs.parent.pkgs`.
|
||||||
|
|
||||||
|
This ensures that `nixpkgs` is evaluated only once per system, drastically improving performance.
|
||||||
|
|
||||||
|
See [Related Libraries](./libraries.md) for examples of this pattern.
|
||||||
37
docs/direnv.md
Normal file
37
docs/direnv.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Direnv Integration
|
||||||
|
|
||||||
|
Rensa provides a custom `direnv` integration to make your development experience smoother.
|
||||||
|
It allows you to automatically load development shells defined in your cells.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
This integration is based on [nix-direnv](https://github.com/nix-community/nix-direnv)
|
||||||
|
but has been improved and optimized specifically for Rensa usage.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. **Create `.envrc`**: Add the following to your `.envrc` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source $(fetchurl https://gitlab.com/rensa-nix/direnv/-/raw/v0.3.0/direnvrc "sha256-u7+KEz684NnIZ+Vh5x5qLrt8rKdnUNexewBoeTcEVHQ=")
|
||||||
|
use ren //backend/devShells/default
|
||||||
|
```
|
||||||
|
|
||||||
|
This will automatically load the devShell `default` defined in `cells/backend/devShells.nix`.
|
||||||
|
|
||||||
|
1. **Allow Direnv**: Run `direnv allow` to trust the configuration.
|
||||||
|
|
||||||
|
## Updating
|
||||||
|
|
||||||
|
To update the `direnvrc` to the latest version (or a specific version), you can use `direnv fetchurl`.
|
||||||
|
|
||||||
|
1. **Run fetchurl**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
direnv fetchurl https://gitlab.com/rensa-nix/direnv/-/raw/v0.3.0/direnvrc
|
||||||
|
```
|
||||||
|
|
||||||
|
*Note: Replace `v0.3.0` with the desired version tag.*
|
||||||
|
|
||||||
|
1. **Update `.envrc`**: The command above will output a new hash.
|
||||||
|
Replace the previous version and hash in your `.envrc` with the new values.
|
||||||
|
|
@ -1 +1,30 @@
|
||||||
# Rensa Core
|
# Rensa Core
|
||||||
|
|
||||||
|
Welcome to the documentation for **Rensa**, a powerful and flexible Nix flake framework.
|
||||||
|
|
||||||
|
Rensa is designed to help you organize your Nix projects into logical units called **Cells**,
|
||||||
|
making your code more modular, maintainable, and scalable.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
If you are new to Rensa, we recommend starting with the [Tutorial](tutorial.md) to build your first project.
|
||||||
|
|
||||||
|
## Core Concepts
|
||||||
|
|
||||||
|
Understand the philosophy behind Rensa by reading about [Concepts](concepts.md), including:
|
||||||
|
|
||||||
|
- **Cells**: Functional domains of your project.
|
||||||
|
- **Blocks**: Typed outputs within cells.
|
||||||
|
- **Actions**: CLI commands for your cells.
|
||||||
|
|
||||||
|
## API Reference
|
||||||
|
|
||||||
|
For detailed information on Rensa's functions and helpers, check the [API Reference](api.md).
|
||||||
|
|
||||||
|
## Ecosystem
|
||||||
|
|
||||||
|
See [Related Libraries](libraries.md) to see how to extend Rensa with pre-built solutions for development shells, documentation, CI, and more.
|
||||||
|
|
||||||
|
## Further Reading
|
||||||
|
|
||||||
|
Rensa is inspired by `std`. For more in-depth information on the underlying concepts, you can refer to the [std Reference](https://std.divnix.com/reference/std.html).
|
||||||
|
|
|
||||||
47
docs/libraries.md
Normal file
47
docs/libraries.md
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Related Libraries
|
||||||
|
|
||||||
|
Rensa has a growing ecosystem of compatible libraries designed to work seamlessly with its cell structure.
|
||||||
|
These libraries typically expose a `lib` output that accepts `pkgs` as an argument.
|
||||||
|
|
||||||
|
## Available Libraries
|
||||||
|
|
||||||
|
Here are some common libraries you might want to use:
|
||||||
|
|
||||||
|
- [**Rensa Devshell**](https://devshell.rensa.projects.tf): _Minimal devshell implementation using Modules._
|
||||||
|
- [**Rensa Devtools**](https://devtools.rensa.projects.tf): _Utils and dev tools for the Rensa ecosystem._
|
||||||
|
- [**Rensa Utils**](https://utils.rensa.projects.tf): _Utilities for NixOS/darwin systems, home & disko configurations etc._
|
||||||
|
- [**Nix-GitLab-CI**](https://nix-gitlab-ci.projects.tf): _Allows (advanced) configuration of GitLab CI using Nix._
|
||||||
|
- [**Nixible**](https://nixible.projects.tf): _Ansible but with Nix._
|
||||||
|
- [**Tofunix**](https://tofunix.projects.tf): _Combining Nix and Terraform for reproducibility and developer experience._
|
||||||
|
- [**Nixlets**](https://nixlets.projects.tf): _Nixlets - like Helm Charts or Grafana Tanka but instead using Nix._
|
||||||
|
- [**Nixtest**](https://nixtest.projects.tf): _Test runner for Nix code._
|
||||||
|
- [**Soonix**](https://soonix.projects.tf): _Auto generated project files from Nix code, with gitignore handling and many generators._
|
||||||
|
- [**NixMkDocs**](https://nix-mkdocs.projects.tf): _Nix library for easy mkdocs integration into projects._
|
||||||
|
- [**Torikae**](https://torikae.projects.tf): _Simple CLI to replace versions in files._
|
||||||
|
|
||||||
|
## Usage Pattern
|
||||||
|
|
||||||
|
When using these libraries within a Cell Flake, you can instantiate them using the `pkgs` passed down from the parent flake.
|
||||||
|
This follows the "Single Instantiation" best practice.
|
||||||
|
|
||||||
|
### Example: `cells/mycell/flake.nix`
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
# Add the library to your inputs
|
||||||
|
devshell.url = "gitlab:rensa-nix/devshell?dir=lib";
|
||||||
|
|
||||||
|
# ... other inputs
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = i:
|
||||||
|
i
|
||||||
|
// {
|
||||||
|
# Instantiate the library using the parent's pkgs
|
||||||
|
dslib = i.devshell.lib { inherit (i.parent) pkgs; };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can use `inputs.dslib` in your blocks!
|
||||||
108
docs/tutorial.md
Normal file
108
docs/tutorial.md
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
# Tutorial
|
||||||
|
|
||||||
|
This tutorial will guide you through creating a new project using Rensa.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Nix installed with flakes enabled.
|
||||||
|
- Optionally `direnv`.
|
||||||
|
|
||||||
|
## Step 1: Initialize the Flake
|
||||||
|
|
||||||
|
Create a new directory for your project and initialize a `flake.nix`:
|
||||||
|
|
||||||
|
```nix title="flake.nix"
|
||||||
|
{
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
|
ren.url = "gitlab:rensa-nix/core";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {ren, self, ...}@inputs: ren.buildWith {
|
||||||
|
inherit inputs;
|
||||||
|
cellsFrom = ./nix;
|
||||||
|
cellBlocks = with ren.blocks; [
|
||||||
|
(simple "packages")
|
||||||
|
];
|
||||||
|
transformInputs = system: inputs: inputs // {
|
||||||
|
pkgs = import inputs.nixpkgs { inherit system; };
|
||||||
|
};
|
||||||
|
} {
|
||||||
|
packages = ren.select self [
|
||||||
|
["backend" "packages"]
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Create a Cell
|
||||||
|
|
||||||
|
Create a directory named `nix` and inside it, create a directory for your first cell, e.g., `backend`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p nix/backend
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 3: Add a Block
|
||||||
|
|
||||||
|
Inside `nix/backend`, create a file named `packages.nix`.
|
||||||
|
This will correspond to the `packages` block we defined in `flake.nix`.
|
||||||
|
|
||||||
|
Since we instantiated `pkgs` in the top-level `flake.nix`, we can access it via `inputs.pkgs`
|
||||||
|
(because we added it to inputs in `transformInputs`).
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
cell,
|
||||||
|
}: {
|
||||||
|
default = inputs.pkgs.hello;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Cell Flakes (Advanced)
|
||||||
|
|
||||||
|
If your cell is a flake (has a `flake.nix`), you can access the parent inputs via `inputs.parent`.
|
||||||
|
|
||||||
|
**`nix/backend/flake.nix`**:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs.common.url = "github:some/common-lib";
|
||||||
|
outputs = inputs: inputs // {
|
||||||
|
# inputs just for the current cell, for example:
|
||||||
|
common = inputs.common.lib {inherit (inputs.parent) pkgs;};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See [here](./libraries.md) for more information about this syntax.
|
||||||
|
|
||||||
|
**`cells/backend/packages.nix`**:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
inputs,
|
||||||
|
cell,
|
||||||
|
}: {
|
||||||
|
default = inputs.common.mkPackage { ... };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 4: Build
|
||||||
|
|
||||||
|
Now you can build your package using the standard Nix commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix build .#backend.packages.default
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you mapped it in `flake.nix`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix build .#default
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 5: Setting up Direnv
|
||||||
|
|
||||||
|
Rensa provides a custom `direnv` integration. See the [Direnv Integration](direnv.md) guide for setup instructions.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue