Skip to content

Add module builder #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Add module builder #48

wants to merge 7 commits into from

Conversation

pedorich-n
Copy link
Contributor

This PR adds a module interface to the builder derivation. This brings benefits such as strict options definition, better type-checks, and flexibility for future improvements or modifications.
I left the old builder in place for backward compatibility. In the future, it could be removed, and an "adapter" could be installed to convert old inputs into the new module system and maintain backward compatibility.

The module is inspired by @tomeon's nix-openwrt-imagebuilder-module project, but it's structured differently and the module itself is simpler. Please let me know if you feel it isn't fair to your work.

Opening this as a draft to gather opinions.
If everything is fine I will add module documentation and update README to tell users to use build-module in a follow-up PR to not pollute this one.

I also moved examples into a dedicated folder, since we have 4 of them now.

Closes #22

Copy link
Contributor Author

@pedorich-n pedorich-n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I would love for people to test this, maybe I missed some corner cases.
In my tests, I tried building with packages, folders, and individual files. I haven't tried disabling services, removing packages or anything else.

'';
};

subtarget = lib.mkOption {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I called it subtarget instead of variant, because it seems like OpenWRT uses this name.

Comment on lines +15 to +27
# TODO: move arch to profiles
detectedArch = hashedTarget.packagesArch;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

arch is already a property in profiles.json. I feel like it's more fitting to get this info from there, than from the feeds, since it's a property of a specific board/target

@astro
Copy link
Owner

astro commented Dec 1, 2024

Cc: @ehmry @adamcstephens @MakiseKurisu

@ehmry
Copy link
Contributor

ehmry commented Dec 2, 2024

I'd like to review but I haven't been using the imagebuilder (or openwrt).

@astro
Copy link
Owner

astro commented Dec 27, 2024

I like this. Please feel encouraged to follow through.

@pedorich-n
Copy link
Contributor Author

Thanks for your encouragement, @astro !

I've updated the docs module, exposing both markdown and json. At a certain iteration, I realized it looked almost like https://github.com/astro/microvm.nix/blob/2ae08de8e8068b00193b9cfbc0acc9dfdda03181/pkgs/doc.nix, so I just copied most of the stuff from there 😅
@SuperSandro2000 please have a look.

I also added support for "separate Kmods" and tested the build with both "old" (23.05.5) and "new" (24.10.0-rc4) versions. Builds fine.

@pedorich-n pedorich-n marked this pull request as ready for review January 5, 2025 07:24
@pedorich-n
Copy link
Contributor Author

Happy New Year everybody!

I've added a new package to generate/update module docs and a GitHub flow to do it from GHA.
I've also updated the documentation with a minimal example and a recommendation to use the builder module over the builder function.

I think this PR is ready for a proper review now.

@pedorich-n
Copy link
Contributor Author

Is there any chance I could get a review @SuperSandro2000 @astro ? 👀

Comment on lines +121 to +123
--replace "SHELL:=/usr/bin/env bash" "SHELL:=${pkgs.runtimeShell}" \
--replace "/usr/bin/env true" "${pkgs.coreutils}/bin/true" \
--replace "/usr/bin/env false" "${pkgs.coreutils}/bin/false"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use --replace-fail here?

release = lib.mkOption {
type = lib.types.nonEmptyStr;
default = latestRelease;
defaultText = lib.literalMD "Value of `latest-release.nix`";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
defaultText = lib.literalMD "Value of `latest-release.nix`";
defaultText = "Value of `latest-release.nix`";

literalMD doesn't exist anymore in unstable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would not commit this file and generate it on the fly for github pages or use https://github.com/nuschtos/search

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be happy to have the action build and push to GH pages like it is already happening over here: https://github.com/astro/microvm.nix/blob/main/.github/workflows/doc.yml

@SuperSandro2000
Copy link
Contributor

I would really need to try this to know fore sure if it works perfectly but I am not keen on bricking my router right now in case of any issues 😓

Copy link
Owner

@astro astro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you already said, if I merge the modules like this we're creating duplicate functionality in this project. Any intermediate PR would have to do twice the work.

That's why I am going to wait for the removal of the old code and the addition of a few shims.

];
}) options;

transformOptions = opt: opt // {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
transformOptions = opt: opt // {
# Fix source links in the generated options docs
transformOptions = opt: opt // {

if matches != [ ]
then builtins.getAttr (builtins.elemAt matches 0) variantFiles
else
builtins.throw ''
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
builtins.throw ''
throw ''

'';
};

rootFsPartSize = lib.mkOption {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: elsewhere you mention rootfs so I wonder if this shouldn't be rootfsPartSize?

Comment on lines +6 to 7
# TODO: rename to subtarget
, variant ? "generic"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# TODO: rename to subtarget
, variant ? "generic"
# DEPRECATED: use `subtarget`
, variant ? "generic"
, subtarget ? variant

Then alias the attrset with }@args and add lib.warnIf (args ? variant) "Using deprecated argument variant, use subtarget instead" before the result of this file (after the top-level let ... in).

@@ -24,6 +24,7 @@ in rec {
)
) hashes.targets
else
# TODO: check if file exists first
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we have to?

There's builtins.readDir and builtins.pathExists.

let
image = pkgs.callPackage ./examples/example-module.nix { inherit (self.lib) build-module; };
in
# Wrap `image` once to avoid `nix flake show` breaking on IFD
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be happy to have the action build and push to GH pages like it is already happening over here: https://github.com/astro/microvm.nix/blob/main/.github/workflows/doc.yml

Comment on lines +38 to +51
mkCopyStatement = file: ''
(
target_rel=${lib.escapeShellArg file.target}
target="files/''${target_rel#/}"
${lib.optionalString (lib.pathIsRegularFile file.source) ''
mkdir -p "$(dirname "''${target}")"
''}
cp -r --no-preserve=all "${file.source}" "''${target}"
)
'';

copyFiles = pkgs.writeScript "copy-openwrt-files" (
lib.concatLines (builtins.map mkCopyStatement config.files)
);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually prefer having once-used definitions inline for readability. The indentation isn't very deep here so I think it would be fine:

Suggested change
mkCopyStatement = file: ''
(
target_rel=${lib.escapeShellArg file.target}
target="files/''${target_rel#/}"
${lib.optionalString (lib.pathIsRegularFile file.source) ''
mkdir -p "$(dirname "''${target}")"
''}
cp -r --no-preserve=all "${file.source}" "''${target}"
)
'';
copyFiles = pkgs.writeScript "copy-openwrt-files" (
lib.concatLines (builtins.map mkCopyStatement config.files)
);
copyFiles = pkgs.writeScript "copy-openwrt-files" (
lib.concatMapStrings (file: ''
(
target_rel=${lib.escapeShellArg file.target}
target="files/''${target_rel#/}"
${lib.optionalString (lib.pathIsRegularFile file.source) ''
mkdir -p "$(dirname "''${target}")"
''}
cp -r --no-preserve=all "${file.source}" "''${target}"
)
'') config.files
);

@SuperSandro2000
Copy link
Contributor

SuperSandro2000 commented Apr 28, 2025

Me and @MarcelCoding have some interest in using this for future infrastructure. Hopefully we find some time bringing this forward together.

@pedorich-n
Copy link
Contributor Author

I'm sorry I haven't been active. I really want to see this working, but I struggled to find the willpower to get back to it.
The changes in this PR have grown quite large, and being asked to completely replace existing code within the same PR became overwhelming for me.

I'd still love to help if we can find a way to contribute incrementally.

@MarcelCoding
Copy link
Contributor

I've successfully deployed my testing AP using this PR in https://gitea.c3d2.de/zentralwerk/network/src/branch/openwrt-module. (I've used my fork to get up-to-date hashes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

PR to support modular interface?
5 participants