Skip to content

Commit

Permalink
feat: add --subpackage option to update multiple derivations
Browse files Browse the repository at this point in the history
  • Loading branch information
av-gal authored and Mic92 committed Dec 20, 2024
1 parent 876d9de commit ab661ac
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 0 deletions.
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,57 @@ Arguments can be passed to `nix-shell maintainers/scripts/update.nix` like so
$ nix-update sbt --use-update-script --update-script-args "--argstr skip-prompt true"
```

## Subpackages

Some packages consist of multiple fixed-output derivations derived from the same upstream source.
For example, a Go project with Go module dependencies might also include a JavaScript project with npm dependencies.

To support such use cases, `nix-update` allows specifying subpackages directly in the command line.
Consider a package accessible via the `some-package` attribute, which also provides a second fixed-output derivation as a subpackage named `web-ui`:

```nix
{
buildGoModule,
fetchFromGitHub,
buildNpmPackage,
}:
let
pname = "some-package";
version = "1.53.0";
src = fetchFromGitHub {
owner = "owner";
repo = "repo";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
web-ui = buildNpmPackage rec {
...
npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
in
buildGoModule rec {
inherit
web-ui
pname
version
src;
vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
preBuild = ''
cp -r ${web-ui}/* web/dist
'';
}
```

You can update the package and its subpackage using `nix-update` as follows:

```
nix-update --sub-packages web-ui some-package # sub-package can be repeated
```

## Development setup

First clone the repo to your preferred location (in the following, we assume
Expand Down
8 changes: 8 additions & 0 deletions nix_update/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ def parse_args(args: list[str]) -> Options:
help="Path to the directory containing the metadata (e.g. Cargo.toml) referenced by the lockfile",
default=".",
)
parser.add_argument(
"-s",
"--subpackage",
action="append",
help="Attribute for a subpackage that nix-update should try to get hashes for",
default=None,
)

a = parser.parse_args(args)
return Options(
Expand All @@ -116,6 +123,7 @@ def parse_args(args: list[str]) -> Options:
commit=a.commit,
use_update_script=a.use_update_script,
update_script_args=a.update_script_args,
subpackages=a.subpackage,
url=a.url,
write_commit_message=a.write_commit_message,
run=a.run,
Expand Down
1 change: 1 addition & 0 deletions nix_update/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Options:
version_preference: VersionPreference = VersionPreference.STABLE
version_regex: str = "(.*)"
import_path: str = os.getcwd()
subpackages: list[str] | None = None
override_filename: str | None = None
url: str | None = None
commit: bool = False
Expand Down
13 changes: 13 additions & 0 deletions nix_update/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import tomllib
from concurrent.futures import ThreadPoolExecutor
from contextlib import contextmanager
from copy import deepcopy
from os import path
from pathlib import Path

Expand Down Expand Up @@ -505,6 +506,18 @@ def update(opts: Options) -> Package:
if package.hash and update_hash:
update_src_hash(opts, package.filename, package.hash)

if opts.subpackages:
for subpackage in opts.subpackages:
info(f"Updating subpackage {subpackage}")
subpackage_opts = deepcopy(opts)
subpackage_opts.attribute += f".{subpackage}"
# Update escaped package attribute
subpackage_opts.__post_init__()
subpackage_opts.subpackages = None
# Do not update the version number since that's already been done
subpackage_opts.version_preference = VersionPreference.SKIP
update(subpackage_opts)

# if no package.hash was provided we just update the other hashes unconditionally
if update_hash or not package.hash:
if package.go_modules:
Expand Down
42 changes: 42 additions & 0 deletions tests/test_subpackage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import subprocess

import conftest

from nix_update.options import Options
from nix_update.update import update


def test_update(helpers: conftest.Helpers) -> None:
with helpers.testpkgs() as path:
opts = Options(
attribute="subpackage", subpackages=["autobrr-web"], import_path=str(path)
)
update(opts)

def get_attr(attr: str) -> str:
return subprocess.run(
[
"nix",
"eval",
"--raw",
"--extra-experimental-features",
"nix-command",
"-f",
path,
attr,
],
text=True,
stdout=subprocess.PIPE,
).stdout.strip()

subpackage_hash = get_attr("subpackage.autobrr-web.pnpmDeps.outputHash")
assert subpackage_hash != "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="

src_hash = get_attr("subpackage.src.outputHash")
assert src_hash != "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="

gomodules_hash = get_attr("subpackage.goModules.outputHash")
assert gomodules_hash != "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="

version = get_attr("subpackage.version")
assert tuple(map(int, version.split("."))) >= (1, 53, 0)
1 change: 1 addition & 0 deletions tests/testpkgs/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@
mix = pkgs.callPackage ./mix.nix { };
set = pkgs.callPackage ./set.nix { };
let-bound-version = pkgs.callPackage ./let-bound-version.nix { };
subpackage = pkgs.callPackage ./subpackage.nix { };
}
64 changes: 64 additions & 0 deletions tests/testpkgs/subpackage.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
buildGoModule,
fetchFromGitHub,
stdenvNoCC,
nodejs,
pnpm_9,
typescript,
}:

let
pname = "autobrr";
version = "1.53.0";
src = fetchFromGitHub {
owner = "autobrr";
repo = "autobrr";
rev = "v${version}";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};

autobrr-web = stdenvNoCC.mkDerivation {
pname = "${pname}-web";
inherit src version;

nativeBuildInputs = [
nodejs
pnpm_9.configHook
typescript
];

sourceRoot = "${src.name}/web";

pnpmDeps = pnpm_9.fetchDeps {
inherit (autobrr-web)
pname
version
src
sourceRoot
;
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};

postBuild = ''
pnpm run build
'';

installPhase = ''
cp -r dist $out
'';
};
in
buildGoModule rec {
inherit
autobrr-web
pname
version
src
;

vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";

preBuild = ''
cp -r ${autobrr-web}/* web/dist
'';
}

0 comments on commit ab661ac

Please sign in to comment.