11from collections .abc import Callable , Generator
2+ from contextlib import contextmanager
23from unittest .mock import MagicMock , patch
34
45import pytest
6+ from django .conf import settings
57from django .core .management import call_command
68
79from shared .hydra import Jobset , JobsetInput , jobset_from_job
@@ -38,35 +40,47 @@ def test_input_branch_default(make_jobset: Callable[[str], Jobset]) -> None:
3840 assert jobset .input_branch ("nixpkgs" , default = "master" ) == "master"
3941
4042
41- _FAKE_SHA1 = "a" * 40
43+ @pytest .fixture
44+ def mock_hydra () -> Callable :
45+ @contextmanager
46+ def factory (channels : dict , jobsets : dict ) -> Generator [None ]:
47+ client = MagicMock ()
48+ client .get_jobset .side_effect = jobsets .get
49+ with (
50+ patch (
51+ "shared.management.commands.fetch_all_channels.channels" ,
52+ channels ,
53+ ),
54+ patch (
55+ "shared.management.commands.fetch_all_channels.default_client" ,
56+ return_value = client ,
57+ ),
58+ ):
59+ yield
60+
61+ return factory
4262
4363
4464@pytest .fixture
45- def hydra_mock () -> Generator [MagicMock ]:
46- client = MagicMock ()
47- client .get_jobset .side_effect = {
48- "nixpkgs/unstable" : Jobset (
49- inputs = {
50- "nixpkgs" : JobsetInput (value = "https://github.com/NixOS/nixpkgs.git" )
51- }
52- ),
53- "nixos/unstable-small" : Jobset (
54- inputs = {
55- "nixpkgs" : JobsetInput (value = "https://github.com/NixOS/nixpkgs.git" )
56- }
57- ),
58- "nixos/release-25.05-small" : Jobset (
59- inputs = {
60- "nixpkgs" : JobsetInput (
61- value = "https://github.com/NixOS/nixpkgs.git release-25.05"
62- )
63- }
64- ),
65- }.get
65+ def mock_head_sha1 () -> Callable :
66+ @contextmanager
67+ def factory (branch_shas : dict [str , str ]) -> Generator [None ]:
68+ with patch (
69+ "shared.management.commands.fetch_all_channels.get_head_sha1" ,
70+ side_effect = lambda url , branch : branch_shas [branch ],
71+ ):
72+ yield
73+
74+ return factory
75+
76+
77+ @pytest .mark .django_db
78+ def test_fetch_all_channels_creates_nix_branches (
79+ mock_hydra : Callable , mock_head_sha1 : Callable
80+ ) -> None :
6681 with (
67- patch (
68- "shared.management.commands.fetch_all_channels.channels" ,
69- {
82+ mock_hydra (
83+ channels = {
7084 "nixpkgs-unstable" : Channel (
7185 job = "nixpkgs/unstable/unstable" ,
7286 status = ChannelState .UNSTABLE ,
@@ -83,35 +97,31 @@ def hydra_mock() -> Generator[MagicMock]:
8397 variant = Channel .Variant .SMALL ,
8498 ),
8599 },
100+ jobsets = {
101+ "nixpkgs/unstable" : Jobset (
102+ inputs = {"nixpkgs" : JobsetInput (value = f"{ settings .GIT_CLONE_URL } " )},
103+ ),
104+ "nixos/unstable-small" : Jobset (
105+ inputs = {"nixpkgs" : JobsetInput (value = f"{ settings .GIT_CLONE_URL } " )},
106+ ),
107+ "nixos/release-25.05-small" : Jobset (
108+ inputs = {
109+ "nixpkgs" : JobsetInput (
110+ value = f"{ settings .GIT_CLONE_URL } release-25.05"
111+ )
112+ }
113+ ),
114+ },
86115 ),
87- patch (
88- "shared.management.commands.fetch_all_channels.default_client" ,
89- return_value = client ,
90- ),
116+ mock_head_sha1 (branch_shas = {"master" : "a" * 40 , "release-25.05" : "b" * 40 }),
91117 ):
92- yield client
93-
94-
95- @pytest .fixture
96- def head_sha1_mock () -> Generator [MagicMock ]:
97- with patch (
98- "shared.management.commands.fetch_all_channels.get_head_sha1" ,
99- return_value = _FAKE_SHA1 ,
100- ) as mock_head :
101- yield mock_head
102-
103-
104- @pytest .mark .django_db
105- def test_fetch_all_channels_creates_nix_branches (
106- hydra_mock : MagicMock , head_sha1_mock : MagicMock
107- ) -> None :
108- call_command ("fetch_all_channels" )
118+ call_command ("fetch_all_channels" )
109119
110120 assert NixpkgsBranch .objects .filter (
111- name = "master" , head_sha1_commit = _FAKE_SHA1
121+ name = settings . TRACKING_BRANCH , head_sha1_commit = "a" * 40
112122 ).exists ()
113123 assert NixpkgsBranch .objects .filter (
114- name = "release-25.05" , head_sha1_commit = _FAKE_SHA1
124+ name = "release-25.05" , head_sha1_commit = "b" * 40
115125 ).exists ()
116126 assert NixChannel .objects .filter (channel_branch = "nixpkgs-unstable" ).exists ()
117127 assert NixChannel .objects .filter (channel_branch = "nixos-unstable-small" ).exists ()
@@ -120,20 +130,53 @@ def test_fetch_all_channels_creates_nix_branches(
120130
121131@pytest .mark .django_db
122132def test_fetch_all_channels_small_variant_updates_branch (
123- hydra_mock : MagicMock ,
124- head_sha1_mock : MagicMock ,
133+ mock_hydra : Callable , mock_head_sha1 : Callable
125134) -> None :
126135 """
127136 Only small-variant channels fetch the Git HEAD.
128137 All other channels reuse the already-fetched branch.
129138 """
130- NixpkgsBranch .objects .create (name = "master" , head_sha1_commit = "b " * 40 )
131- NixpkgsBranch .objects .create (name = "release-25.05" , head_sha1_commit = "c " * 40 )
139+ NixpkgsBranch .objects .create (name = "master" , head_sha1_commit = "c " * 40 )
140+ NixpkgsBranch .objects .create (name = "release-25.05" , head_sha1_commit = "d " * 40 )
132141
133- call_command ("fetch_all_channels" )
142+ with (
143+ mock_hydra (
144+ channels = {
145+ "nixpkgs-unstable" : Channel (
146+ job = "nixpkgs/unstable/unstable" ,
147+ status = ChannelState .UNSTABLE ,
148+ variant = Channel .Variant .PRIMARY ,
149+ ),
150+ "nixos-unstable-small" : Channel (
151+ job = "nixos/unstable-small/tested" ,
152+ status = ChannelState .UNSTABLE ,
153+ variant = Channel .Variant .SMALL ,
154+ ),
155+ "nixos-25.05-small" : Channel (
156+ job = "nixos/release-25.05-small/tested" ,
157+ status = ChannelState .STABLE ,
158+ variant = Channel .Variant .SMALL ,
159+ ),
160+ },
161+ jobsets = {
162+ "nixpkgs/unstable" : Jobset (
163+ inputs = {"nixpkgs" : JobsetInput (value = f"{ settings .GIT_CLONE_URL } " )},
164+ ),
165+ "nixos/unstable-small" : Jobset (
166+ inputs = {"nixpkgs" : JobsetInput (value = f"{ settings .GIT_CLONE_URL } " )},
167+ ),
168+ "nixos/release-25.05-small" : Jobset (
169+ inputs = {
170+ "nixpkgs" : JobsetInput (
171+ value = f"{ settings .GIT_CLONE_URL } release-25.05"
172+ )
173+ },
174+ ),
175+ },
176+ ),
177+ mock_head_sha1 (branch_shas = {"master" : "a" * 40 , "release-25.05" : "b" * 40 }),
178+ ):
179+ call_command ("fetch_all_channels" )
134180
135- assert head_sha1_mock .call_count == 2
136- assert NixpkgsBranch .objects .get (name = "master" ).head_sha1_commit == _FAKE_SHA1
137- assert (
138- NixpkgsBranch .objects .get (name = "release-25.05" ).head_sha1_commit == _FAKE_SHA1
139- )
181+ assert NixpkgsBranch .objects .get (name = "master" ).head_sha1_commit == "a" * 40
182+ assert NixpkgsBranch .objects .get (name = "release-25.05" ).head_sha1_commit == "b" * 40
0 commit comments