···1818| Phase 3 — Nix Install | 🚧 In progress | `scripts/install-nix-in-darling.sh`, `scripts/darling-nix`, `scripts/verify-nix.sh` |
1919| Phase 4 — Building | 🚧 Tooling ready | `scripts/build-trivial.sh` (new) |
2020| Phase 5 — Daemon | 🚧 Stubs done | `src/dirserv/` (new), `tests/dirserv/` (new) |
2121-| Phase 6 — CI | 🚧 In progress | `.github/workflows/nix.yml`, `tests/darling-smoke.nix`, `tests/nix-in-darling.nix` (new) |
2121+| Phase 6 — CI | 🚧 In progress | `.tangled/workflows/ci.yml`, `tests/darling-smoke.nix`, `tests/nix-in-darling.nix` (new) |
2222| Phase 7 — Remote Builder | 📋 Planned | — |
2323| Phase 8 — Stretch | 📋 Planned | — |
2424···130130 a Darling prefix in single-user mode.
131131- **Phase 3.4**: Created `scripts/darling-nix` — host-side wrapper for running
132132 Nix commands inside Darling without manual `darling shell bash -lc` boilerplate.
133133-- **Phase 6.3**: Created `.github/workflows/nix.yml` — Nix CI workflow with
134134- flake check, package build, devShell evaluation, and smoke tests.
133133+- **Phase 6.3**: Created `.tangled/workflows/ci.yml` — tangled.org CI workflow
134134+ with Cachix caching and `nix flake check`.
135135- **Phase 1.7**: Created `plan/syscall-triage.md` — tracking table for
136136 unimplemented syscalls with categories, impact levels, and discovery log.
137137- **Testing**: Created `tests/sandbox/test_sandbox_api.c` (C-level sandbox API
···151151| [plan/05-phase3-nix-install.md](./plan/05-phase3-nix-install.md) | Automated installer, verification, wrappers |
152152| [plan/06-phase4-building.md](./plan/06-phase4-building.md) | Trivial derivations → stdenv → binary substitution |
153153| [plan/07-phase5-daemon.md](./plan/07-phase5-daemon.md) | Multi-user mode, Directory Services stubs, launchd |
154154-| [plan/08-phase6-ci.md](./plan/08-phase6-ci.md) | NixOS VM tests, regression suite, GitHub Actions |
154154+| [plan/08-phase6-ci.md](./plan/08-phase6-ci.md) | NixOS VM tests, regression suite, tangled.org CI |
155155| [plan/09-phase7-remote-builder.md](./plan/09-phase7-remote-builder.md) | Darling as a `nix.buildMachines` target |
156156| [plan/10-phase8-stretch.md](./plan/10-phase8-stretch.md) | `aarch64-darwin`, GUI testing, Hydra builder |
157157| [plan/11-architecture.md](./plan/11-architecture.md) | System diagram, key technical decisions, glossary |
···163163164164```text
165165darling-nix/
166166-├── .github/workflows/nix.yml # Nix CI workflow (Phase 6)
166166+├── .tangled/workflows/ci.yml # tangled.org CI workflow (Phase 6)
167167├── flake.nix # Flake with package, devShell, NixOS module (Phase 0)
168168├── nix/
169169│ ├── package.nix # Darling Nix derivation (Phase 0)
···309309| 5.1 | ✅ | Directory Services stubs (`dseditgroup`, `sysadminctl`, `dscl`) |
310310| 6.1 | ✅ | NixOS VM test (`tests/nix-in-darling.nix`) |
311311| 6.2 | ✅ | Wired tests into `flake.nix` (checks output) |
312312-| 6.3 | ✅ | `.github/workflows/nix.yml` CI workflow |
312312+| 6.3 | ✅ | `.tangled/workflows/ci.yml` tangled.org CI workflow |
313313| 6.6 | ✅ | Darling smoke test (`tests/darling-smoke.nix`) |
314314| — | ✅ | `run-tests.sh` unified test runner (6 suites) |
315315| — | ✅ | `getattrlist` attribute buffer ordering bug fixed |
+51-94
plan/08-phase6-ci.md
···2323- Verify Nix compatibility.
2424- Test inside a NixOS VM (which is needed for namespace/overlay support).
25252626-We need to replace or supplement this with a Nix-native CI pipeline that runs
2727-real integration tests.
2626+We use [tangled.org](https://tangled.org) CI instead of GitHub Actions. Tangled
2727+provides a `nixery` engine that gives us a Nix-enabled container out of the box,
2828+eliminating the need for `install-nix-action` and simplifying the workflow. The
2929+workflow is defined in `.tangled/workflows/ci.yml`.
28302931---
3032···146148147149---
148150149149-### 6.3 — GitHub Actions Workflow ✅
151151+### 6.3 — tangled.org CI Workflow ✅
150152151151-Replace or supplement the existing `.github/workflows/actions.yaml` with a
152152-Nix-native workflow.
153153+Replace the GitHub Actions workflow with a tangled.org CI workflow using the
154154+`nixery` engine, which provides Nix out of the box.
153155154154-**Workflow file**: `.github/workflows/nix-ci.yaml`
156156+**Workflow file**: `.tangled/workflows/ci.yml`
155157156158```yaml
157157-name: Nix CI
159159+when:
160160+ - event: ["push", "pull_request"]
161161+ branch: main
158162159159-on:
160160- push:
161161- branches: [main]
162162- pull_request:
163163+engine: nixery
163164164164-jobs:
165165- build:
166166- runs-on: ubuntu-latest
167167- steps:
168168- - uses: actions/checkout@v4
169169- with:
170170- submodules: recursive
165165+environment:
166166+ USER: root
167167+ CACHIX_NAME: darling-nix
171168172172- - uses: cachix/install-nix-action@v27
173173- with:
174174- extra_nix_config: |
175175- experimental-features = nix-command flakes
169169+steps:
170170+ - name: "Setup Cachix"
171171+ command: |
172172+ nix-env -iA cachix -f https://cachix.org/api/v1/install
173173+ mkdir -p /tangled/home/.config/nix
174174+ echo -e "experimental-features = nix-command flakes\nmax-jobs = auto" > /tangled/home/.config/nix/nix.conf
175175+ cachix use $CACHIX_NAME
176176177177- - uses: cachix/cachix-action@v15
178178- with:
179179- name: darling-nix # our Cachix cache
180180- authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
177177+ - name: "Nix flake check"
178178+ command: |
179179+ rm -rf /homeless-shelter
180180+ ulimit -n 65536
181181+ cachix watch-exec $CACHIX_NAME -- nix flake check --max-jobs 1
181182182182- - name: Build Darling
183183- run: nix build .#darling -L
183183+ - name: "Build Darling"
184184+ command: |
185185+ cachix watch-exec $CACHIX_NAME -- nix build .#darling -L --no-link --print-out-paths
184186185185- - name: Build Darling SDK
186186- run: nix build .#darling-sdk -L
187187-188188- test-syscalls:
189189- runs-on: ubuntu-latest
190190- needs: build
191191- steps:
192192- - uses: actions/checkout@v4
193193- with:
194194- submodules: recursive
195195-196196- - uses: cachix/install-nix-action@v27
197197- with:
198198- extra_nix_config: |
199199- experimental-features = nix-command flakes
200200-201201- - uses: cachix/cachix-action@v15
202202- with:
203203- name: darling-nix
204204-205205- - name: Run syscall regression tests
206206- run: nix build .#checks.x86_64-linux.syscall-regression -L
207207-208208- test-nix-integration:
209209- runs-on: ubuntu-latest
210210- needs: build
211211- steps:
212212- - uses: actions/checkout@v4
213213- with:
214214- submodules: recursive
215215-216216- - uses: cachix/install-nix-action@v27
217217- with:
218218- extra_nix_config: |
219219- experimental-features = nix-command flakes
220220- system-features = kvm
221221-222222- - uses: cachix/cachix-action@v15
223223- with:
224224- name: darling-nix
225225-226226- - name: Run Nix-in-Darling integration test
227227- run: nix build .#checks.x86_64-linux.nix-in-darling -L
228228- timeout-minutes: 60 # generous timeout for VM test
187187+ - name: "Build Darling SDK"
188188+ command: |
189189+ cachix watch-exec $CACHIX_NAME -- nix build .#darling-sdk -L --no-link --print-out-paths
229190```
230191231192**Notes**:
232193233233-- The integration test requires KVM for the NixOS VM. GitHub's `ubuntu-latest`
234234- runners have KVM available. Verify with `system-features = kvm` in the Nix
235235- config.
236236-- The build job runs first and pushes artifacts to Cachix. Subsequent test jobs
237237- pull from the cache, avoiding redundant rebuilds.
238238-- The `timeout-minutes: 60` is important — Darling operations inside a VM inside
239239- CI can be very slow. Adjust as needed based on real-world timings.
240240-- `submodules: recursive` is required because Darling has 100+ submodules. This
241241- checkout step may itself take 5–10 minutes.
242242-243243-**Alternative: use a self-hosted runner** if GitHub's runners are too slow or
244244-lack KVM. A dedicated NixOS machine with nested virtualisation enabled would
245245-provide the most reliable CI environment.
194194+- tangled.org's `nixery` engine provides a Nix-enabled container, so there is
195195+ no need for `install-nix-action` or checkout actions — the repo is already
196196+ cloned and Nix is pre-installed.
197197+- Cachix is installed at runtime and used via `cachix watch-exec` to
198198+ automatically push all build artifacts. Subsequent runs pull from the cache,
199199+ avoiding redundant rebuilds.
200200+- `nix flake check` runs all flake checks (build smoke test, dirserv stubs,
201201+ etc.) in a single step. The `--max-jobs 1` flag prevents OOM on
202202+ memory-constrained CI runners.
203203+- The `CACHIX_NAME` environment variable should match the Cachix cache name.
204204+ The Cachix auth token must be configured as a tangled.org secret.
205205+- `rm -rf /homeless-shelter` works around a Nix sandbox issue in containerised
206206+ environments where `HOME` is set to a nonexistent path.
246207247208---
248209···5935545945553. **Incremental testing**: On PRs that only touch `plan/` or `docs/`, skip the
595556 expensive VM tests. Use path filters in the workflow:
596596- ```yaml
597597- on:
598598- push:
599599- paths-ignore:
600600- - 'plan/**'
601601- - '*.md'
602602- ```
557557+ In the tangled workflow, this can be handled at the application level by
558558+ checking changed paths in early steps, or by relying on Cachix cache hits
559559+ to make unchanged builds near-instant.
6035606045614. **Test VM snapshots**: If the NixOS testing framework supports it, take a
605562 snapshot after Darling initialization and restore from it for each test. This
···623580After completing Phase 6, ALL of the following should be true:
624581625582- [ ] `nix flake check` passes (includes build smoke test)
626626-- [ ] `.github/workflows/nix-ci.yaml` exists and runs on PRs
583583+- [ ] `.tangled/workflows/ci.yml` exists and runs on pushes/PRs to `main`
627584- [ ] Syscall regression tests exist for `lchflags`, `renameatx_np`, `utimensat` (at minimum)
628585- [ ] Sandbox stub tests verify `sandbox-exec` passthrough works
629586- [ ] NixOS VM test installs Nix inside Darling and evaluates an expression
630587- [ ] NixOS VM test builds a trivial derivation inside Darling
631631-- [ ] CI results are visible on GitHub PR checks
588588+- [ ] CI results are visible on tangled.org
632589- [ ] Cachix cache is populated by CI and speeds up subsequent runs
633590- [ ] Compatibility matrix script exists and produces JSON output
634591- [ ] Adding a new syscall implementation has a clear path: implement → add test → CI verifies