Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Nix

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
lint:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
extra-substituters = https://ekala-corepkgs.cachix.org
extra-trusted-public-keys = ekala-corepkgs.cachix.org-1:DcZV+vegWoEzacbSdXFXU4S7728C0eS9RfGpKeyHd6w=
- name: Nix Lint
run: nix fmt . -- --ci

eval:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@v30
with:
extra_nix_config: |
extra-substituters = https://ekala-corepkgs.cachix.org
extra-trusted-public-keys = ekala-corepkgs.cachix.org-1:DcZV+vegWoEzacbSdXFXU4S7728C0eS9RfGpKeyHd6w=
- name: Evaluate all Lua packages
run: ./ci/eval.sh
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ poly-repo nixpkgs fork.

```
default.nix # Entry point
pins.nix # Pinned external dependencies (core-pkgs, nix-lib)
pins.nix # Pinned external dependencies (core-pkgs, nix-lib), read from flake.lock
pkgs-module.nix # Module wiring: creates overlays from pkgs/
lua-packages.nix # System dependency overrides for Lua packages
top-level.nix # Non-Lua top-level package overrides
pkgs/ # Auto-discovered Lua package expressions
ci/ # Evaluation gate run by CI
```

## Adding a package
Expand Down Expand Up @@ -78,3 +79,15 @@ final: prev: {
nix-build -A lua.pkgs.luafilesystem
nix-build -E '(import ./. {}).lua.withPackages (ps: [ ps.lpeg ps.luafilesystem ])'
```

## Checks

CI runs both of these on every pull request:

```sh
./ci/eval.sh # every package in every lua.variants set must evaluate (aliases disabled)
nix fmt . -- --ci # formatting, using corepkgs' treefmt configuration
```

Pins live in `flake.lock`; `pins.nix` reads them, so update them with
`nix flake update`.
14 changes: 14 additions & 0 deletions ci/eval.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Evaluates every package in every `lua.variants.<variant>.pkgs` set.
#
# See ci/packages.nix for what counts as a failure.
#
# Usage:
# nix-instantiate --eval --strict ci/eval.nix

let
packages = import ./packages.nix { };
inherit (packages) probe targets;
in
builtins.deepSeq (map probe targets) {
evaluated = builtins.length targets;
}
33 changes: 33 additions & 0 deletions ci/eval.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Fails if any package in the repository fails to evaluate.
#
# See ci/eval.nix for what counts as a failure.

set -euo pipefail

cd "$(dirname "$0")/.."

stderr="$(mktemp)"
trap 'rm -f "$stderr"' EXIT

# Real failures are `abort`s, missing attributes and type errors, none of which
# `tryEval` can catch -- so they surface here as a non-zero exit with Nix's own
# message, which names the offending expression and its source location.
if ! result="$(nix-instantiate --eval --strict --json ci/eval.nix --show-trace --option allow-import-from-derivation false 2>"$stderr")"; then
cat "$stderr" >&2
exit 1
fi

# Nix's evaluation warnings (deprecated syntax, unclear path literals, ...) are
# errors here: they are cheap to fix and easy to accumulate unnoticed otherwise.
if grep -q '^warning:' "$stderr"; then
cat "$stderr" >&2
echo
echo "Evaluation emitted the warnings above; fix them or the job stays red."
exit 1
fi

# `{"evaluated":N}` -- extract the integer without needing a JSON parser.
count="$(sed -E 's/.*"evaluated":([0-9]+).*/\1/' <<<"$result")"

echo "All $count Lua packages evaluate across every Lua variant."
102 changes: 102 additions & 0 deletions ci/packages.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Enumerates every package in every Lua package set.
#
# Each variant in `lua.variants` (Lua 5.1 through 5.5 and each LuaJIT) has its
# own `pkgs` set, and the overrides in lua-packages.nix depend on the
# interpreter, so every set is covered. The rest of the package set comes from
# corepkgs, whose own CI evaluates it.
#
# Aliases are disabled. They are shims for a package already covered under its
# canonical name, so evaluating them only repeats work.
#
# When `checkMeta` is enabled, `handleEvalIssue` decides which rejections are bugs.
# `unknown-meta` and `broken-outputs` mean the `meta` itself is malformed, so
# they `abort` and name the package. Everything else -- broken, unfree,
# unsupported, insecure -- is a package correctly refusing to evaluate here,
# and `throw`s. So does `disabled = luaOlder ...`, which marks a package
# unsupported on that interpreter.
#
# What is left cannot be caught by `tryEval` and so fails the job with Nix's
# own message and source location: a missing `callPackage` argument, a missing
# attribute, or a type error. Those are the real bugs.

{
checkMeta ? false,
}:

let
pkgs = import ../. {
modules = [
{
config = {
aliases.nixpkgs = false;
inherit checkMeta;

handleEvalIssue =
reason: msg:
if
builtins.elem reason [
"unknown-meta"
"broken-outputs"
]
then
abort msg
else
throw msg;
};
}
];
};

inherit (pkgs) lib;
inherit (pkgs.lua) variants;

# Forcing `drvPath` resolves every dependency and, for ci/eval.nix, runs
# `check-meta`. `package` arrives unforced, so a lookup that throws is caught
# here too.
probe =
package:
let
value = builtins.tryEval package;
in
builtins.tryEval (
if value.success && lib.isDerivation value.value then
builtins.seq value.value.drvPath null
else
null
);

isBuildable =
value:
let
result = builtins.tryEval (lib.isDerivation value && builtins.seq value.drvPath true);
in
result.success && result.value;

# Defined in corepkgs and broken there, so nothing in this repository can fix
# them. Drop each entry once corepkgs is fixed and the pin bumped.
excluded = [
# pkgs-many/lua/luarocks/luarocks-nix.nix takes `nurl`, which corepkgs
# does not package.
"luarocks-nix"
];

# `<variant>.<package>`, e.g. `v5_1.luaposix`.
pairs = lib.concatMap (
variant:
let
set = variants.${variant}.pkgs;
in
map (name: {
name = "${variant}.${name}";
value = set.${name};
}) (builtins.filter (name: !builtins.elem name excluded) (builtins.attrNames set))
) (builtins.attrNames variants);
in
{
inherit probe;

targets = map (pair: pair.value) pairs;

# Attribute set of all buildable derivations, keyed by `<variant>.<package>`.
buildable = builtins.listToAttrs (builtins.filter (pair: isBuildable pair.value) pairs);
}
103 changes: 103 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 25 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
{
description = "Lua packages for poly-repo Nixpkgs";

outputs = { ... }: {
# Primary usage: import ./. {} (legacy, non-flake)
# This flake entry point is provided for convenience.
lib.eval = import ./.;
inputs = {
corepkgs.url = "github:ekala-project/corepkgs";
nix-lib.follows = "corepkgs/nix-lib";
systems.follows = "corepkgs/systems";
};

outputs =
{
corepkgs,
nix-lib,
systems,
...
}:
let
forAllSystems = nix-lib.lib.genAttrs (import systems);
in
{
legacyPackages = forAllSystems (
system:
import ./. {
inherit system;
}
);

formatter = corepkgs.formatter;
};
}
3 changes: 1 addition & 2 deletions lua-packages.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# System dependency overrides for Lua packages.
#
# Lua packages that require native/system libraries to build.
final: prev:
{
final: prev: {
}
26 changes: 17 additions & 9 deletions pins.nix
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
let
# Inherit pinning from flake.lock. `fetchGit` rather than `fetchTree` keeps
# evaluation working on Nix 2.3.
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
fetchLocked =
name:
let
node = lock.nodes.${name}.locked;
in
builtins.fetchGit {
url = "https://github.com/${node.owner}/${node.repo}.git";
inherit (node) rev;
};
in
{
core = builtins.fetchGit {
url = "https://github.com/ekala-project/corepkgs.git";
rev = "e4dd52af6f6329bffc97ec5ec782b5b30037f701";
};

lib = builtins.fetchGit {
url = "https://github.com/ekala-project/nix-lib.git";
rev = "9acd37c8934331a3e53a099f8755101bc2a149e2";
};
core = fetchLocked "corepkgs";
# `nix-lib` follows `corepkgs/nix-lib`, so use the node corepkgs points at.
lib = fetchLocked lock.nodes.corepkgs.inputs.nix-lib;
}
Loading
Loading