qontract-reconcile 0.10.1rc514__py3-none-any.whl → 0.10.1rc515__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qontract_reconcile-0.10.1rc514.dist-info → qontract_reconcile-0.10.1rc515.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc514.dist-info → qontract_reconcile-0.10.1rc515.dist-info}/RECORD +17 -15
- reconcile/saas_auto_promotions_manager/integration.py +28 -3
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager.py +5 -5
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py +144 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py +13 -9
- reconcile/saas_auto_promotions_manager/merge_request_manager/reconciler.py +207 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +9 -6
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +25 -12
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py +3 -0
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +51 -153
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py +11 -9
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py +408 -0
- reconcile/test/saas_auto_promotions_manager/test_integration_test.py +23 -88
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_unbatching.py +0 -96
- {qontract_reconcile-0.10.1rc514.dist-info → qontract_reconcile-0.10.1rc515.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc514.dist-info → qontract_reconcile-0.10.1rc515.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc514.dist-info → qontract_reconcile-0.10.1rc515.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,408 @@
|
|
1
|
+
from collections.abc import Sequence
|
2
|
+
from unittest.mock import create_autospec
|
3
|
+
|
4
|
+
import pytest
|
5
|
+
from gitlab.v4.objects import ProjectMergeRequest
|
6
|
+
|
7
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
8
|
+
OpenMergeRequest,
|
9
|
+
)
|
10
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
11
|
+
MSG_MISSING_UNBATCHING,
|
12
|
+
MSG_NEW_BATCH,
|
13
|
+
MSG_OUTDATED_CONTENT,
|
14
|
+
Addition,
|
15
|
+
Deletion,
|
16
|
+
Diff,
|
17
|
+
Promotion,
|
18
|
+
Reconciler,
|
19
|
+
)
|
20
|
+
|
21
|
+
|
22
|
+
def _aggregate_hashes(items: Sequence[Addition | Deletion]) -> set[str]:
|
23
|
+
hashes: set[str] = set()
|
24
|
+
for item in items:
|
25
|
+
if isinstance(item, Addition):
|
26
|
+
hashes.update(item.content_hashes)
|
27
|
+
else:
|
28
|
+
hashes.update(item.mr.content_hashes)
|
29
|
+
return hashes
|
30
|
+
|
31
|
+
|
32
|
+
def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
33
|
+
channels: set[str] = set()
|
34
|
+
for item in items:
|
35
|
+
if isinstance(item, Addition):
|
36
|
+
channels.update(item.channels)
|
37
|
+
else:
|
38
|
+
channels.update(item.mr.channels)
|
39
|
+
return channels
|
40
|
+
|
41
|
+
|
42
|
+
@pytest.mark.parametrize(
|
43
|
+
"desired_promotions, open_mrs, expected_diff",
|
44
|
+
[
|
45
|
+
# No open MRs. Aggregate desired promotions into single batched Promotion
|
46
|
+
(
|
47
|
+
[
|
48
|
+
Promotion(
|
49
|
+
channels={"chan1"},
|
50
|
+
content_hashes={"hash1"},
|
51
|
+
),
|
52
|
+
Promotion(
|
53
|
+
channels={"chan2", "chan3"},
|
54
|
+
content_hashes={"hash2", "hash3"},
|
55
|
+
),
|
56
|
+
],
|
57
|
+
[],
|
58
|
+
Diff(
|
59
|
+
deletions=[],
|
60
|
+
additions=[
|
61
|
+
Addition(
|
62
|
+
channels={"chan1", "chan2", "chan3"},
|
63
|
+
content_hashes={"hash1", "hash2", "hash3"},
|
64
|
+
batchable=True,
|
65
|
+
),
|
66
|
+
],
|
67
|
+
),
|
68
|
+
),
|
69
|
+
# No desired promotions. We expect that every MR gets closed,
|
70
|
+
# no matter its current state.
|
71
|
+
(
|
72
|
+
[],
|
73
|
+
[
|
74
|
+
OpenMergeRequest(
|
75
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
76
|
+
channels={"chan1", "chan2"},
|
77
|
+
content_hashes={"hash1", "hash2"},
|
78
|
+
failed_mr_check=True,
|
79
|
+
is_batchable=True,
|
80
|
+
),
|
81
|
+
OpenMergeRequest(
|
82
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
83
|
+
channels={"chan3"},
|
84
|
+
content_hashes={"hash3"},
|
85
|
+
failed_mr_check=False,
|
86
|
+
is_batchable=True,
|
87
|
+
),
|
88
|
+
OpenMergeRequest(
|
89
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
90
|
+
channels={"chan4"},
|
91
|
+
content_hashes={"hash4"},
|
92
|
+
failed_mr_check=False,
|
93
|
+
is_batchable=False,
|
94
|
+
),
|
95
|
+
OpenMergeRequest(
|
96
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
97
|
+
channels={"chan5"},
|
98
|
+
content_hashes={"hash5"},
|
99
|
+
failed_mr_check=True,
|
100
|
+
is_batchable=False,
|
101
|
+
),
|
102
|
+
],
|
103
|
+
Diff(
|
104
|
+
deletions=[
|
105
|
+
Deletion(
|
106
|
+
mr=OpenMergeRequest(
|
107
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
108
|
+
channels={"chan1", "chan2"},
|
109
|
+
content_hashes={"hash1", "hash2"},
|
110
|
+
failed_mr_check=True,
|
111
|
+
is_batchable=True,
|
112
|
+
),
|
113
|
+
reason=MSG_MISSING_UNBATCHING,
|
114
|
+
),
|
115
|
+
Deletion(
|
116
|
+
mr=OpenMergeRequest(
|
117
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
118
|
+
channels={"chan3"},
|
119
|
+
content_hashes={"hash3"},
|
120
|
+
failed_mr_check=False,
|
121
|
+
is_batchable=True,
|
122
|
+
),
|
123
|
+
reason=MSG_OUTDATED_CONTENT,
|
124
|
+
),
|
125
|
+
Deletion(
|
126
|
+
mr=OpenMergeRequest(
|
127
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
128
|
+
channels={"chan4"},
|
129
|
+
content_hashes={"hash4"},
|
130
|
+
failed_mr_check=False,
|
131
|
+
is_batchable=False,
|
132
|
+
),
|
133
|
+
reason=MSG_OUTDATED_CONTENT,
|
134
|
+
),
|
135
|
+
Deletion(
|
136
|
+
mr=OpenMergeRequest(
|
137
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
138
|
+
channels={"chan5"},
|
139
|
+
content_hashes={"hash5"},
|
140
|
+
failed_mr_check=True,
|
141
|
+
is_batchable=False,
|
142
|
+
),
|
143
|
+
reason=MSG_OUTDATED_CONTENT,
|
144
|
+
),
|
145
|
+
],
|
146
|
+
additions=[],
|
147
|
+
),
|
148
|
+
),
|
149
|
+
# We have a single failed, but still marked as batchable MR.
|
150
|
+
# The hashes in the failed MR are still desired state.
|
151
|
+
# We expect this MR to be closed. Further, a new MR should be
|
152
|
+
# opened that is marked as unbatchable. Each hash should have
|
153
|
+
# its own separated MR.
|
154
|
+
(
|
155
|
+
[
|
156
|
+
Promotion(
|
157
|
+
channels={"chan1"},
|
158
|
+
content_hashes={"hash1"},
|
159
|
+
),
|
160
|
+
Promotion(
|
161
|
+
channels={"chan2"},
|
162
|
+
content_hashes={"hash2"},
|
163
|
+
),
|
164
|
+
],
|
165
|
+
[
|
166
|
+
OpenMergeRequest(
|
167
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
168
|
+
channels={"chan1", "chan2"},
|
169
|
+
content_hashes={"hash1", "hash2"},
|
170
|
+
failed_mr_check=True,
|
171
|
+
is_batchable=True,
|
172
|
+
),
|
173
|
+
],
|
174
|
+
Diff(
|
175
|
+
deletions=[
|
176
|
+
Deletion(
|
177
|
+
mr=OpenMergeRequest(
|
178
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
179
|
+
channels={"chan1", "chan2"},
|
180
|
+
content_hashes={"hash1", "hash2"},
|
181
|
+
failed_mr_check=True,
|
182
|
+
is_batchable=True,
|
183
|
+
),
|
184
|
+
reason=MSG_MISSING_UNBATCHING,
|
185
|
+
)
|
186
|
+
],
|
187
|
+
additions=[
|
188
|
+
Addition(
|
189
|
+
channels={"chan1"},
|
190
|
+
content_hashes={"hash1"},
|
191
|
+
batchable=False,
|
192
|
+
),
|
193
|
+
Addition(
|
194
|
+
channels={"chan2"},
|
195
|
+
content_hashes={"hash2"},
|
196
|
+
batchable=False,
|
197
|
+
),
|
198
|
+
],
|
199
|
+
),
|
200
|
+
),
|
201
|
+
# We have an open valid batched MR. All desired promotions
|
202
|
+
# are already addressed by that MR -> there is nothing to do.
|
203
|
+
(
|
204
|
+
[
|
205
|
+
Promotion(
|
206
|
+
channels={"chan1"},
|
207
|
+
content_hashes={"hash1"},
|
208
|
+
),
|
209
|
+
Promotion(
|
210
|
+
channels={"chan2"},
|
211
|
+
content_hashes={"hash2"},
|
212
|
+
),
|
213
|
+
],
|
214
|
+
[
|
215
|
+
OpenMergeRequest(
|
216
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
217
|
+
channels={"chan1", "chan2"},
|
218
|
+
content_hashes={"hash1", "hash2"},
|
219
|
+
failed_mr_check=False,
|
220
|
+
is_batchable=True,
|
221
|
+
),
|
222
|
+
],
|
223
|
+
Diff(
|
224
|
+
deletions=[],
|
225
|
+
additions=[],
|
226
|
+
),
|
227
|
+
),
|
228
|
+
# We have an open valid batched MR. However, there is a promotion
|
229
|
+
# that is not addressed by the open MR.
|
230
|
+
# We expect that the MR gets closed and a new
|
231
|
+
# batched MR gets created which addresses all desired promotions.
|
232
|
+
(
|
233
|
+
[
|
234
|
+
Promotion(
|
235
|
+
channels={"chan1"},
|
236
|
+
content_hashes={"hash1"},
|
237
|
+
),
|
238
|
+
Promotion(
|
239
|
+
channels={"chan2"},
|
240
|
+
content_hashes={"hash2"},
|
241
|
+
),
|
242
|
+
Promotion(
|
243
|
+
channels={"chan3", "chan4"},
|
244
|
+
content_hashes={"hash3", "hash4"},
|
245
|
+
),
|
246
|
+
],
|
247
|
+
[
|
248
|
+
OpenMergeRequest(
|
249
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
250
|
+
channels={"chan1", "chan2"},
|
251
|
+
content_hashes={"hash1", "hash2"},
|
252
|
+
failed_mr_check=False,
|
253
|
+
is_batchable=True,
|
254
|
+
),
|
255
|
+
],
|
256
|
+
Diff(
|
257
|
+
deletions=[
|
258
|
+
Deletion(
|
259
|
+
mr=OpenMergeRequest(
|
260
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
261
|
+
channels={"chan1", "chan2"},
|
262
|
+
content_hashes={"hash1", "hash2"},
|
263
|
+
failed_mr_check=False,
|
264
|
+
is_batchable=True,
|
265
|
+
),
|
266
|
+
reason=MSG_NEW_BATCH,
|
267
|
+
)
|
268
|
+
],
|
269
|
+
additions=[
|
270
|
+
Addition(
|
271
|
+
content_hashes={"hash1", "hash2", "hash3", "hash4"},
|
272
|
+
channels={"chan1", "chan2", "chan3", "chan4"},
|
273
|
+
batchable=True,
|
274
|
+
)
|
275
|
+
],
|
276
|
+
),
|
277
|
+
),
|
278
|
+
# We want to promote 12 content hashes.
|
279
|
+
# We surpass the current batch limit of 5.
|
280
|
+
# We expect a total of 3 batch MRs to be created.
|
281
|
+
# The existing open batch MR should be closed.
|
282
|
+
(
|
283
|
+
[
|
284
|
+
Promotion(
|
285
|
+
channels={"chan1", "chan2", "chan3"},
|
286
|
+
content_hashes={"hash1", "hash2", "hash3"},
|
287
|
+
),
|
288
|
+
Promotion(
|
289
|
+
channels={"chan4", "chan5", "chan6"},
|
290
|
+
content_hashes={"hash4", "hash5", "hash6"},
|
291
|
+
),
|
292
|
+
Promotion(
|
293
|
+
channels={"chan7", "chan8", "chan9"},
|
294
|
+
content_hashes={"hash7", "hash8", "hash9"},
|
295
|
+
),
|
296
|
+
Promotion(
|
297
|
+
channels={"chan10", "chan11", "chan12"},
|
298
|
+
content_hashes={"hash10", "hash11", "hash12"},
|
299
|
+
),
|
300
|
+
Promotion(
|
301
|
+
channels={"chan13", "chan14"},
|
302
|
+
content_hashes={"hash13", "hash14"},
|
303
|
+
),
|
304
|
+
],
|
305
|
+
[
|
306
|
+
OpenMergeRequest(
|
307
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
308
|
+
channels={"chan1", "chan2"},
|
309
|
+
content_hashes={"hash1", "hash2"},
|
310
|
+
failed_mr_check=False,
|
311
|
+
is_batchable=True,
|
312
|
+
),
|
313
|
+
],
|
314
|
+
Diff(
|
315
|
+
deletions=[
|
316
|
+
Deletion(
|
317
|
+
mr=OpenMergeRequest(
|
318
|
+
raw=create_autospec(spec=ProjectMergeRequest),
|
319
|
+
channels={"chan1", "chan2"},
|
320
|
+
content_hashes={"hash1", "hash2"},
|
321
|
+
failed_mr_check=False,
|
322
|
+
is_batchable=True,
|
323
|
+
),
|
324
|
+
reason=MSG_NEW_BATCH,
|
325
|
+
)
|
326
|
+
],
|
327
|
+
additions=[
|
328
|
+
Addition(
|
329
|
+
# Note, that we expect more than 5 hashes here. The reason is that the
|
330
|
+
# aggregated promotions consist of 3 hashes, i.e., 3+3 = 6
|
331
|
+
# This is expected and fine.
|
332
|
+
content_hashes={
|
333
|
+
"hash1",
|
334
|
+
"hash2",
|
335
|
+
"hash3",
|
336
|
+
"hash4",
|
337
|
+
"hash5",
|
338
|
+
"hash6",
|
339
|
+
},
|
340
|
+
channels={"chan1", "chan2", "chan3", "chan4", "chan5", "chan6"},
|
341
|
+
batchable=True,
|
342
|
+
),
|
343
|
+
Addition(
|
344
|
+
content_hashes={
|
345
|
+
"hash7",
|
346
|
+
"hash8",
|
347
|
+
"hash9",
|
348
|
+
"hash10",
|
349
|
+
"hash11",
|
350
|
+
"hash12",
|
351
|
+
},
|
352
|
+
channels={
|
353
|
+
"chan7",
|
354
|
+
"chan8",
|
355
|
+
"chan9",
|
356
|
+
"chan10",
|
357
|
+
"chan11",
|
358
|
+
"chan12",
|
359
|
+
},
|
360
|
+
batchable=True,
|
361
|
+
),
|
362
|
+
Addition(
|
363
|
+
content_hashes={"hash13", "hash14"},
|
364
|
+
channels={"chan13", "chan14"},
|
365
|
+
batchable=True,
|
366
|
+
),
|
367
|
+
],
|
368
|
+
),
|
369
|
+
),
|
370
|
+
],
|
371
|
+
)
|
372
|
+
def test_reconcile(
|
373
|
+
desired_promotions: list[Promotion],
|
374
|
+
open_mrs: list[OpenMergeRequest],
|
375
|
+
expected_diff: Diff,
|
376
|
+
) -> None:
|
377
|
+
reconciler = Reconciler()
|
378
|
+
diff = reconciler.reconcile(
|
379
|
+
desired_promotions=desired_promotions, open_mrs=open_mrs, batch_limit=5
|
380
|
+
)
|
381
|
+
|
382
|
+
# We do not care about the order. As the batcher is working on sets, this
|
383
|
+
# is not deterministic
|
384
|
+
assert len(diff.additions) == len(expected_diff.additions)
|
385
|
+
assert _aggregate_hashes(diff.additions) == _aggregate_hashes(
|
386
|
+
expected_diff.additions
|
387
|
+
)
|
388
|
+
assert _aggregate_channels(diff.additions) == _aggregate_channels(
|
389
|
+
expected_diff.additions
|
390
|
+
)
|
391
|
+
|
392
|
+
# Deletions are actually processed in a deterministic way.
|
393
|
+
assert len(diff.deletions) == len(expected_diff.deletions)
|
394
|
+
for i in range(len(diff.deletions)):
|
395
|
+
assert diff.deletions[i].mr.channels == expected_diff.deletions[i].mr.channels
|
396
|
+
assert (
|
397
|
+
diff.deletions[i].mr.content_hashes
|
398
|
+
== expected_diff.deletions[i].mr.content_hashes
|
399
|
+
)
|
400
|
+
assert (
|
401
|
+
diff.deletions[i].mr.failed_mr_check
|
402
|
+
== expected_diff.deletions[i].mr.failed_mr_check
|
403
|
+
)
|
404
|
+
assert (
|
405
|
+
diff.deletions[i].mr.is_batchable
|
406
|
+
== expected_diff.deletions[i].mr.is_batchable
|
407
|
+
)
|
408
|
+
assert diff.deletions[i].reason == expected_diff.deletions[i].reason
|
@@ -1,124 +1,59 @@
|
|
1
|
-
from collections.abc import (
|
2
|
-
Callable,
|
3
|
-
Iterable,
|
4
|
-
Mapping,
|
5
|
-
)
|
6
1
|
from unittest.mock import create_autospec
|
7
2
|
|
8
3
|
from reconcile.saas_auto_promotions_manager.integration import SaasAutoPromotionsManager
|
9
4
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager import (
|
10
5
|
MergeRequestManager,
|
11
6
|
)
|
7
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
|
8
|
+
MergeRequestManagerV2,
|
9
|
+
)
|
12
10
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
13
11
|
MRParser,
|
14
12
|
)
|
13
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
14
|
+
Reconciler,
|
15
|
+
)
|
15
16
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
16
17
|
Renderer,
|
17
18
|
)
|
18
19
|
from reconcile.saas_auto_promotions_manager.utils.saas_files_inventory import (
|
19
20
|
SaasFilesInventory,
|
20
21
|
)
|
21
|
-
from reconcile.typed_queries.saas_files import SaasFile
|
22
22
|
from reconcile.utils.promotion_state import (
|
23
|
-
PromotionData,
|
24
23
|
PromotionState,
|
25
24
|
)
|
26
25
|
from reconcile.utils.vcs import VCS
|
27
26
|
|
28
27
|
|
29
|
-
def test_integration_test(
|
30
|
-
saas_files_builder: Callable[[Iterable[Mapping]], list[SaasFile]],
|
31
|
-
vcs_builder: Callable[..., VCS],
|
32
|
-
promotion_state_builder: Callable[..., PromotionState],
|
33
|
-
):
|
28
|
+
def test_integration_test():
|
34
29
|
"""
|
35
30
|
Have all the parts glued together and have one full run.
|
36
|
-
This is too complex to setup and maintain
|
37
|
-
|
31
|
+
This is too complex to setup and properly maintain.
|
32
|
+
However, it is a good single test to see if
|
38
33
|
all components are wired properly.
|
39
|
-
|
40
|
-
These saas files and states should result in a single
|
41
|
-
merge request being opened.
|
42
34
|
"""
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
"url": "repo1/url",
|
51
|
-
"targets": [
|
52
|
-
{
|
53
|
-
"ref": "main",
|
54
|
-
"namespace": {"path": "/namespace1.yml"},
|
55
|
-
"promotion": {
|
56
|
-
"publish": ["channel-1"],
|
57
|
-
},
|
58
|
-
},
|
59
|
-
{
|
60
|
-
"ref": "main",
|
61
|
-
"namespace": {"path": "/namespace2.yml"},
|
62
|
-
"promotion": {
|
63
|
-
"publish": ["channel-2"],
|
64
|
-
},
|
65
|
-
},
|
66
|
-
],
|
67
|
-
}
|
68
|
-
],
|
69
|
-
},
|
70
|
-
{
|
71
|
-
"path": "/saas2.yml",
|
72
|
-
"name": "saas_2",
|
73
|
-
"resourceTemplates": [
|
74
|
-
{
|
75
|
-
"name": "template_2",
|
76
|
-
"url": "repo1/url",
|
77
|
-
"targets": [
|
78
|
-
{
|
79
|
-
"ref": "current_sha",
|
80
|
-
"namespace": {"path": "/namespace3.yml"},
|
81
|
-
"promotion": {
|
82
|
-
"subscribe": ["channel-1", "channel-2"],
|
83
|
-
"auto": True,
|
84
|
-
},
|
85
|
-
}
|
86
|
-
],
|
87
|
-
}
|
88
|
-
],
|
89
|
-
},
|
90
|
-
])
|
91
|
-
vcs = vcs_builder()
|
92
|
-
deployment_state = promotion_state_builder([
|
93
|
-
PromotionData(
|
94
|
-
success=True,
|
95
|
-
target_config_hash="new_hash",
|
96
|
-
saas_file="saas_1",
|
97
|
-
),
|
98
|
-
PromotionData(
|
99
|
-
success=True,
|
100
|
-
target_config_hash="new_hash",
|
101
|
-
saas_file="saas_1",
|
102
|
-
),
|
103
|
-
])
|
104
|
-
renderer = create_autospec(spec=Renderer)
|
105
|
-
mr_parser = create_autospec(spec=MRParser)
|
35
|
+
vcs = create_autospec(spec=VCS)
|
36
|
+
merge_request_manager_v2 = MergeRequestManagerV2(
|
37
|
+
vcs=vcs,
|
38
|
+
reconciler=create_autospec(spec=Reconciler),
|
39
|
+
mr_parser=create_autospec(spec=MRParser),
|
40
|
+
renderer=create_autospec(spec=Renderer),
|
41
|
+
)
|
106
42
|
merge_request_manager = MergeRequestManager(
|
107
43
|
vcs=vcs,
|
108
|
-
mr_parser=
|
109
|
-
renderer=
|
44
|
+
mr_parser=create_autospec(spec=MRParser),
|
45
|
+
renderer=create_autospec(spec=Renderer),
|
110
46
|
)
|
111
47
|
manager = SaasAutoPromotionsManager(
|
112
|
-
deployment_state=
|
113
|
-
saas_file_inventory=SaasFilesInventory(saas_files=
|
48
|
+
deployment_state=create_autospec(spec=PromotionState),
|
49
|
+
saas_file_inventory=SaasFilesInventory(saas_files=[]),
|
114
50
|
vcs=vcs,
|
51
|
+
merge_request_manager_v2=merge_request_manager_v2,
|
115
52
|
merge_request_manager=merge_request_manager,
|
116
53
|
thread_pool_size=1,
|
117
54
|
dry_run=False,
|
118
55
|
)
|
119
56
|
manager.reconcile()
|
120
57
|
|
121
|
-
|
122
|
-
|
123
|
-
vcs.close_app_interface_mr.assert_not_called() # type: ignore[attr-defined]
|
124
|
-
vcs.open_app_interface_merge_request.assert_called_once() # type: ignore[attr-defined]
|
58
|
+
vcs.close_app_interface_mr.assert_not_called()
|
59
|
+
vcs.open_app_interface_merge_request.assert_not_called()
|
@@ -1,96 +0,0 @@
|
|
1
|
-
from collections.abc import (
|
2
|
-
Callable,
|
3
|
-
Iterable,
|
4
|
-
)
|
5
|
-
from unittest.mock import call, create_autospec
|
6
|
-
|
7
|
-
from gitlab.v4.objects import ProjectMergeRequest
|
8
|
-
|
9
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager import (
|
10
|
-
MergeRequestManager,
|
11
|
-
)
|
12
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
13
|
-
MRParser,
|
14
|
-
OpenMergeRequest,
|
15
|
-
)
|
16
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
17
|
-
Renderer,
|
18
|
-
)
|
19
|
-
from reconcile.utils.vcs import VCS
|
20
|
-
|
21
|
-
|
22
|
-
def test_unbatch_multiple_valid(
|
23
|
-
mr_parser_builder: Callable[[Iterable], MRParser],
|
24
|
-
renderer: Renderer,
|
25
|
-
) -> None:
|
26
|
-
# We have 2 MRs that failed MR check, but are marked as batchable
|
27
|
-
open_mrs = [
|
28
|
-
OpenMergeRequest(
|
29
|
-
raw=create_autospec(spec=ProjectMergeRequest),
|
30
|
-
channels="multiple,aggregated,channels",
|
31
|
-
content_hashes="a,b,c",
|
32
|
-
is_batchable=True,
|
33
|
-
failed_mr_check=True,
|
34
|
-
),
|
35
|
-
OpenMergeRequest(
|
36
|
-
raw=create_autospec(spec=ProjectMergeRequest),
|
37
|
-
channels="chan",
|
38
|
-
content_hashes="d",
|
39
|
-
is_batchable=True,
|
40
|
-
failed_mr_check=True,
|
41
|
-
),
|
42
|
-
]
|
43
|
-
mr_parser = mr_parser_builder(open_mrs)
|
44
|
-
|
45
|
-
vcs = create_autospec(spec=VCS)
|
46
|
-
merge_request_manager = MergeRequestManager(
|
47
|
-
vcs=vcs,
|
48
|
-
mr_parser=mr_parser,
|
49
|
-
renderer=renderer,
|
50
|
-
)
|
51
|
-
expected_close_mr_calls = [
|
52
|
-
call(
|
53
|
-
mr.raw,
|
54
|
-
"Closing this MR because it failed MR check and isn't marked un-batchable yet.",
|
55
|
-
)
|
56
|
-
for mr in open_mrs
|
57
|
-
]
|
58
|
-
merge_request_manager.housekeeping()
|
59
|
-
vcs.close_app_interface_mr.assert_has_calls(expected_close_mr_calls, any_order=True)
|
60
|
-
assert vcs.close_app_interface_mr.call_count == 2
|
61
|
-
assert merge_request_manager._unbatchable_hashes == set(["a", "b", "c", "d"])
|
62
|
-
assert len(merge_request_manager._open_mrs) == 0
|
63
|
-
|
64
|
-
|
65
|
-
def test_unbatch_multiple_invalid(
|
66
|
-
mr_parser_builder: Callable[[Iterable], MRParser],
|
67
|
-
renderer: Renderer,
|
68
|
-
) -> None:
|
69
|
-
open_mrs = [
|
70
|
-
OpenMergeRequest(
|
71
|
-
raw=create_autospec(spec=ProjectMergeRequest),
|
72
|
-
channels="multiple,aggregated,channels",
|
73
|
-
content_hashes="a,b,c",
|
74
|
-
is_batchable=False,
|
75
|
-
failed_mr_check=False,
|
76
|
-
),
|
77
|
-
OpenMergeRequest(
|
78
|
-
raw=create_autospec(spec=ProjectMergeRequest),
|
79
|
-
channels="chan",
|
80
|
-
content_hashes="d",
|
81
|
-
is_batchable=True,
|
82
|
-
failed_mr_check=False,
|
83
|
-
),
|
84
|
-
]
|
85
|
-
mr_parser = mr_parser_builder(open_mrs)
|
86
|
-
|
87
|
-
vcs = create_autospec(spec=VCS)
|
88
|
-
merge_request_manager = MergeRequestManager(
|
89
|
-
vcs=vcs,
|
90
|
-
mr_parser=mr_parser,
|
91
|
-
renderer=renderer,
|
92
|
-
)
|
93
|
-
merge_request_manager.housekeeping()
|
94
|
-
vcs.close_app_interface_mr.assert_not_called()
|
95
|
-
assert merge_request_manager._unbatchable_hashes == set()
|
96
|
-
assert len(merge_request_manager._open_mrs) == 2
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc514.dist-info → qontract_reconcile-0.10.1rc515.dist-info}/top_level.txt
RENAMED
File without changes
|