qontract-reconcile 0.10.1rc766__py3-none-any.whl → 0.10.1rc767__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.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/METADATA +1 -1
- {qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/RECORD +18 -17
- reconcile/saas_auto_promotions_manager/integration.py +4 -4
- reconcile/saas_auto_promotions_manager/merge_request_manager/{reconciler.py → batcher.py} +12 -12
- reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py +1 -1
- reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py +7 -6
- reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py +70 -36
- reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py +23 -0
- reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py +1 -0
- reconcile/saas_auto_promotions_manager/meta.py +1 -1
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py +10 -10
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py +11 -9
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py +44 -5
- reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py +25 -25
- reconcile/test/saas_auto_promotions_manager/test_integration_test.py +4 -4
- {qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/WHEEL +0 -0
- {qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/entry_points.txt +0 -0
- {qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/top_level.txt +0 -0
{qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: qontract-reconcile
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.1rc767
|
4
4
|
Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
|
5
5
|
Home-page: https://github.com/app-sre/qontract-reconcile
|
6
6
|
Author: Red Hat App-SRE Team
|
{qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/RECORD
RENAMED
@@ -406,19 +406,20 @@ reconcile/rhidp/sso_client/base.py,sha256=EfQ2ewcOKh5idg46UKAkY6z0m_nGQfvnQKffa2
|
|
406
406
|
reconcile/rhidp/sso_client/integration.py,sha256=kA8g7c38ZBSdrRtyfEqy_WgSreD1PbwY7ZIN-3tZRPc,2221
|
407
407
|
reconcile/rhidp/sso_client/metrics.py,sha256=Tq7tSOsqL3XdcPUdozxqzSPIodUeOV87UCTqpuuqqhw,1013
|
408
408
|
reconcile/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
409
|
-
reconcile/saas_auto_promotions_manager/integration.py,sha256=
|
410
|
-
reconcile/saas_auto_promotions_manager/meta.py,sha256=
|
409
|
+
reconcile/saas_auto_promotions_manager/integration.py,sha256=8IXLEvpblgZRr2UPfTsaLZIUDJOdJaoakhqLBkGU_Es,6750
|
410
|
+
reconcile/saas_auto_promotions_manager/meta.py,sha256=76Jp50r6Y_KyJoXFfSjrt5YrCtXyg_A4FXXxHYiS3TE,161
|
411
411
|
reconcile/saas_auto_promotions_manager/publisher.py,sha256=psrthZGgCQDUO3rwQjKSBMlwcTgfij6sxdebGuxkNv4,2739
|
412
412
|
reconcile/saas_auto_promotions_manager/s3_exporter.py,sha256=IKlVWZmiPnvl7sKeF6JgAlhXZe5CovKTxQc0SNkNSx4,2583
|
413
413
|
reconcile/saas_auto_promotions_manager/subscriber.py,sha256=NPhlagNF8om7ikrjRlYNSQ2Ra7wgW_3-OlEWapnjtW0,9405
|
414
414
|
reconcile/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
415
|
-
reconcile/saas_auto_promotions_manager/merge_request_manager/
|
415
|
+
reconcile/saas_auto_promotions_manager/merge_request_manager/batcher.py,sha256=lHIULPE8nmPN9pJVfZFdD0l48EB20o4cAy4owahJenw,7848
|
416
|
+
reconcile/saas_auto_promotions_manager/merge_request_manager/desired_state.py,sha256=isY8frVsL3PlcdZmdZ4O0qyp76oczl4DUMX9uMArs5Y,1222
|
416
417
|
reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request.py,sha256=BeAJWLow7b4HQyZ9zz398sQkPeIz8chpMkCts2NU27c,1282
|
417
|
-
reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256
|
418
|
+
reconcile/saas_auto_promotions_manager/merge_request_manager/merge_request_manager_v2.py,sha256=-zWK-cqr_8o9ZEnNfD3cfkv3hrrU4HJ4UMzi4J2Hjhw,6223
|
418
419
|
reconcile/saas_auto_promotions_manager/merge_request_manager/metrics.py,sha256=sdHp71Wl87tFM-Z_QvqvdHhyrppFLGi4ekksCi_e_bs,977
|
419
|
-
reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256=
|
420
|
-
reconcile/saas_auto_promotions_manager/merge_request_manager/
|
421
|
-
reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=
|
420
|
+
reconcile/saas_auto_promotions_manager/merge_request_manager/mr_parser.py,sha256=WDpClngRA7o9j9o8WsTDDU42p_xVqkmr6dERxQXBIAA,8579
|
421
|
+
reconcile/saas_auto_promotions_manager/merge_request_manager/open_merge_requests.py,sha256=-qGQOh6Jdp4lomNDij3zWVC0pl6uPHFWS5Woqcp5HQk,410
|
422
|
+
reconcile/saas_auto_promotions_manager/merge_request_manager/renderer.py,sha256=ERi-a400C-c0HnAyS6EsvCrsyY3MO4xL8N3A1e04T4M,7087
|
422
423
|
reconcile/saas_auto_promotions_manager/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
423
424
|
reconcile/saas_auto_promotions_manager/utils/saas_files_inventory.py,sha256=7LlTQCzYotWCbtYBaNQP81CFlLUOvsyGMBQE-Ha0cKY,7820
|
424
425
|
reconcile/skupper_network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -535,15 +536,15 @@ reconcile/test/test_vpc_peerings_validator.py,sha256=dFSmjc_dMN2GqMbntCFpa7PUZmy
|
|
535
536
|
reconcile/test/test_wrong_region.py,sha256=7KzL7OaICQ9Z3DW27zt_ykMN7_87owAFC-2CYjvGoyA,2138
|
536
537
|
reconcile/test/saas_auto_promotions_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
537
538
|
reconcile/test/saas_auto_promotions_manager/conftest.py,sha256=4BtuxVZ0Lsmdp6AhG8kbtowkwG7e-pSjIKv35Wm1hI0,5803
|
538
|
-
reconcile/test/saas_auto_promotions_manager/test_integration_test.py,sha256=
|
539
|
+
reconcile/test/saas_auto_promotions_manager/test_integration_test.py,sha256=S30eXJSy2Vc3YLbCP7AfLkOiFGUVoKhEvEBL5vwnbfg,1848
|
539
540
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
540
541
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
541
|
-
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py,sha256=
|
542
|
+
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py,sha256=y_SL9zBr98SlOnvbA9C7a0_dFZrRAbkuR85m_u6ijcI,3520
|
542
543
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/data_keys.py,sha256=Z1IV51OUuzhd-3S8W-k7ixC-fkaglCokn0eakK0Z73s,606
|
543
544
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_desired_state.py,sha256=OLtJ11SsznoT39_tudsozcksK0N3TVNv-JWhIrCVaQk,2356
|
544
|
-
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py,sha256=
|
545
|
-
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py,sha256=
|
546
|
-
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py,sha256=
|
545
|
+
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_merge_request_manager.py,sha256=5jOrR5flENfqz7c9ADnjm-yPl7DJLTyVZM1ndvm9MVY,2491
|
546
|
+
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_mr_parser.py,sha256=aohFc18g9DKt0kK1YypXJrBGE8eGhsVMOGd1KOCzX0k,11677
|
547
|
+
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/test_reconciler.py,sha256=REBOmIt1hwu9K5zqyQdKIDhma2YUWIKidI7SJ4GB9ZE,17969
|
547
548
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
548
549
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/conftest.py,sha256=MjTLg7KwvdIYvxkCzgJG-gByD1fZxaq6c4SI6rWWUu8,552
|
549
550
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/renderer/test_content_multiple_namespaces.py,sha256=6LMsnbPx5svTF1nL6oQGLTp1NgjLG_tO56c0hbA2Di4,1059
|
@@ -782,8 +783,8 @@ tools/test/test_app_interface_metrics_exporter.py,sha256=SX7qL3D1SIRKFo95FoQztvf
|
|
782
783
|
tools/test/test_qontract_cli.py,sha256=w2l4BHB09k1d-BGJ1jBUNCqDv7zkqYrMHojQXg-21kQ,4155
|
783
784
|
tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
|
784
785
|
tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
|
785
|
-
qontract_reconcile-0.10.
|
786
|
-
qontract_reconcile-0.10.
|
787
|
-
qontract_reconcile-0.10.
|
788
|
-
qontract_reconcile-0.10.
|
789
|
-
qontract_reconcile-0.10.
|
786
|
+
qontract_reconcile-0.10.1rc767.dist-info/METADATA,sha256=JWA4m9u9lod5MIvLOvk3dDfvQrKGG8cmdIdd4tpoU9M,2382
|
787
|
+
qontract_reconcile-0.10.1rc767.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
788
|
+
qontract_reconcile-0.10.1rc767.dist-info/entry_points.txt,sha256=rIxI5zWtHNlfpDeq1a7pZXAPoqf7HG32KMTN3MeWK_8,429
|
789
|
+
qontract_reconcile-0.10.1rc767.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
|
790
|
+
qontract_reconcile-0.10.1rc767.dist-info/RECORD,,
|
@@ -6,15 +6,15 @@ from sretoolbox.utils import threaded
|
|
6
6
|
from reconcile.openshift_saas_deploy import (
|
7
7
|
QONTRACT_INTEGRATION as OPENSHIFT_SAAS_DEPLOY,
|
8
8
|
)
|
9
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
10
|
+
Batcher,
|
11
|
+
)
|
9
12
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
|
10
13
|
MergeRequestManagerV2,
|
11
14
|
)
|
12
15
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
13
16
|
MRParser,
|
14
17
|
)
|
15
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
16
|
-
Reconciler,
|
17
|
-
)
|
18
18
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
19
19
|
Renderer,
|
20
20
|
)
|
@@ -135,7 +135,7 @@ def init_external_dependencies(
|
|
135
135
|
mr_parser = MRParser(vcs=vcs)
|
136
136
|
merge_request_manager_v2 = MergeRequestManagerV2(
|
137
137
|
vcs=vcs,
|
138
|
-
reconciler=
|
138
|
+
reconciler=Batcher(),
|
139
139
|
mr_parser=mr_parser,
|
140
140
|
renderer=Renderer(),
|
141
141
|
)
|
@@ -3,8 +3,8 @@ from dataclasses import dataclass
|
|
3
3
|
from enum import Enum
|
4
4
|
from typing import Optional
|
5
5
|
|
6
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.
|
7
|
-
|
6
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_requests import (
|
7
|
+
OpenBatcherMergeRequest,
|
8
8
|
)
|
9
9
|
|
10
10
|
|
@@ -22,7 +22,7 @@ class Promotion:
|
|
22
22
|
|
23
23
|
@dataclass
|
24
24
|
class Deletion:
|
25
|
-
mr:
|
25
|
+
mr: OpenBatcherMergeRequest
|
26
26
|
reason: Reason
|
27
27
|
|
28
28
|
|
@@ -39,18 +39,18 @@ class Diff:
|
|
39
39
|
additions: list[Addition]
|
40
40
|
|
41
41
|
|
42
|
-
class
|
42
|
+
class Batcher:
|
43
43
|
"""
|
44
|
-
The
|
45
|
-
and which MRs need to be closed (Deletion). The
|
46
|
-
dependencies and does not interact with VCS. The
|
44
|
+
The batcher calculates a Diff. I.e., which MRs need to be opened (Addition)
|
45
|
+
and which MRs need to be closed (Deletion). The batcher has no external
|
46
|
+
dependencies and does not interact with VCS. The batcher expects to be
|
47
47
|
given the desired state (which promotions do we want) and the current state
|
48
48
|
(the currently open MRs) in order to calculate the Diff.
|
49
49
|
"""
|
50
50
|
|
51
51
|
def __init__(self) -> None:
|
52
52
|
self._desired_promotions: Iterable[Promotion] = []
|
53
|
-
self._open_mrs: Iterable[
|
53
|
+
self._open_mrs: Iterable[OpenBatcherMergeRequest] = []
|
54
54
|
|
55
55
|
def _unbatch(self, diff: Diff) -> None:
|
56
56
|
"""
|
@@ -61,7 +61,7 @@ class Reconciler:
|
|
61
61
|
and close the old batched MR. By doing so, we ensure that unrelated MRs are not blocking each other.
|
62
62
|
Unbatched MRs are marked and will never be batched again.
|
63
63
|
"""
|
64
|
-
open_mrs_after_unbatching: list[
|
64
|
+
open_mrs_after_unbatching: list[OpenBatcherMergeRequest] = []
|
65
65
|
unbatchable_hashes: set[str] = set()
|
66
66
|
falsely_marked_batchable_hashes: set[str] = set()
|
67
67
|
for mr in self._open_mrs:
|
@@ -107,7 +107,7 @@ class Reconciler:
|
|
107
107
|
for promotion in self._desired_promotions:
|
108
108
|
all_desired_content_hashes.update(promotion.content_hashes)
|
109
109
|
|
110
|
-
open_mrs_after_deletion: list[
|
110
|
+
open_mrs_after_deletion: list[OpenBatcherMergeRequest] = []
|
111
111
|
for mr in self._open_mrs:
|
112
112
|
if mr.content_hashes.issubset(all_desired_content_hashes):
|
113
113
|
open_mrs_after_deletion.append(mr)
|
@@ -145,7 +145,7 @@ class Reconciler:
|
|
145
145
|
if not unsubmitted_promotions:
|
146
146
|
return
|
147
147
|
|
148
|
-
batch_with_capacity: Optional[
|
148
|
+
batch_with_capacity: Optional[OpenBatcherMergeRequest] = None
|
149
149
|
for mr in self._open_mrs:
|
150
150
|
if mr.is_batchable and len(mr.content_hashes) < batch_limit:
|
151
151
|
batch_with_capacity = mr
|
@@ -194,7 +194,7 @@ class Reconciler:
|
|
194
194
|
def reconcile(
|
195
195
|
self,
|
196
196
|
desired_promotions: Iterable[Promotion],
|
197
|
-
open_mrs: Iterable[
|
197
|
+
open_mrs: Iterable[OpenBatcherMergeRequest],
|
198
198
|
batch_limit: int,
|
199
199
|
) -> Diff:
|
200
200
|
self._open_mrs = open_mrs
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from collections import defaultdict
|
2
2
|
from collections.abc import Iterable
|
3
3
|
|
4
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.
|
4
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
5
5
|
Promotion,
|
6
6
|
)
|
7
7
|
from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
|
@@ -3,6 +3,10 @@ from collections.abc import Iterable
|
|
3
3
|
|
4
4
|
from gitlab.exceptions import GitlabGetError
|
5
5
|
|
6
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
7
|
+
Addition,
|
8
|
+
Batcher,
|
9
|
+
)
|
6
10
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.desired_state import (
|
7
11
|
DesiredState,
|
8
12
|
)
|
@@ -21,10 +25,6 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.metrics import
|
|
21
25
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
22
26
|
MRParser,
|
23
27
|
)
|
24
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
25
|
-
Addition,
|
26
|
-
Reconciler,
|
27
|
-
)
|
28
28
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
29
29
|
Renderer,
|
30
30
|
)
|
@@ -61,7 +61,7 @@ class MergeRequestManagerV2:
|
|
61
61
|
"""
|
62
62
|
|
63
63
|
def __init__(
|
64
|
-
self, vcs: VCS, mr_parser: MRParser, reconciler:
|
64
|
+
self, vcs: VCS, mr_parser: MRParser, reconciler: Batcher, renderer: Renderer
|
65
65
|
):
|
66
66
|
self._vcs = vcs
|
67
67
|
self._mr_parser = mr_parser
|
@@ -130,7 +130,8 @@ class MergeRequestManagerV2:
|
|
130
130
|
)
|
131
131
|
|
132
132
|
def reconcile(self, subscribers: Iterable[Subscriber]) -> None:
|
133
|
-
|
133
|
+
self._mr_parser.fetch_mrs(label=SAPM_LABEL)
|
134
|
+
current_state = self._mr_parser.get_open_batcher_mrs()
|
134
135
|
desired_state = DesiredState(subscribers=subscribers)
|
135
136
|
self._desired_state = desired_state
|
136
137
|
|
@@ -1,29 +1,25 @@
|
|
1
1
|
import logging
|
2
2
|
import re
|
3
|
-
from
|
3
|
+
from collections.abc import Iterable
|
4
4
|
|
5
5
|
from gitlab.v4.objects import ProjectMergeRequest
|
6
6
|
|
7
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_requests import (
|
8
|
+
MRKind,
|
9
|
+
OpenBatcherMergeRequest,
|
10
|
+
OpenSchedulerMergeRequest,
|
11
|
+
)
|
7
12
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
8
13
|
CHANNELS_REF,
|
9
14
|
CONTENT_HASHES,
|
10
15
|
IS_BATCHABLE,
|
16
|
+
MR_KIND_REF,
|
11
17
|
PROMOTION_DATA_SEPARATOR,
|
12
18
|
SAPM_VERSION,
|
13
19
|
VERSION_REF,
|
14
20
|
)
|
15
21
|
from reconcile.utils.vcs import VCS, MRCheckStatus
|
16
22
|
|
17
|
-
|
18
|
-
@dataclass
|
19
|
-
class OpenMergeRequest:
|
20
|
-
raw: ProjectMergeRequest
|
21
|
-
content_hashes: set[str]
|
22
|
-
channels: set[str]
|
23
|
-
failed_mr_check: bool
|
24
|
-
is_batchable: bool
|
25
|
-
|
26
|
-
|
27
23
|
ITEM_SEPARATOR = ","
|
28
24
|
|
29
25
|
|
@@ -41,6 +37,15 @@ class MRParser:
|
|
41
37
|
self._content_hash_regex = re.compile(rf"{CONTENT_HASHES}: (.*)$", re.MULTILINE)
|
42
38
|
self._channels_regex = re.compile(rf"{CHANNELS_REF}: (.*)$", re.MULTILINE)
|
43
39
|
self._is_batchable_regex = re.compile(rf"{IS_BATCHABLE}: (.*)$", re.MULTILINE)
|
40
|
+
self._mr_kind_regex = re.compile(rf"{MR_KIND_REF}: (.*)$", re.MULTILINE)
|
41
|
+
self._open_batcher_mrs: list[OpenBatcherMergeRequest] = []
|
42
|
+
self._open_scheduler_mrs: list[OpenSchedulerMergeRequest] = []
|
43
|
+
|
44
|
+
def get_open_batcher_mrs(self) -> list[OpenBatcherMergeRequest]:
|
45
|
+
return self._open_batcher_mrs
|
46
|
+
|
47
|
+
def get_open_scheduler_mrs(self) -> list[OpenSchedulerMergeRequest]:
|
48
|
+
return self._open_scheduler_mrs
|
44
49
|
|
45
50
|
def _apply_regex(self, pattern: re.Pattern, promotion_data: str) -> str:
|
46
51
|
matches = pattern.search(promotion_data)
|
@@ -51,15 +56,9 @@ class MRParser:
|
|
51
56
|
return ""
|
52
57
|
return groups[0]
|
53
58
|
|
54
|
-
def
|
55
|
-
self, label: str
|
56
|
-
) -> list[ProjectMergeRequest]:
|
57
|
-
all_open_mrs = self._vcs.get_open_app_interface_merge_requests()
|
58
|
-
return [mr for mr in all_open_mrs if label in mr.attributes.get("labels")]
|
59
|
-
|
60
|
-
def retrieve_open_mrs(self, label: str) -> list[OpenMergeRequest]:
|
59
|
+
def fetch_mrs(self, label: str) -> None:
|
61
60
|
"""
|
62
|
-
This function parses the state
|
61
|
+
This function parses the state of valid, parsed open MRs (current state).
|
63
62
|
If any issue is encountered during parsing, we consider this MR
|
64
63
|
to be broken and close it. Information we want to parse includes:
|
65
64
|
- SAPM_VERSION -> Close if it doesnt match current version
|
@@ -68,21 +67,14 @@ class MRParser:
|
|
68
67
|
- IS_BATCHABLE flag
|
69
68
|
- MR has merge conflicts
|
70
69
|
"""
|
71
|
-
|
72
|
-
|
73
|
-
|
70
|
+
all_open_mrs = self._vcs.get_open_app_interface_merge_requests()
|
71
|
+
sapm_mrs = [mr for mr in all_open_mrs if label in mr.attributes.get("labels")]
|
72
|
+
open_batcher_mrs: list[ProjectMergeRequest] = []
|
73
|
+
open_scheduler_mrs: list[ProjectMergeRequest] = []
|
74
|
+
|
75
|
+
for mr in sapm_mrs:
|
74
76
|
attrs = mr.attributes
|
75
77
|
desc = attrs.get("description")
|
76
|
-
has_conflicts = attrs.get("has_conflicts", False)
|
77
|
-
if has_conflicts:
|
78
|
-
logging.info(
|
79
|
-
"Merge-conflict detected. Closing %s",
|
80
|
-
mr.attributes.get("web_url", "NO_WEBURL"),
|
81
|
-
)
|
82
|
-
self._vcs.close_app_interface_mr(
|
83
|
-
mr, "Closing this MR because of a merge-conflict."
|
84
|
-
)
|
85
|
-
continue
|
86
78
|
parts = desc.split(PROMOTION_DATA_SEPARATOR)
|
87
79
|
if not len(parts) == 2:
|
88
80
|
logging.info(
|
@@ -121,6 +113,49 @@ class MRParser:
|
|
121
113
|
)
|
122
114
|
continue
|
123
115
|
|
116
|
+
mr_kind_str = self._apply_regex(
|
117
|
+
pattern=self._mr_kind_regex, promotion_data=promotion_data
|
118
|
+
)
|
119
|
+
if not mr_kind_str or mr_kind_str not in {
|
120
|
+
MRKind.BATCHER.value,
|
121
|
+
MRKind.SCHEDULER.value,
|
122
|
+
}:
|
123
|
+
logging.info(
|
124
|
+
"Bad %s format. Closing %s",
|
125
|
+
MR_KIND_REF,
|
126
|
+
mr.attributes.get("web_url", "NO_WEBURL"),
|
127
|
+
)
|
128
|
+
self._vcs.close_app_interface_mr(
|
129
|
+
mr, f"Closing this MR because of bad {MR_KIND_REF} format."
|
130
|
+
)
|
131
|
+
continue
|
132
|
+
|
133
|
+
mr_kind = MRKind(mr_kind_str)
|
134
|
+
if mr_kind == MRKind.BATCHER:
|
135
|
+
open_batcher_mrs.append(mr)
|
136
|
+
elif mr_kind == MRKind.SCHEDULER:
|
137
|
+
open_scheduler_mrs.append(mr)
|
138
|
+
|
139
|
+
self._handle_open_batcher_mrs(open_batcher_mrs)
|
140
|
+
|
141
|
+
def _handle_open_batcher_mrs(self, mrs: Iterable[ProjectMergeRequest]) -> None:
|
142
|
+
seen: set[tuple[str, str]] = set()
|
143
|
+
for mr in mrs:
|
144
|
+
attrs = mr.attributes
|
145
|
+
desc = attrs.get("description")
|
146
|
+
parts = desc.split(PROMOTION_DATA_SEPARATOR)
|
147
|
+
promotion_data = parts[1]
|
148
|
+
has_conflicts = attrs.get("has_conflicts", False)
|
149
|
+
if has_conflicts:
|
150
|
+
logging.info(
|
151
|
+
"Merge-conflict detected. Closing %s",
|
152
|
+
mr.attributes.get("web_url", "NO_WEBURL"),
|
153
|
+
)
|
154
|
+
self._vcs.close_app_interface_mr(
|
155
|
+
mr, "Closing this MR because of a merge-conflict."
|
156
|
+
)
|
157
|
+
continue
|
158
|
+
|
124
159
|
content_hashes = self._apply_regex(
|
125
160
|
pattern=self._content_hash_regex, promotion_data=promotion_data
|
126
161
|
)
|
@@ -149,7 +184,7 @@ class MRParser:
|
|
149
184
|
)
|
150
185
|
continue
|
151
186
|
|
152
|
-
key = (
|
187
|
+
key = (channels_refs, content_hashes)
|
153
188
|
if key in seen:
|
154
189
|
logging.info(
|
155
190
|
"Duplicate MR detected. Closing %s",
|
@@ -178,8 +213,8 @@ class MRParser:
|
|
178
213
|
|
179
214
|
mr_check_status = self._vcs.get_gitlab_mr_check_status(mr)
|
180
215
|
|
181
|
-
|
182
|
-
|
216
|
+
self._open_batcher_mrs.append(
|
217
|
+
OpenBatcherMergeRequest(
|
183
218
|
raw=mr,
|
184
219
|
content_hashes=set(content_hashes.split(ITEM_SEPARATOR)),
|
185
220
|
channels=set(channels_refs.split(ITEM_SEPARATOR)),
|
@@ -187,4 +222,3 @@ class MRParser:
|
|
187
222
|
is_batchable=is_batchable_str == "True",
|
188
223
|
)
|
189
224
|
)
|
190
|
-
return open_mrs
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from dataclasses import dataclass
|
2
|
+
from enum import Enum
|
3
|
+
|
4
|
+
from gitlab.v4.objects import ProjectMergeRequest
|
5
|
+
|
6
|
+
|
7
|
+
class MRKind(Enum):
|
8
|
+
BATCHER = "batcher"
|
9
|
+
SCHEDULER = "scheduler"
|
10
|
+
|
11
|
+
|
12
|
+
@dataclass
|
13
|
+
class OpenBatcherMergeRequest:
|
14
|
+
raw: ProjectMergeRequest
|
15
|
+
content_hashes: set[str]
|
16
|
+
channels: set[str]
|
17
|
+
failed_mr_check: bool
|
18
|
+
is_batchable: bool
|
19
|
+
|
20
|
+
|
21
|
+
@dataclass
|
22
|
+
class OpenSchedulerMergeRequest:
|
23
|
+
pass
|
reconcile/test/saas_auto_promotions_manager/merge_request_manager/merge_request_manager/conftest.py
CHANGED
@@ -8,16 +8,16 @@ from unittest.mock import create_autospec
|
|
8
8
|
import pytest
|
9
9
|
from gitlab.v4.objects import ProjectMergeRequest
|
10
10
|
|
11
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
12
|
+
Batcher,
|
13
|
+
Diff,
|
14
|
+
)
|
11
15
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
|
12
16
|
SAPM_LABEL,
|
13
17
|
)
|
14
18
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
15
19
|
MRParser,
|
16
|
-
|
17
|
-
)
|
18
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
19
|
-
Diff,
|
20
|
-
Reconciler,
|
20
|
+
OpenBatcherMergeRequest,
|
21
21
|
)
|
22
22
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
23
23
|
CHANNELS_REF,
|
@@ -91,8 +91,8 @@ def vcs_builder(
|
|
91
91
|
|
92
92
|
|
93
93
|
@pytest.fixture
|
94
|
-
def mr_parser_builder() -> Callable[[Iterable[
|
95
|
-
def builder(data: Iterable[
|
94
|
+
def mr_parser_builder() -> Callable[[Iterable[OpenBatcherMergeRequest]], MRParser]:
|
95
|
+
def builder(data: Iterable[OpenBatcherMergeRequest]) -> MRParser:
|
96
96
|
mr_parser = create_autospec(spec=MRParser)
|
97
97
|
mr_parser.retrieve_open_mrs.side_effect = [data]
|
98
98
|
return mr_parser
|
@@ -101,9 +101,9 @@ def mr_parser_builder() -> Callable[[Iterable[OpenMergeRequest]], MRParser]:
|
|
101
101
|
|
102
102
|
|
103
103
|
@pytest.fixture
|
104
|
-
def reconciler_builder() -> Callable[[Diff],
|
105
|
-
def builder(data: Diff) ->
|
106
|
-
reconciler = create_autospec(spec=
|
104
|
+
def reconciler_builder() -> Callable[[Diff], Batcher]:
|
105
|
+
def builder(data: Diff) -> Batcher:
|
106
|
+
reconciler = create_autospec(spec=Batcher)
|
107
107
|
reconciler.reconcile.side_effect = [data]
|
108
108
|
return reconciler
|
109
109
|
|
@@ -3,19 +3,21 @@ from unittest.mock import call, create_autospec
|
|
3
3
|
|
4
4
|
from gitlab.v4.objects import ProjectMergeRequest
|
5
5
|
|
6
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
7
|
+
Addition,
|
8
|
+
Batcher,
|
9
|
+
Deletion,
|
10
|
+
Diff,
|
11
|
+
Reason,
|
12
|
+
)
|
6
13
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
|
7
14
|
MergeRequestManagerV2,
|
8
15
|
)
|
9
16
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
10
17
|
MRParser,
|
11
|
-
OpenMergeRequest,
|
12
18
|
)
|
13
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.
|
14
|
-
|
15
|
-
Deletion,
|
16
|
-
Diff,
|
17
|
-
Reason,
|
18
|
-
Reconciler,
|
19
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_requests import (
|
20
|
+
OpenBatcherMergeRequest,
|
19
21
|
)
|
20
22
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
21
23
|
Renderer,
|
@@ -29,7 +31,7 @@ from reconcile.utils.vcs import VCS
|
|
29
31
|
|
30
32
|
|
31
33
|
def test_reconcile(
|
32
|
-
reconciler_builder: Callable[[Diff],
|
34
|
+
reconciler_builder: Callable[[Diff], Batcher],
|
33
35
|
subscriber_builder: Callable[..., Subscriber],
|
34
36
|
) -> None:
|
35
37
|
vcs = create_autospec(spec=VCS)
|
@@ -42,7 +44,7 @@ def test_reconcile(
|
|
42
44
|
})
|
43
45
|
]
|
44
46
|
deletion = Deletion(
|
45
|
-
mr=
|
47
|
+
mr=OpenBatcherMergeRequest(
|
46
48
|
raw=create_autospec(spec=ProjectMergeRequest),
|
47
49
|
channels=set(),
|
48
50
|
content_hashes=set(),
|
@@ -12,10 +12,14 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_
|
|
12
12
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
13
13
|
MRParser,
|
14
14
|
)
|
15
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_requests import (
|
16
|
+
MRKind,
|
17
|
+
)
|
15
18
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
16
19
|
CHANNELS_REF,
|
17
20
|
CONTENT_HASHES,
|
18
21
|
IS_BATCHABLE,
|
22
|
+
MR_KIND_REF,
|
19
23
|
PROMOTION_DATA_SEPARATOR,
|
20
24
|
SAPM_VERSION,
|
21
25
|
VERSION_REF,
|
@@ -44,6 +48,7 @@ def test_valid_parsing(
|
|
44
48
|
{CHANNELS_REF}: channel0
|
45
49
|
{CONTENT_HASHES}: hash0
|
46
50
|
{IS_BATCHABLE}: True
|
51
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
47
52
|
""",
|
48
53
|
},
|
49
54
|
{
|
@@ -55,6 +60,7 @@ def test_valid_parsing(
|
|
55
60
|
{CHANNELS_REF}: channel1
|
56
61
|
{CONTENT_HASHES}: hash1
|
57
62
|
{IS_BATCHABLE}: False
|
63
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
58
64
|
""",
|
59
65
|
},
|
60
66
|
]
|
@@ -62,7 +68,8 @@ def test_valid_parsing(
|
|
62
68
|
mr_parser = MRParser(
|
63
69
|
vcs=vcs,
|
64
70
|
)
|
65
|
-
|
71
|
+
mr_parser.fetch_mrs(label=SAPM_LABEL)
|
72
|
+
open_mrs = mr_parser._open_batcher_mrs
|
66
73
|
assert len(open_mrs) == 2
|
67
74
|
|
68
75
|
assert open_mrs[0].raw == expectd_mrs[0]
|
@@ -90,6 +97,7 @@ def test_labels_filter(
|
|
90
97
|
{CHANNELS_REF}: other-channel
|
91
98
|
{CONTENT_HASHES}: other_hash
|
92
99
|
{IS_BATCHABLE}: True
|
100
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
93
101
|
""",
|
94
102
|
},
|
95
103
|
# This MR should get ignored
|
@@ -102,6 +110,7 @@ def test_labels_filter(
|
|
102
110
|
{CHANNELS_REF}: some-channel
|
103
111
|
{CONTENT_HASHES}: some_hash
|
104
112
|
{IS_BATCHABLE}: True
|
113
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
105
114
|
""",
|
106
115
|
},
|
107
116
|
]
|
@@ -109,7 +118,8 @@ def test_labels_filter(
|
|
109
118
|
mr_parser = MRParser(
|
110
119
|
vcs=vcs,
|
111
120
|
)
|
112
|
-
|
121
|
+
mr_parser.fetch_mrs(label=SAPM_LABEL)
|
122
|
+
open_mrs = mr_parser.get_open_batcher_mrs()
|
113
123
|
assert len(open_mrs) == 1
|
114
124
|
assert open_mrs[0].raw == expectd_mrs[0]
|
115
125
|
|
@@ -128,6 +138,7 @@ def test_bad_mrs(
|
|
128
138
|
{CHANNELS_REF}: some-channel
|
129
139
|
{CONTENT_HASHES}: hash_1
|
130
140
|
{IS_BATCHABLE}: True
|
141
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
131
142
|
""",
|
132
143
|
},
|
133
144
|
{
|
@@ -139,6 +150,7 @@ def test_bad_mrs(
|
|
139
150
|
{CHANNELS_REF}: some-channel
|
140
151
|
{IS_BATCHABLE}: True
|
141
152
|
missing-content-hash-key: some_hash
|
153
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
142
154
|
""",
|
143
155
|
},
|
144
156
|
{
|
@@ -149,6 +161,7 @@ def test_bad_mrs(
|
|
149
161
|
{VERSION_REF}: {SAPM_VERSION}
|
150
162
|
{CONTENT_HASHES}: hash_3
|
151
163
|
{IS_BATCHABLE}: True
|
164
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
152
165
|
""",
|
153
166
|
},
|
154
167
|
{
|
@@ -160,6 +173,7 @@ def test_bad_mrs(
|
|
160
173
|
{CHANNELS_REF}: some-channel
|
161
174
|
{CONTENT_HASHES}: hash_4
|
162
175
|
{IS_BATCHABLE}: True
|
176
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
163
177
|
""",
|
164
178
|
},
|
165
179
|
{
|
@@ -173,6 +187,7 @@ def test_bad_mrs(
|
|
173
187
|
{CHANNELS_REF}: some-channel
|
174
188
|
{CONTENT_HASHES}: hash_5
|
175
189
|
{IS_BATCHABLE}: True
|
190
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
176
191
|
""",
|
177
192
|
},
|
178
193
|
{
|
@@ -184,6 +199,7 @@ def test_bad_mrs(
|
|
184
199
|
{CHANNELS_REF}: some-channel
|
185
200
|
{CONTENT_HASHES}: hash_6
|
186
201
|
{IS_BATCHABLE}: True
|
202
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
187
203
|
""",
|
188
204
|
},
|
189
205
|
{
|
@@ -195,6 +211,7 @@ def test_bad_mrs(
|
|
195
211
|
bad_channel_ref: some-channel
|
196
212
|
{CONTENT_HASHES}: hash_7
|
197
213
|
{IS_BATCHABLE}: True
|
214
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
198
215
|
""",
|
199
216
|
},
|
200
217
|
{
|
@@ -206,6 +223,7 @@ def test_bad_mrs(
|
|
206
223
|
{CHANNELS_REF}: some-channel
|
207
224
|
{CONTENT_HASHES}: hash_8
|
208
225
|
missing-batchable-key
|
226
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
209
227
|
""",
|
210
228
|
},
|
211
229
|
{
|
@@ -217,6 +235,19 @@ def test_bad_mrs(
|
|
217
235
|
{CHANNELS_REF}: some-channel
|
218
236
|
{CONTENT_HASHES}: hash_9
|
219
237
|
{IS_BATCHABLE}: Something-non-bool
|
238
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
239
|
+
""",
|
240
|
+
},
|
241
|
+
{
|
242
|
+
LABELS: [SAPM_LABEL],
|
243
|
+
DESCRIPTION: f"""
|
244
|
+
Blabla
|
245
|
+
{PROMOTION_DATA_SEPARATOR}
|
246
|
+
{VERSION_REF}: {SAPM_VERSION}
|
247
|
+
{CHANNELS_REF}: some-channel
|
248
|
+
{CONTENT_HASHES}: hash_10
|
249
|
+
{IS_BATCHABLE}: True
|
250
|
+
{MR_KIND_REF}: blub
|
220
251
|
""",
|
221
252
|
},
|
222
253
|
]
|
@@ -261,11 +292,16 @@ def test_bad_mrs(
|
|
261
292
|
expected_mrs[8],
|
262
293
|
"Closing this MR because of bad is_batchable format.",
|
263
294
|
),
|
295
|
+
call(
|
296
|
+
expected_mrs[9],
|
297
|
+
"Closing this MR because of bad kind format.",
|
298
|
+
),
|
264
299
|
]
|
265
300
|
|
266
|
-
|
301
|
+
mr_parser.fetch_mrs(label=SAPM_LABEL)
|
302
|
+
open_mrs = mr_parser.get_open_batcher_mrs()
|
267
303
|
assert len(open_mrs) == 0
|
268
|
-
vcs.close_app_interface_mr.assert_has_calls(expected_calls) # type: ignore[attr-defined]
|
304
|
+
vcs.close_app_interface_mr.assert_has_calls(expected_calls, any_order=True) # type: ignore[attr-defined]
|
269
305
|
assert vcs.close_app_interface_mr.call_count == len(expected_calls) # type: ignore[attr-defined]
|
270
306
|
|
271
307
|
|
@@ -283,6 +319,7 @@ def test_remove_duplicates(
|
|
283
319
|
{CHANNELS_REF}: some_channel
|
284
320
|
{CONTENT_HASHES}: same_hash
|
285
321
|
{IS_BATCHABLE}: True
|
322
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
286
323
|
""",
|
287
324
|
},
|
288
325
|
{
|
@@ -294,6 +331,7 @@ def test_remove_duplicates(
|
|
294
331
|
{CHANNELS_REF}: some_channel
|
295
332
|
{CONTENT_HASHES}: same_hash
|
296
333
|
{IS_BATCHABLE}: True
|
334
|
+
{MR_KIND_REF}: {MRKind.BATCHER.value}
|
297
335
|
""",
|
298
336
|
},
|
299
337
|
]
|
@@ -301,7 +339,8 @@ def test_remove_duplicates(
|
|
301
339
|
mr_parser = MRParser(
|
302
340
|
vcs=vcs,
|
303
341
|
)
|
304
|
-
|
342
|
+
mr_parser.fetch_mrs(label=SAPM_LABEL)
|
343
|
+
open_mrs = mr_parser.get_open_batcher_mrs()
|
305
344
|
vcs.close_app_interface_mr.assert_has_calls([ # type: ignore[attr-defined]
|
306
345
|
call(
|
307
346
|
expected_mrs[1],
|
@@ -4,16 +4,16 @@ from unittest.mock import create_autospec
|
|
4
4
|
import pytest
|
5
5
|
from gitlab.v4.objects import ProjectMergeRequest
|
6
6
|
|
7
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.
|
8
|
-
OpenMergeRequest,
|
9
|
-
)
|
10
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
7
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
11
8
|
Addition,
|
9
|
+
Batcher,
|
12
10
|
Deletion,
|
13
11
|
Diff,
|
14
12
|
Promotion,
|
15
13
|
Reason,
|
16
|
-
|
14
|
+
)
|
15
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.open_merge_requests import (
|
16
|
+
OpenBatcherMergeRequest,
|
17
17
|
)
|
18
18
|
|
19
19
|
|
@@ -69,28 +69,28 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
69
69
|
(
|
70
70
|
[],
|
71
71
|
[
|
72
|
-
|
72
|
+
OpenBatcherMergeRequest(
|
73
73
|
raw=create_autospec(spec=ProjectMergeRequest),
|
74
74
|
channels={"chan1", "chan2"},
|
75
75
|
content_hashes={"hash1", "hash2"},
|
76
76
|
failed_mr_check=True,
|
77
77
|
is_batchable=True,
|
78
78
|
),
|
79
|
-
|
79
|
+
OpenBatcherMergeRequest(
|
80
80
|
raw=create_autospec(spec=ProjectMergeRequest),
|
81
81
|
channels={"chan3"},
|
82
82
|
content_hashes={"hash3"},
|
83
83
|
failed_mr_check=False,
|
84
84
|
is_batchable=True,
|
85
85
|
),
|
86
|
-
|
86
|
+
OpenBatcherMergeRequest(
|
87
87
|
raw=create_autospec(spec=ProjectMergeRequest),
|
88
88
|
channels={"chan4"},
|
89
89
|
content_hashes={"hash4"},
|
90
90
|
failed_mr_check=False,
|
91
91
|
is_batchable=False,
|
92
92
|
),
|
93
|
-
|
93
|
+
OpenBatcherMergeRequest(
|
94
94
|
raw=create_autospec(spec=ProjectMergeRequest),
|
95
95
|
channels={"chan5"},
|
96
96
|
content_hashes={"hash5"},
|
@@ -101,7 +101,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
101
101
|
Diff(
|
102
102
|
deletions=[
|
103
103
|
Deletion(
|
104
|
-
mr=
|
104
|
+
mr=OpenBatcherMergeRequest(
|
105
105
|
raw=create_autospec(spec=ProjectMergeRequest),
|
106
106
|
channels={"chan1", "chan2"},
|
107
107
|
content_hashes={"hash1", "hash2"},
|
@@ -111,7 +111,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
111
111
|
reason=Reason.MISSING_UNBATCHING,
|
112
112
|
),
|
113
113
|
Deletion(
|
114
|
-
mr=
|
114
|
+
mr=OpenBatcherMergeRequest(
|
115
115
|
raw=create_autospec(spec=ProjectMergeRequest),
|
116
116
|
channels={"chan3"},
|
117
117
|
content_hashes={"hash3"},
|
@@ -121,7 +121,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
121
121
|
reason=Reason.OUTDATED_CONTENT,
|
122
122
|
),
|
123
123
|
Deletion(
|
124
|
-
mr=
|
124
|
+
mr=OpenBatcherMergeRequest(
|
125
125
|
raw=create_autospec(spec=ProjectMergeRequest),
|
126
126
|
channels={"chan4"},
|
127
127
|
content_hashes={"hash4"},
|
@@ -131,7 +131,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
131
131
|
reason=Reason.OUTDATED_CONTENT,
|
132
132
|
),
|
133
133
|
Deletion(
|
134
|
-
mr=
|
134
|
+
mr=OpenBatcherMergeRequest(
|
135
135
|
raw=create_autospec(spec=ProjectMergeRequest),
|
136
136
|
channels={"chan5"},
|
137
137
|
content_hashes={"hash5"},
|
@@ -161,7 +161,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
161
161
|
),
|
162
162
|
],
|
163
163
|
[
|
164
|
-
|
164
|
+
OpenBatcherMergeRequest(
|
165
165
|
raw=create_autospec(spec=ProjectMergeRequest),
|
166
166
|
channels={"chan1", "chan2"},
|
167
167
|
content_hashes={"hash1", "hash2"},
|
@@ -172,7 +172,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
172
172
|
Diff(
|
173
173
|
deletions=[
|
174
174
|
Deletion(
|
175
|
-
mr=
|
175
|
+
mr=OpenBatcherMergeRequest(
|
176
176
|
raw=create_autospec(spec=ProjectMergeRequest),
|
177
177
|
channels={"chan1", "chan2"},
|
178
178
|
content_hashes={"hash1", "hash2"},
|
@@ -210,7 +210,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
210
210
|
),
|
211
211
|
],
|
212
212
|
[
|
213
|
-
|
213
|
+
OpenBatcherMergeRequest(
|
214
214
|
raw=create_autospec(spec=ProjectMergeRequest),
|
215
215
|
channels={"chan1", "chan2"},
|
216
216
|
content_hashes={"hash1", "hash2"},
|
@@ -243,7 +243,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
243
243
|
),
|
244
244
|
],
|
245
245
|
[
|
246
|
-
|
246
|
+
OpenBatcherMergeRequest(
|
247
247
|
raw=create_autospec(spec=ProjectMergeRequest),
|
248
248
|
channels={"chan1", "chan2"},
|
249
249
|
content_hashes={"hash1", "hash2"},
|
@@ -254,7 +254,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
254
254
|
Diff(
|
255
255
|
deletions=[
|
256
256
|
Deletion(
|
257
|
-
mr=
|
257
|
+
mr=OpenBatcherMergeRequest(
|
258
258
|
raw=create_autospec(spec=ProjectMergeRequest),
|
259
259
|
channels={"chan1", "chan2"},
|
260
260
|
content_hashes={"hash1", "hash2"},
|
@@ -301,7 +301,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
301
301
|
),
|
302
302
|
],
|
303
303
|
[
|
304
|
-
|
304
|
+
OpenBatcherMergeRequest(
|
305
305
|
raw=create_autospec(spec=ProjectMergeRequest),
|
306
306
|
channels={"chan1", "chan2"},
|
307
307
|
content_hashes={"hash1", "hash2"},
|
@@ -312,7 +312,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
312
312
|
Diff(
|
313
313
|
deletions=[
|
314
314
|
Deletion(
|
315
|
-
mr=
|
315
|
+
mr=OpenBatcherMergeRequest(
|
316
316
|
raw=create_autospec(spec=ProjectMergeRequest),
|
317
317
|
channels={"chan1", "chan2"},
|
318
318
|
content_hashes={"hash1", "hash2"},
|
@@ -380,7 +380,7 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
380
380
|
),
|
381
381
|
],
|
382
382
|
[
|
383
|
-
|
383
|
+
OpenBatcherMergeRequest(
|
384
384
|
raw=create_autospec(spec=ProjectMergeRequest),
|
385
385
|
channels={"chan1"},
|
386
386
|
content_hashes={"hash1"},
|
@@ -424,14 +424,14 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
424
424
|
),
|
425
425
|
],
|
426
426
|
[
|
427
|
-
|
427
|
+
OpenBatcherMergeRequest(
|
428
428
|
raw=create_autospec(spec=ProjectMergeRequest),
|
429
429
|
channels={"chan1"},
|
430
430
|
content_hashes={"hash1"},
|
431
431
|
failed_mr_check=False,
|
432
432
|
is_batchable=False,
|
433
433
|
),
|
434
|
-
|
434
|
+
OpenBatcherMergeRequest(
|
435
435
|
raw=create_autospec(spec=ProjectMergeRequest),
|
436
436
|
channels={"chan2"},
|
437
437
|
content_hashes={"hash2"},
|
@@ -457,10 +457,10 @@ def _aggregate_channels(items: Sequence[Addition | Deletion]) -> set[str]:
|
|
457
457
|
)
|
458
458
|
def test_reconcile(
|
459
459
|
desired_promotions: list[Promotion],
|
460
|
-
open_mrs: list[
|
460
|
+
open_mrs: list[OpenBatcherMergeRequest],
|
461
461
|
expected_diff: Diff,
|
462
462
|
) -> None:
|
463
|
-
reconciler =
|
463
|
+
reconciler = Batcher()
|
464
464
|
diff = reconciler.reconcile(
|
465
465
|
desired_promotions=desired_promotions, open_mrs=open_mrs, batch_limit=5
|
466
466
|
)
|
@@ -1,15 +1,15 @@
|
|
1
1
|
from unittest.mock import create_autospec
|
2
2
|
|
3
3
|
from reconcile.saas_auto_promotions_manager.integration import SaasAutoPromotionsManager
|
4
|
+
from reconcile.saas_auto_promotions_manager.merge_request_manager.batcher import (
|
5
|
+
Batcher,
|
6
|
+
)
|
4
7
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.merge_request_manager_v2 import (
|
5
8
|
MergeRequestManagerV2,
|
6
9
|
)
|
7
10
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.mr_parser import (
|
8
11
|
MRParser,
|
9
12
|
)
|
10
|
-
from reconcile.saas_auto_promotions_manager.merge_request_manager.reconciler import (
|
11
|
-
Reconciler,
|
12
|
-
)
|
13
13
|
from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer import (
|
14
14
|
Renderer,
|
15
15
|
)
|
@@ -33,7 +33,7 @@ def test_integration_test():
|
|
33
33
|
vcs = create_autospec(spec=VCS)
|
34
34
|
merge_request_manager_v2 = MergeRequestManagerV2(
|
35
35
|
vcs=vcs,
|
36
|
-
reconciler=create_autospec(spec=
|
36
|
+
reconciler=create_autospec(spec=Batcher),
|
37
37
|
mr_parser=create_autospec(spec=MRParser),
|
38
38
|
renderer=create_autospec(spec=Renderer),
|
39
39
|
)
|
File without changes
|
File without changes
|
{qontract_reconcile-0.10.1rc766.dist-info → qontract_reconcile-0.10.1rc767.dist-info}/top_level.txt
RENAMED
File without changes
|