Breaking Changes (MfGames Project Setup Flake)

In the beginning, I wanted to use NixOS options with the flake instead of using a mkConfig function to generate the files and shell hooks. But, due to complexities and struggling with Nix, I couldn't figure it out. But, after two years of working on it, I finally got a working implementation that uses the cleaner approach of options.

So that means instead of using mkLib, using mfgames-project-setup-flake means adding it as an input (as before), importing the model (that's new), and then using configuration settings (those are new).

The flake still needs to be added as an input:

inputs.mfgames-project-setup.url = "git+https://src.mfgames.com/nixos-contrib/mfgames-project-setup-flake.git";

It also now has a module which needs to be imported and then configured using the same syntax that most other configurations are used.

imports = [
    inputs.mfgames-project-setup.flakeModules.default
];

mfgames.project = {
    enable = true;
    rust.enable = true;
};

Then, in the mkShell call, the various hooks are called to integrate it.

devShells.default = pkgs.mkShell {
    packages = []
        ++ config.mfgames.project.packages;

    shellHook = config.mfgames.project.shellHook;
};

I also refactored how options where documented and displayed. It is now a script-generated file that is rebuild during the build process so I don't have to worry about getting it stale.

Versions

The old version is now v0.5.0 with the new version current at v1.1.0.

Breaking Changes

Since this is a really breaks existing setups, I'm also taking the opportunity to make other changes that have popped up in the last few years that I didn't want to be disruptive but I think will benefit the project in the long run.

REUSE

Probably the biggest one is stumbling onto REUSE Software and seeing a more nuanced (though complicated) specification for handling licenses that differ across files even in the same project. That is osmething I couldn't do but it resolved a number of issues I had after trying to integrate mfgames-writing-project-setup which is less code-oriented and more prose-oriented. After mulling over it, I decided to remove looking over the differencesand reasoning, I decided to integrate REUSE into the flake and remove the existing licensing handling.

This means removing the following keys from before:

  • creativeCommonsAttributionShareAlike.enable
  • creativeCommonsAttributionNonCommercialShareAlike.enable
  • mit.enable
  • mit.filename

And replacing it with:

  • mfgames.project.reuse.enable
  • mfgames.project.reuse.ignore-dot-config
  • mfgames.project.reuse.annotations

The most complicated part is that REUSE is “picky”. It requires every file to be properly licensed, so I introduced the ability to create the REUSE.toml annotations from the flake file which will be suppelemented by the automatic annotations from the generated files this flake produces.

mfgames.project.reuse.annotations = [
    {
        path = [
            "docs/**/*.md"
            "news/**/*.md"
            "README.md"
        ];

        SPDX-FileCopyrightText = "2026 Dylan Moonfire <contact@mfgames.com>";
        SPDX-License-Identifier = "CC-BY-4.0";
    }
    {
        path = "src/**/*.nix";
        SPDX-FileCopyrightText = "2026 Dylan Moonfire <contact@mfgames.com>";
        SPDX-License-Identifier = "MIT";
    }
];

I also consider most of the contents in .config to be generated files, so an annotation is added to mark all of those files as public domain unless turned off with mfgames.project.reuse.ignore-dot-config = false;.

Developer Certificate of Origin

I modified the setup so it adds the “Signed-off-by” to the bottom of Git commit messages if `mfgames.project.developerCertificateOfOrigin.enable = true".

Rust

I prefer a more vertical style of formatting in my code. That usually means I want braces on their own line for almost everything, including if statements. This was “on the same line” in the previous version, but now it defaults to braces on their own line.

Non-Breaking Changes

I found a consistent logging program that gives useful messages: gum. While the colors are not exactly my thing, I find it useful to have the same type of messages across the board. So you'll see a variety of functions now use that for logging, when easily done.

Project UUID

A few years ago, I stumbled onto a blog post about creating a “power ID” for projects. In effect, a UUIDv7 that uniquely identifies a project and make it easier to distinguish projects of the same same (such as Gemini the Protocol, Gemini the Cryptocurrency, and Gemini the LLM). That is why you see 019530bd-5065-731f-925b-3961eb7aa613 in almost every blog post and article I write about mfgames-project-setup-flake.

Since I've embraced that, I also modified this project to generate one if there is no .config/project-uuid.txt present in the project. This is intended to be checked in since it shouldn't change.

This functionality can be turned off with:

mfgames.project.project-uuid.enable = false;

Shell Formatting and Checking

I also recently started using shfmt and shellcheck for my shell scripts. I've introduced some options for this.

  • mfgames.project.shell.enable
  • mfgames.project.shell.check
  • mfgames.project.shell.format
  • mfgames.project.shell.includes

check and format use enable if not defined. And enable defaults to mfgames.project.enable.

If check is true, then just check-shellcheck or just check will run that utility against the files.

If format is true, then just format and just format-shfmt will format the shell script, as will commiting a file.

Metadata

Project

Categories: