Skip to content
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

feature: nixpkgs_flake_package #380

Merged
merged 5 commits into from
May 16, 2023
Merged

feature: nixpkgs_flake_package #380

merged 5 commits into from
May 16, 2023

Conversation

rickvanprim
Copy link
Contributor

Introduces a new repository rule nixpkgs_flake_package that invokes nix build <label>#<package> and makes the output available as a Bazel repository. This allows all the Nix version pinning to happen as part of the Nix Flake functionality with flake.lock and simplifies the Bazel side implementation by not having to fetch nixpkgs (or any other Nix repositories) outside of Nix and inject them in.

Contributes to #348.

@rickvanprim rickvanprim requested a review from benradf as a code owner May 5, 2023 17:11
@@ -1,4 +1,4 @@
"""<!-- Edit the docstring in `core/nixpkgs.bzl` and run `bazel run //docs:update-README.md` to change this repository's `README.md`. -->
"""<!-- Edit the docstring in `core/nixpkgs.bzl` and run `bazel run @rules_nixpkgs_docs//:update-readme` to change this repository's `README.md`. -->
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to match //nixpkgs/nixpkgs.bzl.

core/nixpkgs.bzl Outdated
@@ -453,6 +454,7 @@ def _nixpkgs_package_impl(repository_ctx):
else:
# No user supplied build file, we may create the default one.
create_build_file_if_needed = True

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Auto-added by Buildifier.

core/nixpkgs.bzl Outdated
Comment on lines 691 to 717
# Is nix supported on this platform?
not_supported = not is_supported_platform(repository_ctx)

# Should we fail if Nix is not supported?
fail_not_supported = repository_ctx.attr.fail_not_supported

if not_supported and fail_not_supported:
fail("Platform is not supported: `nix` not found in PATH. See attribute `fail_not_supported` if you don't want to use Nix.")
elif not_supported:
return

# If true, a BUILD file will be created from a template if it does not
# exist.
# However this will happen AFTER the nix-build command.
create_build_file_if_needed = False
if repository_ctx.attr.build_file and repository_ctx.attr.build_file_content:
fail("Specify one of 'build_file' or 'build_file_content', but not both.")
elif repository_ctx.attr.build_file:
repository_ctx.symlink(repository_ctx.attr.build_file, "BUILD")
elif repository_ctx.attr.build_file_content:
repository_ctx.file("BUILD", content = repository_ctx.attr.build_file_content)
else:
# No user supplied build file, we may create the default one.
create_build_file_if_needed = True

# Workaround to bazelbuild/bazel#4533
repository_ctx.path("BUILD")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could potentially be pulled out of here and nixpkgs_package(). I don't think there's a good way to deduplicate the docstring though?

Copy link
Member

Choose a reason for hiding this comment

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

Factoring out the common parts between nixpkgs_package and nixpkgs_flake_package would be great. There is a fair bit of complexity around invoking Nix that was tricky to get right. I'd be wary of duplicating it and risk it diverging.

Comment on lines +719 to +721
nix_flake_file_deps = {}
for dep_lbl, dep_str in repository_ctx.attr.nix_flake_file_deps.items():
nix_flake_file_deps[dep_str] = cp(repository_ctx, dep_lbl)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This could potentially be grouped with the expand_location() call below and pulled out to be shared with nixpkgs_package().

Comment on lines +743 to +751
expr_args.extend([
expand_location(
repository_ctx = repository_ctx,
string = opt,
labels = nix_flake_file_deps,
attr = "nixopts",
)
for opt in repository_ctx.attr.nixopts
])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above.

core/nixpkgs.bzl Outdated
Comment on lines 791 to 796
# Create a default BUILD file only if it does not exists and is not
# provided by `build_file` or `build_file_content`.
if create_build_file_if_needed:
p = repository_ctx.path("BUILD")
if not p.exists:
repository_ctx.template("BUILD", Label("@rules_nixpkgs_core//:BUILD.bazel.tpl"))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could potentially be pulled into the BUILD file function mentioned above.

nix_flake_file,
nix_flake_lock_file,
nix_flake_file_deps = [],
package = None,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would attribute_path be a better name than package? That would be consistent with nixpkgs_package(). I chose package here initially as it matches the name of one of the known Flake output fields.

@rickvanprim
Copy link
Contributor Author

Looking at //tests, it looks like there's only really one test right now. Should I copy-paste invalid_nixpkgs_package (directory and shell script) to make a test for nixpkgs_flake_package or what's the expectation as far as adding tests? 🙂

@aherrmann
Copy link
Member

Looking at //tests, it looks like there's only really one test right now.

The tests for core live under testing/core. See #319 for motivation and further details.

Further tests for core should also go there.

core/nixpkgs.bzl Outdated
package: Nix Flake package to make available. The default package will be used if not specified.
build_file: The file to use as the BUILD file for this repository.

Its contents are copied copied into the file `BUILD` in root of the nix output folder. The Label does not need to be named `BUILD`, but can be.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Its contents are copied copied into the file `BUILD` in root of the nix output folder. The Label does not need to be named `BUILD`, but can be.
Its contents are copied into the file `BUILD` in root of the nix output folder. The Label does not need to be named `BUILD`, but can be.

core/nixpkgs.bzl Outdated
Comment on lines 691 to 717
# Is nix supported on this platform?
not_supported = not is_supported_platform(repository_ctx)

# Should we fail if Nix is not supported?
fail_not_supported = repository_ctx.attr.fail_not_supported

if not_supported and fail_not_supported:
fail("Platform is not supported: `nix` not found in PATH. See attribute `fail_not_supported` if you don't want to use Nix.")
elif not_supported:
return

# If true, a BUILD file will be created from a template if it does not
# exist.
# However this will happen AFTER the nix-build command.
create_build_file_if_needed = False
if repository_ctx.attr.build_file and repository_ctx.attr.build_file_content:
fail("Specify one of 'build_file' or 'build_file_content', but not both.")
elif repository_ctx.attr.build_file:
repository_ctx.symlink(repository_ctx.attr.build_file, "BUILD")
elif repository_ctx.attr.build_file_content:
repository_ctx.file("BUILD", content = repository_ctx.attr.build_file_content)
else:
# No user supplied build file, we may create the default one.
create_build_file_if_needed = True

# Workaround to bazelbuild/bazel#4533
repository_ctx.path("BUILD")
Copy link
Member

Choose a reason for hiding this comment

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

Factoring out the common parts between nixpkgs_package and nixpkgs_flake_package would be great. There is a fair bit of complexity around invoking Nix that was tricky to get right. I'd be wary of duplicating it and risk it diverging.

@benradf
Copy link
Contributor

benradf commented May 11, 2023

The workspace CI jobs are failing because the README doesn't match the docstrings in the bzl files. We shouldn't change the README files directly - there are targets to regenerate them from the docstrings. This is minor though - we can fix it when the PR is otherwise ready merge.

The bzlmod CI jobs are failing with this error:

Error in fail: Invalid Nix repository, you must use the nix_repo extension and request a global repository or register a local repository: Unknown repository - no repository named 'flake-hello' available for module 'rules_nixpkgs_core_testing'.

You can reproduce this locally by running the following in the testing/core directory:

bazel run --config=bzlmod //tests:run-flake-hello

I started looking into how the bzlmod code path would need to change to fix this but didn't figure it out yet. I'm guessing nixpkgs_flake_package doesn't do some bzlmod stuff that nixpkgs_package does. Any suggestions @aherrmann?

Comment on lines 34 to 35
"flake-hello",
"flake-hello-with-build-file",
Copy link
Member

Choose a reason for hiding this comment

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

In reply to #380 (comment).
The issue is that these tests were added here. This list comprehension is only valid for tests of packages that are imported using a bzlmod Bazel module extension. However, no such extension exists for the flake part, yet.
You can fix this by adding another instance of the list comprehension like this (unverified code):

[
    # All of these tests use the "hello" binary to see
    # whether different invocations of `nixpkgs_flake_package`
    # produce a valid bazel repository.
    sh_test(
        name = "run-{0}".format(test),
        timeout = "short",
        srcs = ["test_bin.sh"],
        args = ["$(location @{0}//:bin)".format(test)],
        data = ["@{0}//:bin".format(test)],
    )
    for test in [
        "flake-hello",
        "flake-hello-with-build-file",

(If you go through the Git history of this file, you'll find instances of such code from when not all tests had been converted to use the module extension, yet)

You'll also need to add use_repo entries to MODULE.bazel to import these two repositories from the non_module_deps extension.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is that just a temporary workaround or the proper fix? It seems like my work here is only half done, as I presumably need to write @rules_nixpkgs_core//extensions:flake_package.bzl (or whatever bikeshed)? This is based on my observation that nix_pkg = use_extension("@rules_nixpkgs_core//extensions:package.bzl", "nix_pkg") seems to be a bzlmod wrapper/validator around nixpkgs_package().

Copy link
Member

Choose a reason for hiding this comment

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

It's a temporary workaround until there is direct bzlmod support for flake with a module extension.
However, I would keep that out of this PR and defer for later. This will require some design work first - right know I don't really have a good picture for what a module extension for flake support should look like. As mentioned in #348 (comment), I don't know how or if we'd want to approach globally unified packages.

Flakes also bring their own dependency management features. There's a question of whether we'd want to integrate those with bzlmod somehow. Part of the bzlmod design is to provide support for package manager integration via module extensions and tags, with a distinct resolution phase before fetching/importing individual deps. So, from that point of view it could make sense to integrate with Nix flake's dependency management features.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

bzlmod test fixes pushed. Not sure if they work as the CI jobs don't seem to run automatically?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, we have to run them manually for contributors from outside the organization. Looks like CI is passing now.

Copy link
Contributor

@benradf benradf left a comment

Choose a reason for hiding this comment

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

Good to see _nixpkgs_package_impl being broken up a little - it was getting pretty big for a single macro. Thanks for this contribution @rickvanprim!

@benradf benradf added the merge-queue merge on green CI label May 16, 2023
@benradf benradf merged commit b103523 into tweag:master May 16, 2023
@mergify mergify bot removed the merge-queue merge on green CI label May 16, 2023
@rickvanprim rickvanprim deleted the jleitch branch May 16, 2023 15:39
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.

3 participants