Skip to content

Commit ab661ac

Browse files
av-galMic92
authored andcommitted
feat: add --subpackage option to update multiple derivations
1 parent 876d9de commit ab661ac

File tree

7 files changed

+180
-0
lines changed

7 files changed

+180
-0
lines changed

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,57 @@ Arguments can be passed to `nix-shell maintainers/scripts/update.nix` like so
197197
$ nix-update sbt --use-update-script --update-script-args "--argstr skip-prompt true"
198198
```
199199

200+
## Subpackages
201+
202+
Some packages consist of multiple fixed-output derivations derived from the same upstream source.
203+
For example, a Go project with Go module dependencies might also include a JavaScript project with npm dependencies.
204+
205+
To support such use cases, `nix-update` allows specifying subpackages directly in the command line.
206+
Consider a package accessible via the `some-package` attribute, which also provides a second fixed-output derivation as a subpackage named `web-ui`:
207+
208+
```nix
209+
{
210+
buildGoModule,
211+
fetchFromGitHub,
212+
buildNpmPackage,
213+
}:
214+
215+
let
216+
pname = "some-package";
217+
version = "1.53.0";
218+
src = fetchFromGitHub {
219+
owner = "owner";
220+
repo = "repo";
221+
rev = "v${version}";
222+
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
223+
};
224+
225+
web-ui = buildNpmPackage rec {
226+
...
227+
npmDepsHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
228+
};
229+
in
230+
buildGoModule rec {
231+
inherit
232+
web-ui
233+
pname
234+
version
235+
src;
236+
237+
vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
238+
239+
preBuild = ''
240+
cp -r ${web-ui}/* web/dist
241+
'';
242+
}
243+
```
244+
245+
You can update the package and its subpackage using `nix-update` as follows:
246+
247+
```
248+
nix-update --sub-packages web-ui some-package # sub-package can be repeated
249+
```
250+
200251
## Development setup
201252

202253
First clone the repo to your preferred location (in the following, we assume

nix_update/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ def parse_args(args: list[str]) -> Options:
107107
help="Path to the directory containing the metadata (e.g. Cargo.toml) referenced by the lockfile",
108108
default=".",
109109
)
110+
parser.add_argument(
111+
"-s",
112+
"--subpackage",
113+
action="append",
114+
help="Attribute for a subpackage that nix-update should try to get hashes for",
115+
default=None,
116+
)
110117

111118
a = parser.parse_args(args)
112119
return Options(
@@ -116,6 +123,7 @@ def parse_args(args: list[str]) -> Options:
116123
commit=a.commit,
117124
use_update_script=a.use_update_script,
118125
update_script_args=a.update_script_args,
126+
subpackages=a.subpackage,
119127
url=a.url,
120128
write_commit_message=a.write_commit_message,
121129
run=a.run,

nix_update/options.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Options:
1313
version_preference: VersionPreference = VersionPreference.STABLE
1414
version_regex: str = "(.*)"
1515
import_path: str = os.getcwd()
16+
subpackages: list[str] | None = None
1617
override_filename: str | None = None
1718
url: str | None = None
1819
commit: bool = False

nix_update/update.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import tomllib
1010
from concurrent.futures import ThreadPoolExecutor
1111
from contextlib import contextmanager
12+
from copy import deepcopy
1213
from os import path
1314
from pathlib import Path
1415

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

509+
if opts.subpackages:
510+
for subpackage in opts.subpackages:
511+
info(f"Updating subpackage {subpackage}")
512+
subpackage_opts = deepcopy(opts)
513+
subpackage_opts.attribute += f".{subpackage}"
514+
# Update escaped package attribute
515+
subpackage_opts.__post_init__()
516+
subpackage_opts.subpackages = None
517+
# Do not update the version number since that's already been done
518+
subpackage_opts.version_preference = VersionPreference.SKIP
519+
update(subpackage_opts)
520+
508521
# if no package.hash was provided we just update the other hashes unconditionally
509522
if update_hash or not package.hash:
510523
if package.go_modules:

tests/test_subpackage.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import subprocess
2+
3+
import conftest
4+
5+
from nix_update.options import Options
6+
from nix_update.update import update
7+
8+
9+
def test_update(helpers: conftest.Helpers) -> None:
10+
with helpers.testpkgs() as path:
11+
opts = Options(
12+
attribute="subpackage", subpackages=["autobrr-web"], import_path=str(path)
13+
)
14+
update(opts)
15+
16+
def get_attr(attr: str) -> str:
17+
return subprocess.run(
18+
[
19+
"nix",
20+
"eval",
21+
"--raw",
22+
"--extra-experimental-features",
23+
"nix-command",
24+
"-f",
25+
path,
26+
attr,
27+
],
28+
text=True,
29+
stdout=subprocess.PIPE,
30+
).stdout.strip()
31+
32+
subpackage_hash = get_attr("subpackage.autobrr-web.pnpmDeps.outputHash")
33+
assert subpackage_hash != "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
34+
35+
src_hash = get_attr("subpackage.src.outputHash")
36+
assert src_hash != "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
37+
38+
gomodules_hash = get_attr("subpackage.goModules.outputHash")
39+
assert gomodules_hash != "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
40+
41+
version = get_attr("subpackage.version")
42+
assert tuple(map(int, version.split("."))) >= (1, 53, 0)

tests/testpkgs/default.nix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,5 @@
3333
mix = pkgs.callPackage ./mix.nix { };
3434
set = pkgs.callPackage ./set.nix { };
3535
let-bound-version = pkgs.callPackage ./let-bound-version.nix { };
36+
subpackage = pkgs.callPackage ./subpackage.nix { };
3637
}

tests/testpkgs/subpackage.nix

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
buildGoModule,
3+
fetchFromGitHub,
4+
stdenvNoCC,
5+
nodejs,
6+
pnpm_9,
7+
typescript,
8+
}:
9+
10+
let
11+
pname = "autobrr";
12+
version = "1.53.0";
13+
src = fetchFromGitHub {
14+
owner = "autobrr";
15+
repo = "autobrr";
16+
rev = "v${version}";
17+
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
18+
};
19+
20+
autobrr-web = stdenvNoCC.mkDerivation {
21+
pname = "${pname}-web";
22+
inherit src version;
23+
24+
nativeBuildInputs = [
25+
nodejs
26+
pnpm_9.configHook
27+
typescript
28+
];
29+
30+
sourceRoot = "${src.name}/web";
31+
32+
pnpmDeps = pnpm_9.fetchDeps {
33+
inherit (autobrr-web)
34+
pname
35+
version
36+
src
37+
sourceRoot
38+
;
39+
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
40+
};
41+
42+
postBuild = ''
43+
pnpm run build
44+
'';
45+
46+
installPhase = ''
47+
cp -r dist $out
48+
'';
49+
};
50+
in
51+
buildGoModule rec {
52+
inherit
53+
autobrr-web
54+
pname
55+
version
56+
src
57+
;
58+
59+
vendorHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
60+
61+
preBuild = ''
62+
cp -r ${autobrr-web}/* web/dist
63+
'';
64+
}

0 commit comments

Comments
 (0)