# An equivalent of \`lib.hm.dag\`, or some other mechanism for ordering, in \`nixpkgs.lib\`

**URL:** https://discourse.nixos.org/t/an-equivalent-of-lib-hm-dag-or-some-other-mechanism-for-ordering-in-nixpkgs-lib/75195
**Category:** Help
**Created:** [February 10, 2026, 3:21pm UTC](https://discourse.nixos.org/t/an-equivalent-of-lib-hm-dag-or-some-other-mechanism-for-ordering-in-nixpkgs-lib/75195 "2026-02-10T15:21:33Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![TLATER](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tlater/32/4257_2.png) [@TLATER](https://discourse.nixos.org/u/TLATER)
#### Post date: [February 10, 2026, 3:21pm UTC](https://discourse.nixos.org/t/an-equivalent-of-lib-hm-dag-or-some-other-mechanism-for-ordering-in-nixpkgs-lib/75195/1 "2026-02-10T15:21:33Z")

</div>

I’d really like to be able to control the ordering of - at least - lists at merge-time in NixOS modules. I’ve recently seen a post in #Help where someone wanted something similar; though I can’t find it again right now.

The module system already contains a string-exclusive type capable of this ([strings-with-deps](https://github.com/NixOS/nixpkgs/blob/dfcc8a7bfb5b581331aeb110204076188636c7a2/lib/strings-with-deps.nix#L181:C17)), and home-manager has a more generic [`hm.lib.dag`](https://github.com/nix-community/home-manager/blob/6c4fdbe1ad198fac36c320fd45c5957324a80b8e/modules/lib/dag.nix), but as far as I can tell there is no way to do this with generic lists today.

Often, the order in lists is incidental, but as explained in [Does it matter what order things are listed in configuration.nix?](https://discourse.nixos.org/t/does-it-matter-what-order-things-are-listed-in-configuration-nix/13373), nix lists are ordered and the order does have practical effects. There are edge cases where the module system cannot unfold its usual power simply because an option uses `types.list`.

Am I overlooking an existing solution? Is there a specific reason an equivalent doesn’t exist in `nixpkgs.lib`? I find that `hm.lib.dag` isn’t particularly ergonomic, either, has there been experimentation or thought about something more flexible, even just at an API level?

> **Click here for more context in case you suspect an XY problem**
>
> My motivation is part of a drive to improve our CI infra at $dayjob, I’m trying to fix a lot of limitations we’re running into with GitHub actions.
> 
> I think I’ve stumbled upon a pretty nice way to do this with flake-parts through [github-actions-nix](https://github.com/synapdeck/github-actions-nix); _assuming_ something like `lib.hm.dag` exists.
> 
> I.e., my ultimate goal is to allow something like this (in pseudocode):
> 
> ```nix
> # org-wide, shared workflows.nix
> {
> perSystem.githubActions.workflows.foo = {
> name = "Example workflow";
> on.push.branches = ["main"];
> 
> jobs.build = {
> runsOn = "ubuntu-latest";
> 
> steps.foo = [
> {
> name = "foo";
> run = "exec foo";
> }
> ];
> };
> };    
> };
> }
> 
> ```
> 
> ```nix
> # workflows.nix in a project managed by a specific team
> { lib, ... }: {
> # Override upstream workflow's `foo` with the `foo` from unstable
> perSystem.githubActions.workflows.foo.jobs.build.steps = [
> (lib.mkBefore ["foo"] {
> name = "bar";
> run = "nix add nixpkgs-unstable#foo"
> })
> ];
> }
> 
> ```
> 
> Obviously `hm.lib.dag` doesn’t quite apply, but the use case should be obvious; this lets the downstream flake create a workflow that makes a small tweak to the upstream one, without having to take on ownership of the full workflow. Details like the `on` stanza don’t have to be repeated, and if the upstream workflow changes what a step does the downstream workflow continues to work as intended. There _are_ limitations, but I think this will generally help fix the unmaintainable (let alone auditable) mess of CI scripts we have.
> 
> Of course the example is very specific to my use case, but this kind of composition seems generally useful, and I think `nixpkgs.lib` could use something like it.
> 
> Sorry for making use of community goodwill for topics related to my employment, but hey, if nothing else this might indirectly get my employer to start paying some of y’all 😉

---

<div class="post-metadata">

### Author: ![Infinisil](https://discourse.nixos.org/user_avatar/discourse.nixos.org/infinisil/32/26523_2.png) [@Infinisil](https://discourse.nixos.org/u/Infinisil)
#### Post date: [February 10, 2026, 3:47pm UTC](https://discourse.nixos.org/t/an-equivalent-of-lib-hm-dag-or-some-other-mechanism-for-ordering-in-nixpkgs-lib/75195/2 "2026-02-10T15:47:45Z")

</div>

There’s nothing that could do this generally. I have a stalled PR for it though: [https://github.com/NixOS/nixpkgs/pull/97392](https://github.com/NixOS/nixpkgs/pull/97392)

---

<div class="post-metadata">

### Author: ![rhendric](https://discourse.nixos.org/user_avatar/discourse.nixos.org/rhendric/32/5699_2.png) [@rhendric](https://discourse.nixos.org/u/rhendric)
#### Post date: [February 10, 2026, 3:56pm UTC](https://discourse.nixos.org/t/an-equivalent-of-lib-hm-dag-or-some-other-mechanism-for-ordering-in-nixpkgs-lib/75195/3 "2026-02-10T15:56:19Z")

</div>

> [@TLATER](#):
>
> The module system already contains a string-exclusive type capable of this ([strings-with-deps](https://github.com/NixOS/nixpkgs/blob/dfcc8a7bfb5b581331aeb110204076188636c7a2/lib/strings-with-deps.nix#L181:C17))

What’s wrong with using this for generic values, exactly? Despite the name, you can put any value in `text` when you call `lib.textClosureList { foo = { deps = []; text = ...; }; }`.

---

<div class="post-metadata">

### Author: ![TLATER](https://discourse.nixos.org/user_avatar/discourse.nixos.org/tlater/32/4257_2.png) [@TLATER](https://discourse.nixos.org/u/TLATER)
#### Post date: [February 10, 2026, 3:57pm UTC](https://discourse.nixos.org/t/an-equivalent-of-lib-hm-dag-or-some-other-mechanism-for-ordering-in-nixpkgs-lib/75195/4 "2026-02-10T15:57:59Z")

</div>

Huh. Well, the name _is_ an issue for code readability reasons, but I might give that a shot for the time being.
