qontract-reconcile 0.10.2.dev215__py3-none-any.whl → 0.10.2.dev217__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.
@@ -243,7 +243,7 @@ def close_item(
243
243
  enable_closing: bool,
244
244
  item_type: str,
245
245
  item: ProjectIssue | ProjectMergeRequest,
246
- ):
246
+ ) -> None:
247
247
  if enable_closing:
248
248
  logging.info([
249
249
  "close_item",
@@ -263,32 +263,31 @@ def close_item(
263
263
 
264
264
 
265
265
  def handle_stale_items(
266
- dry_run,
267
- gl,
268
- days_interval,
269
- enable_closing,
270
- items,
271
- item_type,
272
- ):
266
+ dry_run: bool,
267
+ gl: GitLabApi,
268
+ days_interval: int,
269
+ enable_closing: bool,
270
+ items: Iterable[ProjectIssue | ProjectMergeRequest],
271
+ item_type: str,
272
+ ) -> None:
273
273
  LABEL = "stale"
274
274
 
275
275
  now = datetime.utcnow()
276
276
  for item in items:
277
- item_iid = item.attributes.get("iid")
278
277
  if AUTO_MERGE in item.labels:
279
278
  if item.merge_status == MRStatus.UNCHECKED:
280
279
  # this call triggers a status recheck
281
- item = gl.get_merge_request(item_iid)
280
+ item = gl.get_merge_request(item.iid)
282
281
  if item.merge_status == MRStatus.CANNOT_BE_MERGED:
283
282
  close_item(dry_run, gl, enable_closing, item_type, item)
284
- update_date = datetime.strptime(item.attributes.get("updated_at"), DATE_FORMAT)
283
+ update_date = datetime.strptime(item.updated_at, DATE_FORMAT)
285
284
 
286
285
  # if item is over days_interval
287
286
  current_interval = now.date() - update_date.date()
288
287
  if current_interval > timedelta(days=days_interval):
289
288
  # if item does not have 'stale' label - add it
290
289
  if LABEL not in item.labels:
291
- logging.info(["add_label", gl.project.name, item_type, item_iid, LABEL])
290
+ logging.info(["add_label", gl.project.name, item_type, item.iid, LABEL])
292
291
  if not dry_run:
293
292
  gl.add_label_with_note(item, LABEL)
294
293
  # if item has 'stale' label - close it
@@ -310,8 +309,7 @@ def handle_stale_items(
310
309
  continue
311
310
 
312
311
  cancel_notes_dates = [
313
- datetime.strptime(note.attributes.get("updated_at"), DATE_FORMAT)
314
- for note in cancel_notes
312
+ datetime.strptime(item.updated_at, DATE_FORMAT) for note in cancel_notes
315
313
  ]
316
314
  latest_cancel_note_date = max(d for d in cancel_notes_dates)
317
315
  # if the latest cancel note is under
@@ -322,20 +320,20 @@ def handle_stale_items(
322
320
  "remove_label",
323
321
  gl.project.name,
324
322
  item_type,
325
- item_iid,
323
+ item.iid,
326
324
  LABEL,
327
325
  ])
328
326
  if not dry_run:
329
327
  gl.remove_label(item, LABEL)
330
328
 
331
329
 
332
- def is_good_to_merge(labels):
330
+ def is_good_to_merge(labels: Iterable[str]) -> bool:
333
331
  return any(m in MERGE_LABELS_PRIORITY for m in labels) and not any(
334
332
  b in HOLD_LABELS for b in labels
335
333
  )
336
334
 
337
335
 
338
- def is_rebased(mr, gl: GitLabApi) -> bool:
336
+ def is_rebased(mr: ProjectMergeRequest, gl: GitLabApi) -> bool:
339
337
  target_branch = mr.target_branch
340
338
  head = cast(
341
339
  list[ProjectCommit],
@@ -471,14 +469,14 @@ def preprocess_merge_requests(
471
469
 
472
470
 
473
471
  def rebase_merge_requests(
474
- dry_run,
475
- gl,
476
- rebase_limit,
477
- pipeline_timeout=None,
478
- wait_for_pipeline=False,
479
- users_allowed_to_label=None,
480
- state=None,
481
- ):
472
+ dry_run: bool,
473
+ gl: GitLabApi,
474
+ rebase_limit: int,
475
+ state: State,
476
+ pipeline_timeout: int | None = None,
477
+ wait_for_pipeline: bool = False,
478
+ users_allowed_to_label: Iterable[str] | None = None,
479
+ ) -> None:
482
480
  rebases = 0
483
481
  merge_requests = [
484
482
  item["mr"]
@@ -542,20 +540,20 @@ def rebase_merge_requests(
542
540
 
543
541
  @retry(max_attempts=10, hook=_log_exception)
544
542
  def merge_merge_requests(
545
- dry_run,
543
+ dry_run: bool,
546
544
  gl: GitLabApi,
547
545
  project_merge_requests: list[ProjectMergeRequest],
548
546
  reload_toggle: ReloadToggle,
549
- merge_limit,
550
- rebase,
547
+ merge_limit: int,
548
+ rebase: bool,
551
549
  app_sre_usernames: Set[str],
552
- pipeline_timeout=None,
553
- insist=False,
554
- wait_for_pipeline=False,
555
- users_allowed_to_label=None,
556
- must_pass=None,
557
- state=None,
558
- ):
550
+ state: State,
551
+ pipeline_timeout: int | None = None,
552
+ insist: bool = False,
553
+ wait_for_pipeline: bool = False,
554
+ users_allowed_to_label: Iterable[str] | None = None,
555
+ must_pass: Iterable[str] | None = None,
556
+ ) -> None:
559
557
  merges = 0
560
558
  if reload_toggle.reload:
561
559
  project_merge_requests = gl.get_merge_requests(state=MRState.OPENED)
@@ -654,7 +652,7 @@ def publish_access_token_expiration_metrics(gl: GitLabApi) -> None:
654
652
  gitlab_token_expiration.remove(pat.name)
655
653
 
656
654
 
657
- def run(dry_run, wait_for_pipeline):
655
+ def run(dry_run: bool, wait_for_pipeline: bool) -> None:
658
656
  default_days_interval = 15
659
657
  default_limit = 8
660
658
  default_enable_closing = False
@@ -711,45 +709,46 @@ def run(dry_run, wait_for_pipeline):
711
709
  must_pass = hk.get("must_pass")
712
710
  try:
713
711
  merge_merge_requests(
714
- dry_run,
715
- gl,
716
- project_merge_requests,
717
- reload_toggle,
718
- limit,
719
- rebase,
720
- app_sre_usernames,
721
- pipeline_timeout,
712
+ dry_run=dry_run,
713
+ gl=gl,
714
+ project_merge_requests=project_merge_requests,
715
+ reload_toggle=reload_toggle,
716
+ merge_limit=limit,
717
+ rebase=rebase,
718
+ app_sre_usernames=app_sre_usernames,
719
+ state=state,
720
+ pipeline_timeout=pipeline_timeout,
722
721
  insist=True,
723
722
  wait_for_pipeline=wait_for_pipeline,
724
723
  users_allowed_to_label=users_allowed_to_label,
725
724
  must_pass=must_pass,
726
- state=state,
727
725
  )
728
726
  except Exception:
729
727
  logging.error(
730
728
  "All retries failed, trying to rerun merge_merge_requests() again."
731
729
  )
732
730
  merge_merge_requests(
733
- dry_run,
734
- gl,
735
- project_merge_requests,
736
- reload_toggle,
737
- limit,
738
- rebase,
739
- app_sre_usernames,
740
- pipeline_timeout,
731
+ dry_run=dry_run,
732
+ gl=gl,
733
+ project_merge_requests=project_merge_requests,
734
+ reload_toggle=reload_toggle,
735
+ merge_limit=limit,
736
+ rebase=rebase,
737
+ app_sre_usernames=app_sre_usernames,
738
+ state=state,
739
+ pipeline_timeout=pipeline_timeout,
740
+ insist=False,
741
741
  wait_for_pipeline=wait_for_pipeline,
742
742
  users_allowed_to_label=users_allowed_to_label,
743
743
  must_pass=must_pass,
744
- state=state,
745
744
  )
746
745
  if rebase:
747
746
  rebase_merge_requests(
748
- dry_run,
749
- gl,
750
- limit,
747
+ dry_run=dry_run,
748
+ gl=gl,
749
+ rebase_limit=limit,
750
+ state=state,
751
751
  pipeline_timeout=pipeline_timeout,
752
752
  wait_for_pipeline=wait_for_pipeline,
753
753
  users_allowed_to_label=users_allowed_to_label,
754
- state=state,
755
754
  )
@@ -1,10 +1,12 @@
1
1
  import itertools
2
2
  import logging
3
+ from collections.abc import Callable, Iterable
3
4
  from dataclasses import dataclass
4
5
  from typing import Any, cast
5
6
 
6
7
  from gitlab.exceptions import GitlabGetError
7
8
  from gitlab.v4.objects import (
9
+ GroupMember,
8
10
  Project,
9
11
  SharedProject,
10
12
  )
@@ -159,7 +161,9 @@ class GroupPermissionHandler:
159
161
  raise ExceptionGroup("Reconcile errors occurred", errors)
160
162
 
161
163
 
162
- def get_members_to_add(repo, gl, app_sre):
164
+ def get_members_to_add(
165
+ repo: str, gl: GitLabApi, app_sre: list[GroupMember]
166
+ ) -> list[dict[str, Any]]:
163
167
  maintainers = get_all_app_sre_maintainers(repo, gl, app_sre)
164
168
  if maintainers is None:
165
169
  return []
@@ -172,7 +176,9 @@ def get_members_to_add(repo, gl, app_sre):
172
176
  return members_to_add
173
177
 
174
178
 
175
- def get_all_app_sre_maintainers(repo, gl, app_sre):
179
+ def get_all_app_sre_maintainers(
180
+ repo: str, gl: GitLabApi, app_sre: list[GroupMember]
181
+ ) -> list[str]:
176
182
  app_sre_user_ids = [user.id for user in app_sre]
177
183
  chunks = batches.batched(app_sre_user_ids, PAGE_SIZE)
178
184
  app_sre_maintainers = (
@@ -182,12 +188,14 @@ def get_all_app_sre_maintainers(repo, gl, app_sre):
182
188
  return list(itertools.chain.from_iterable(app_sre_maintainers))
183
189
 
184
190
 
185
- def create_user_ids_query(ids):
191
+ def create_user_ids_query(ids: Iterable[str]) -> dict[str, str]:
186
192
  return {"user_ids": ",".join(str(id) for id in ids)}
187
193
 
188
194
 
189
195
  @defer
190
- def run(dry_run, thread_pool_size=10, defer=None):
196
+ def run(
197
+ dry_run: bool, thread_pool_size: int = 10, defer: Callable | None = None
198
+ ) -> None:
191
199
  instance = queries.get_gitlab_instance()
192
200
  settings = queries.get_app_interface_settings()
193
201
  gl = GitLabApi(instance, settings=settings)
@@ -221,7 +229,7 @@ def share_project_with_group_members(
221
229
  gl.add_project_member(m["repo"], m["user"])
222
230
 
223
231
 
224
- def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
232
+ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
225
233
  instance = queries.get_gitlab_instance()
226
234
  return {
227
235
  "instance": instance,
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import sys
3
+ from collections.abc import Callable
3
4
  from typing import Any
4
5
 
5
6
  from reconcile import queries
@@ -10,14 +11,15 @@ QONTRACT_INTEGRATION = "gitlab-projects"
10
11
 
11
12
 
12
13
  @defer
13
- def run(dry_run, defer=None):
14
+ def run(dry_run: bool, defer: Callable | None = None) -> None:
14
15
  instance = queries.get_gitlab_instance()
15
16
  settings = queries.get_app_interface_settings()
16
17
  code_components = queries.get_code_components()
17
18
  app_int_repos = [c["url"] for c in code_components]
18
19
  saas_bundle_repos = [c["url"] for c in code_components if c["resource"] == "bundle"]
19
20
  gl = GitLabApi(instance, settings=settings)
20
- defer(gl.cleanup)
21
+ if defer:
22
+ defer(gl.cleanup)
21
23
 
22
24
  project_requests = instance["projectRequests"] or []
23
25
  error = False
@@ -45,7 +47,7 @@ def run(dry_run, defer=None):
45
47
  sys.exit(error)
46
48
 
47
49
 
48
- def early_exit_desired_state(*args, **kwargs) -> dict[str, Any]:
50
+ def early_exit_desired_state(*args: Any, **kwargs: Any) -> dict[str, Any]:
49
51
  instance = queries.get_gitlab_instance()
50
52
  return {
51
53
  "instance": instance,
@@ -90,6 +90,20 @@ query AutomatedActionsInstances {
90
90
  max_age_minutes
91
91
  }
92
92
  }
93
+ ... on AutomatedActionExternalResourceFlushElastiCache_v1 {
94
+ external_resource_flush_elasticache_arguments: arguments {
95
+ namespace {
96
+ externalResources {
97
+ provisioner {
98
+ ... on AWSAccount_v1 {
99
+ name
100
+ }
101
+ }
102
+ }
103
+ }
104
+ identifier
105
+ }
106
+ }
93
107
  ... on AutomatedActionExternalResourceRdsReboot_v1 {
94
108
  external_resource_rds_reboot_arguments: arguments {
95
109
  namespace {
@@ -194,8 +208,33 @@ class AutomatedActionExternalResourceArgumentV1(ConfiguredBaseModel):
194
208
  identifier: str = Field(..., alias="identifier")
195
209
 
196
210
 
211
+ class AutomatedActionExternalResourceFlushElastiCacheV1(AutomatedActionV1):
212
+ external_resource_flush_elasticache_arguments: list[AutomatedActionExternalResourceArgumentV1] = Field(..., alias="external_resource_flush_elasticache_arguments")
213
+
214
+
215
+ class AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1_ExternalResourcesProvisionerV1(ConfiguredBaseModel):
216
+ ...
217
+
218
+
219
+ class AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1_ExternalResourcesProvisionerV1_AWSAccountV1(AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1_ExternalResourcesProvisionerV1):
220
+ name: str = Field(..., alias="name")
221
+
222
+
223
+ class AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1(ConfiguredBaseModel):
224
+ provisioner: Union[AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1_ExternalResourcesProvisionerV1_AWSAccountV1, AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1_ExternalResourcesProvisionerV1] = Field(..., alias="provisioner")
225
+
226
+
227
+ class AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1(ConfiguredBaseModel):
228
+ external_resources: Optional[list[AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1_NamespaceExternalResourceV1]] = Field(..., alias="externalResources")
229
+
230
+
231
+ class AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1(ConfiguredBaseModel):
232
+ namespace: AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1_NamespaceV1 = Field(..., alias="namespace")
233
+ identifier: str = Field(..., alias="identifier")
234
+
235
+
197
236
  class AutomatedActionExternalResourceRdsRebootV1(AutomatedActionV1):
198
- external_resource_rds_reboot_arguments: list[AutomatedActionExternalResourceArgumentV1] = Field(..., alias="external_resource_rds_reboot_arguments")
237
+ external_resource_rds_reboot_arguments: list[AutomatedActionExternalResourceRdsRebootV1_AutomatedActionExternalResourceArgumentV1] = Field(..., alias="external_resource_rds_reboot_arguments")
199
238
 
200
239
 
201
240
  class DisableClusterAutomationsV1(ConfiguredBaseModel):
@@ -226,7 +265,7 @@ class AutomatedActionOpenshiftWorkloadRestartV1(AutomatedActionV1):
226
265
  class AutomatedActionsInstanceV1(ConfiguredBaseModel):
227
266
  name: str = Field(..., alias="name")
228
267
  deployment: NamespaceV1 = Field(..., alias="deployment")
229
- actions: Optional[list[Union[AutomatedActionActionListV1, AutomatedActionExternalResourceRdsRebootV1, AutomatedActionOpenshiftWorkloadRestartV1, AutomatedActionV1]]] = Field(..., alias="actions")
268
+ actions: Optional[list[Union[AutomatedActionActionListV1, AutomatedActionExternalResourceFlushElastiCacheV1, AutomatedActionExternalResourceRdsRebootV1, AutomatedActionOpenshiftWorkloadRestartV1, AutomatedActionV1]]] = Field(..., alias="actions")
230
269
 
231
270
 
232
271
  class AutomatedActionsInstancesQueryData(ConfiguredBaseModel):
@@ -5737,6 +5737,11 @@
5737
5737
  "name": "AutomatedActionCreateToken_v1",
5738
5738
  "ofType": null
5739
5739
  },
5740
+ {
5741
+ "kind": "OBJECT",
5742
+ "name": "AutomatedActionExternalResourceFlushElastiCache_v1",
5743
+ "ofType": null
5744
+ },
5740
5745
  {
5741
5746
  "kind": "OBJECT",
5742
5747
  "name": "AutomatedActionExternalResourceRdsReboot_v1",
@@ -27344,6 +27349,11 @@
27344
27349
  "name": "AutomatedActionCreateToken_v1",
27345
27350
  "ofType": null
27346
27351
  },
27352
+ {
27353
+ "kind": "OBJECT",
27354
+ "name": "AutomatedActionExternalResourceFlushElastiCache_v1",
27355
+ "ofType": null
27356
+ },
27347
27357
  {
27348
27358
  "kind": "OBJECT",
27349
27359
  "name": "AutomatedActionExternalResourceRdsReboot_v1",
@@ -53512,7 +53522,7 @@
53512
53522
  },
53513
53523
  {
53514
53524
  "kind": "OBJECT",
53515
- "name": "AutomatedActionExternalResourceRdsReboot_v1",
53525
+ "name": "AutomatedActionExternalResourceFlushElastiCache_v1",
53516
53526
  "description": null,
53517
53527
  "fields": [
53518
53528
  {
@@ -53719,6 +53729,172 @@
53719
53729
  "enumValues": null,
53720
53730
  "possibleTypes": null
53721
53731
  },
53732
+ {
53733
+ "kind": "OBJECT",
53734
+ "name": "AutomatedActionExternalResourceRdsReboot_v1",
53735
+ "description": null,
53736
+ "fields": [
53737
+ {
53738
+ "name": "schema",
53739
+ "description": null,
53740
+ "args": [],
53741
+ "type": {
53742
+ "kind": "NON_NULL",
53743
+ "name": null,
53744
+ "ofType": {
53745
+ "kind": "SCALAR",
53746
+ "name": "String",
53747
+ "ofType": null
53748
+ }
53749
+ },
53750
+ "isDeprecated": false,
53751
+ "deprecationReason": null
53752
+ },
53753
+ {
53754
+ "name": "path",
53755
+ "description": null,
53756
+ "args": [],
53757
+ "type": {
53758
+ "kind": "NON_NULL",
53759
+ "name": null,
53760
+ "ofType": {
53761
+ "kind": "SCALAR",
53762
+ "name": "String",
53763
+ "ofType": null
53764
+ }
53765
+ },
53766
+ "isDeprecated": false,
53767
+ "deprecationReason": null
53768
+ },
53769
+ {
53770
+ "name": "type",
53771
+ "description": null,
53772
+ "args": [],
53773
+ "type": {
53774
+ "kind": "NON_NULL",
53775
+ "name": null,
53776
+ "ofType": {
53777
+ "kind": "SCALAR",
53778
+ "name": "String",
53779
+ "ofType": null
53780
+ }
53781
+ },
53782
+ "isDeprecated": false,
53783
+ "deprecationReason": null
53784
+ },
53785
+ {
53786
+ "name": "description",
53787
+ "description": null,
53788
+ "args": [],
53789
+ "type": {
53790
+ "kind": "SCALAR",
53791
+ "name": "String",
53792
+ "ofType": null
53793
+ },
53794
+ "isDeprecated": false,
53795
+ "deprecationReason": null
53796
+ },
53797
+ {
53798
+ "name": "maxOps",
53799
+ "description": null,
53800
+ "args": [],
53801
+ "type": {
53802
+ "kind": "NON_NULL",
53803
+ "name": null,
53804
+ "ofType": {
53805
+ "kind": "SCALAR",
53806
+ "name": "Int",
53807
+ "ofType": null
53808
+ }
53809
+ },
53810
+ "isDeprecated": false,
53811
+ "deprecationReason": null
53812
+ },
53813
+ {
53814
+ "name": "instances",
53815
+ "description": null,
53816
+ "args": [],
53817
+ "type": {
53818
+ "kind": "NON_NULL",
53819
+ "name": null,
53820
+ "ofType": {
53821
+ "kind": "LIST",
53822
+ "name": null,
53823
+ "ofType": {
53824
+ "kind": "NON_NULL",
53825
+ "name": null,
53826
+ "ofType": {
53827
+ "kind": "OBJECT",
53828
+ "name": "AutomatedActionsInstance_v1",
53829
+ "ofType": null
53830
+ }
53831
+ }
53832
+ }
53833
+ },
53834
+ "isDeprecated": false,
53835
+ "deprecationReason": null
53836
+ },
53837
+ {
53838
+ "name": "permissions",
53839
+ "description": null,
53840
+ "args": [],
53841
+ "type": {
53842
+ "kind": "LIST",
53843
+ "name": null,
53844
+ "ofType": {
53845
+ "kind": "NON_NULL",
53846
+ "name": null,
53847
+ "ofType": {
53848
+ "kind": "OBJECT",
53849
+ "name": "PermissionAutomatedActions_v1",
53850
+ "ofType": null
53851
+ }
53852
+ }
53853
+ },
53854
+ "isDeprecated": false,
53855
+ "deprecationReason": null
53856
+ },
53857
+ {
53858
+ "name": "arguments",
53859
+ "description": null,
53860
+ "args": [],
53861
+ "type": {
53862
+ "kind": "NON_NULL",
53863
+ "name": null,
53864
+ "ofType": {
53865
+ "kind": "LIST",
53866
+ "name": null,
53867
+ "ofType": {
53868
+ "kind": "NON_NULL",
53869
+ "name": null,
53870
+ "ofType": {
53871
+ "kind": "OBJECT",
53872
+ "name": "AutomatedActionExternalResourceArgument_v1",
53873
+ "ofType": null
53874
+ }
53875
+ }
53876
+ }
53877
+ },
53878
+ "isDeprecated": false,
53879
+ "deprecationReason": null
53880
+ }
53881
+ ],
53882
+ "inputFields": null,
53883
+ "interfaces": [
53884
+ {
53885
+ "kind": "INTERFACE",
53886
+ "name": "AutomatedAction_v1",
53887
+ "ofType": null
53888
+ },
53889
+ {
53890
+ "kind": "INTERFACE",
53891
+ "name": "DatafileObject_v1",
53892
+ "ofType": null
53893
+ }
53894
+ ],
53895
+ "enumValues": null,
53896
+ "possibleTypes": null
53897
+ },
53722
53898
  {
53723
53899
  "kind": "OBJECT",
53724
53900
  "name": "AutomatedActionNoOp_v1",