infrahub-server 1.1.7__py3-none-any.whl → 1.2.0b1__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.
Files changed (399) hide show
  1. infrahub/api/artifact.py +16 -4
  2. infrahub/api/dependencies.py +8 -0
  3. infrahub/api/oauth2.py +0 -1
  4. infrahub/api/oidc.py +0 -1
  5. infrahub/api/query.py +18 -7
  6. infrahub/api/schema.py +32 -6
  7. infrahub/api/transformation.py +12 -5
  8. infrahub/{message_bus/messages/check_artifact_create.py → artifacts/models.py} +5 -3
  9. infrahub/{message_bus/operations/check/artifact.py → artifacts/tasks.py} +26 -25
  10. infrahub/cli/__init__.py +0 -2
  11. infrahub/cli/db.py +6 -7
  12. infrahub/cli/events.py +8 -3
  13. infrahub/cli/git_agent.py +9 -7
  14. infrahub/cli/tasks.py +4 -6
  15. infrahub/computed_attribute/models.py +1 -1
  16. infrahub/computed_attribute/tasks.py +64 -17
  17. infrahub/computed_attribute/triggers.py +90 -0
  18. infrahub/config.py +1 -1
  19. infrahub/context.py +39 -0
  20. infrahub/core/account.py +5 -8
  21. infrahub/core/attribute.py +50 -21
  22. infrahub/core/branch/models.py +4 -4
  23. infrahub/core/branch/tasks.py +130 -125
  24. infrahub/core/changelog/__init__.py +0 -0
  25. infrahub/core/changelog/diff.py +283 -0
  26. infrahub/core/changelog/models.py +499 -0
  27. infrahub/core/constants/__init__.py +43 -2
  28. infrahub/core/constants/infrahubkind.py +1 -0
  29. infrahub/core/constants/schema.py +2 -0
  30. infrahub/core/diff/combiner.py +1 -1
  31. infrahub/core/diff/enricher/cardinality_one.py +6 -1
  32. infrahub/core/diff/enricher/hierarchy.py +22 -7
  33. infrahub/core/diff/enricher/labels.py +6 -1
  34. infrahub/core/diff/enricher/path_identifier.py +5 -1
  35. infrahub/core/diff/enricher/summary_counts.py +107 -0
  36. infrahub/core/diff/merger/merger.py +3 -1
  37. infrahub/core/diff/model/path.py +34 -11
  38. infrahub/core/diff/parent_node_adder.py +78 -0
  39. infrahub/core/diff/payload_builder.py +13 -2
  40. infrahub/core/diff/query/all_conflicts.py +1 -1
  41. infrahub/core/diff/query/artifact.py +1 -1
  42. infrahub/core/diff/query/delete_query.py +1 -1
  43. infrahub/core/diff/query/diff_get.py +1 -1
  44. infrahub/core/diff/query/diff_summary.py +1 -1
  45. infrahub/core/diff/query/field_specifiers.py +1 -1
  46. infrahub/core/diff/query/field_summary.py +1 -1
  47. infrahub/core/diff/query/filters.py +2 -2
  48. infrahub/core/diff/query/get_conflict_query.py +1 -1
  49. infrahub/core/diff/query/has_conflicts_query.py +1 -1
  50. infrahub/core/diff/query/merge.py +3 -3
  51. infrahub/core/diff/query/merge_tracking_id.py +1 -1
  52. infrahub/core/diff/query/roots_metadata.py +1 -1
  53. infrahub/core/diff/query/save.py +191 -185
  54. infrahub/core/diff/query/summary_counts_enricher.py +52 -5
  55. infrahub/core/diff/query/time_range_query.py +1 -1
  56. infrahub/core/diff/query/update_conflict_query.py +1 -1
  57. infrahub/core/diff/repository/deserializer.py +9 -4
  58. infrahub/core/diff/repository/repository.py +156 -38
  59. infrahub/core/diff/tasks.py +13 -12
  60. infrahub/core/enums.py +1 -1
  61. infrahub/core/graph/__init__.py +1 -1
  62. infrahub/core/graph/index.py +3 -0
  63. infrahub/core/integrity/object_conflict/conflict_recorder.py +1 -1
  64. infrahub/core/ipam/reconciler.py +1 -1
  65. infrahub/core/ipam/tasks.py +2 -3
  66. infrahub/core/manager.py +20 -15
  67. infrahub/core/merge.py +5 -2
  68. infrahub/core/migrations/graph/__init__.py +4 -0
  69. infrahub/core/migrations/graph/m001_add_version_to_graph.py +1 -1
  70. infrahub/core/migrations/graph/m002_attribute_is_default.py +2 -2
  71. infrahub/core/migrations/graph/m003_relationship_parent_optional.py +2 -2
  72. infrahub/core/migrations/graph/m004_add_attr_documentation.py +1 -1
  73. infrahub/core/migrations/graph/m005_add_rel_read_only.py +1 -1
  74. infrahub/core/migrations/graph/m006_add_rel_on_delete.py +1 -1
  75. infrahub/core/migrations/graph/m007_add_rel_allow_override.py +1 -1
  76. infrahub/core/migrations/graph/m008_add_human_friendly_id.py +1 -1
  77. infrahub/core/migrations/graph/m009_add_generate_profile_attr.py +1 -1
  78. infrahub/core/migrations/graph/m010_add_generate_profile_attr_generic.py +1 -1
  79. infrahub/core/migrations/graph/m011_remove_profile_relationship_schema.py +2 -2
  80. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -23
  81. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -11
  82. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +2 -2
  83. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  84. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  85. infrahub/core/migrations/graph/m017_add_core_profile.py +1 -1
  86. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +2 -2
  87. infrahub/core/migrations/graph/m019_restore_rels_to_time.py +256 -0
  88. infrahub/core/migrations/graph/m020_add_generate_template_attr.py +48 -0
  89. infrahub/core/migrations/query/attribute_add.py +1 -1
  90. infrahub/core/migrations/query/attribute_rename.py +1 -1
  91. infrahub/core/migrations/query/delete_element_in_schema.py +1 -1
  92. infrahub/core/migrations/query/node_duplicate.py +39 -19
  93. infrahub/core/migrations/query/relationship_duplicate.py +1 -1
  94. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  95. infrahub/core/migrations/schema/node_attribute_remove.py +1 -1
  96. infrahub/core/migrations/schema/node_remove.py +27 -13
  97. infrahub/core/migrations/schema/tasks.py +5 -5
  98. infrahub/core/migrations/shared.py +4 -4
  99. infrahub/core/models.py +7 -8
  100. infrahub/core/node/__init__.py +164 -45
  101. infrahub/core/node/base.py +1 -1
  102. infrahub/core/node/delete_validator.py +4 -4
  103. infrahub/core/node/ipam.py +7 -7
  104. infrahub/core/node/resource_manager/ip_prefix_pool.py +8 -5
  105. infrahub/core/node/standard.py +3 -5
  106. infrahub/core/property.py +1 -1
  107. infrahub/core/protocols.py +6 -0
  108. infrahub/core/protocols_base.py +4 -2
  109. infrahub/core/query/__init__.py +2 -5
  110. infrahub/core/query/attribute.py +9 -9
  111. infrahub/core/query/branch.py +5 -5
  112. infrahub/core/query/delete.py +1 -1
  113. infrahub/core/query/diff.py +4 -4
  114. infrahub/core/query/ipam.py +4 -4
  115. infrahub/core/query/node.py +11 -12
  116. infrahub/core/query/relationship.py +211 -25
  117. infrahub/core/query/resource_manager.py +10 -10
  118. infrahub/core/query/standard_node.py +6 -6
  119. infrahub/core/query/task.py +3 -3
  120. infrahub/core/query/task_log.py +1 -1
  121. infrahub/core/query/utils.py +5 -5
  122. infrahub/core/registry.py +0 -2
  123. infrahub/core/relationship/constraints/count.py +1 -1
  124. infrahub/core/relationship/constraints/peer_kind.py +1 -1
  125. infrahub/core/relationship/model.py +76 -38
  126. infrahub/core/schema/__init__.py +6 -4
  127. infrahub/core/schema/attribute_schema.py +8 -0
  128. infrahub/core/schema/basenode_schema.py +13 -3
  129. infrahub/core/schema/definitions/core/__init__.py +153 -0
  130. infrahub/core/schema/definitions/core/account.py +168 -0
  131. infrahub/core/schema/definitions/core/artifact.py +127 -0
  132. infrahub/core/schema/definitions/core/builtin.py +21 -0
  133. infrahub/core/schema/definitions/core/check.py +60 -0
  134. infrahub/core/schema/definitions/core/generator.py +96 -0
  135. infrahub/core/schema/definitions/core/graphql_query.py +77 -0
  136. infrahub/core/schema/definitions/core/group.py +105 -0
  137. infrahub/core/schema/definitions/core/ipam.py +252 -0
  138. infrahub/core/schema/definitions/core/lineage.py +17 -0
  139. infrahub/core/schema/definitions/core/menu.py +46 -0
  140. infrahub/core/schema/definitions/core/permission.py +161 -0
  141. infrahub/core/schema/definitions/core/profile.py +29 -0
  142. infrahub/core/schema/definitions/core/propose_change.py +88 -0
  143. infrahub/core/schema/definitions/core/propose_change_comment.py +188 -0
  144. infrahub/core/schema/definitions/core/propose_change_validator.py +326 -0
  145. infrahub/core/schema/definitions/core/repository.py +280 -0
  146. infrahub/core/schema/definitions/core/resource_pool.py +180 -0
  147. infrahub/core/schema/definitions/core/template.py +12 -0
  148. infrahub/core/schema/definitions/core/transform.py +87 -0
  149. infrahub/core/schema/definitions/core/webhook.py +108 -0
  150. infrahub/core/schema/definitions/internal.py +16 -0
  151. infrahub/core/schema/generated/genericnode_schema.py +5 -0
  152. infrahub/core/schema/generated/node_schema.py +5 -0
  153. infrahub/core/schema/generic_schema.py +5 -1
  154. infrahub/core/schema/manager.py +45 -42
  155. infrahub/core/schema/node_schema.py +4 -0
  156. infrahub/core/schema/profile_schema.py +4 -0
  157. infrahub/core/schema/relationship_schema.py +10 -2
  158. infrahub/core/schema/schema_branch.py +260 -16
  159. infrahub/core/schema/template_schema.py +36 -0
  160. infrahub/core/task/user_task.py +7 -5
  161. infrahub/core/timestamp.py +3 -3
  162. infrahub/core/utils.py +2 -2
  163. infrahub/core/validators/attribute/choices.py +1 -1
  164. infrahub/core/validators/attribute/enum.py +1 -1
  165. infrahub/core/validators/attribute/kind.py +1 -1
  166. infrahub/core/validators/attribute/length.py +1 -1
  167. infrahub/core/validators/attribute/optional.py +1 -1
  168. infrahub/core/validators/attribute/regex.py +1 -1
  169. infrahub/core/validators/attribute/unique.py +1 -1
  170. infrahub/core/validators/checks_runner.py +37 -0
  171. infrahub/core/validators/node/generate_profile.py +1 -1
  172. infrahub/core/validators/node/hierarchy.py +1 -1
  173. infrahub/core/validators/query.py +1 -1
  174. infrahub/core/validators/relationship/count.py +1 -1
  175. infrahub/core/validators/relationship/optional.py +1 -1
  176. infrahub/core/validators/relationship/peer.py +1 -1
  177. infrahub/core/validators/tasks.py +8 -6
  178. infrahub/core/validators/uniqueness/query.py +1 -1
  179. infrahub/database/__init__.py +3 -2
  180. infrahub/database/memgraph.py +1 -1
  181. infrahub/dependencies/builder/diff/combiner.py +1 -1
  182. infrahub/dependencies/builder/diff/conflicts_enricher.py +1 -1
  183. infrahub/dependencies/builder/diff/deserializer.py +4 -2
  184. infrahub/dependencies/builder/diff/enricher/hierarchy.py +3 -1
  185. infrahub/dependencies/builder/diff/enricher/summary_counts.py +8 -0
  186. infrahub/dependencies/builder/diff/parent_node_adder.py +8 -0
  187. infrahub/events/artifact_action.py +76 -0
  188. infrahub/events/branch_action.py +50 -21
  189. infrahub/events/group_action.py +117 -0
  190. infrahub/events/models.py +164 -51
  191. infrahub/events/node_action.py +70 -8
  192. infrahub/events/repository_action.py +8 -8
  193. infrahub/events/schema_action.py +21 -8
  194. infrahub/exceptions.py +9 -0
  195. infrahub/generators/models.py +1 -0
  196. infrahub/generators/tasks.py +34 -15
  197. infrahub/git/base.py +3 -5
  198. infrahub/git/constants.py +0 -1
  199. infrahub/git/integrator.py +60 -36
  200. infrahub/git/models.py +80 -1
  201. infrahub/git/repository.py +7 -8
  202. infrahub/git/tasks.py +432 -112
  203. infrahub/git_credential/helper.py +2 -3
  204. infrahub/graphql/analyzer.py +572 -11
  205. infrahub/graphql/app.py +34 -26
  206. infrahub/graphql/auth/query_permission_checker/anonymous_checker.py +5 -5
  207. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +4 -4
  208. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +4 -4
  209. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +28 -35
  210. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -5
  211. infrahub/graphql/context.py +33 -0
  212. infrahub/graphql/enums.py +1 -1
  213. infrahub/graphql/initialization.py +5 -1
  214. infrahub/graphql/loaders/node.py +2 -2
  215. infrahub/graphql/manager.py +63 -63
  216. infrahub/graphql/mutations/account.py +20 -13
  217. infrahub/graphql/mutations/artifact_definition.py +16 -12
  218. infrahub/graphql/mutations/branch.py +86 -40
  219. infrahub/graphql/mutations/computed_attribute.py +24 -15
  220. infrahub/graphql/mutations/diff.py +33 -17
  221. infrahub/graphql/mutations/diff_conflict.py +14 -8
  222. infrahub/graphql/mutations/generator.py +83 -0
  223. infrahub/graphql/mutations/graphql_query.py +19 -11
  224. infrahub/graphql/mutations/ipam.py +25 -23
  225. infrahub/graphql/mutations/main.py +233 -45
  226. infrahub/graphql/mutations/menu.py +10 -10
  227. infrahub/graphql/mutations/proposed_change.py +36 -28
  228. infrahub/graphql/mutations/relationship.py +341 -130
  229. infrahub/graphql/mutations/repository.py +41 -35
  230. infrahub/graphql/mutations/resource_manager.py +26 -26
  231. infrahub/graphql/mutations/schema.py +66 -33
  232. infrahub/graphql/mutations/tasks.py +10 -7
  233. infrahub/graphql/parser.py +1 -1
  234. infrahub/graphql/permissions.py +3 -10
  235. infrahub/graphql/queries/account.py +22 -18
  236. infrahub/graphql/queries/branch.py +6 -4
  237. infrahub/graphql/queries/diff/tree.py +63 -52
  238. infrahub/graphql/queries/event.py +115 -0
  239. infrahub/graphql/queries/internal.py +3 -3
  240. infrahub/graphql/queries/ipam.py +23 -18
  241. infrahub/graphql/queries/relationship.py +11 -10
  242. infrahub/graphql/queries/resource_manager.py +37 -25
  243. infrahub/graphql/queries/search.py +9 -8
  244. infrahub/graphql/queries/status.py +12 -9
  245. infrahub/graphql/queries/task.py +11 -9
  246. infrahub/graphql/resolvers/resolver.py +69 -43
  247. infrahub/graphql/resolvers/single_relationship.py +16 -10
  248. infrahub/graphql/schema.py +4 -0
  249. infrahub/graphql/subscription/__init__.py +1 -1
  250. infrahub/graphql/subscription/events.py +1 -1
  251. infrahub/graphql/subscription/graphql_query.py +8 -8
  252. infrahub/graphql/types/branch.py +2 -2
  253. infrahub/graphql/types/common.py +6 -1
  254. infrahub/graphql/types/context.py +12 -0
  255. infrahub/graphql/types/enums.py +2 -0
  256. infrahub/graphql/types/event.py +158 -0
  257. infrahub/graphql/types/interface.py +2 -2
  258. infrahub/graphql/types/node.py +3 -3
  259. infrahub/graphql/types/permission.py +2 -2
  260. infrahub/graphql/types/relationship.py +3 -3
  261. infrahub/graphql/types/standard_node.py +9 -11
  262. infrahub/graphql/utils.py +28 -182
  263. infrahub/groups/tasks.py +2 -3
  264. infrahub/lock.py +21 -21
  265. infrahub/menu/generator.py +0 -1
  266. infrahub/menu/menu.py +116 -138
  267. infrahub/menu/models.py +4 -4
  268. infrahub/message_bus/__init__.py +11 -13
  269. infrahub/message_bus/messages/__init__.py +0 -14
  270. infrahub/message_bus/messages/check_generator_run.py +1 -3
  271. infrahub/message_bus/messages/event_branch_merge.py +3 -0
  272. infrahub/message_bus/messages/proposed_change/request_proposedchange_refreshartifacts.py +6 -0
  273. infrahub/message_bus/messages/request_proposedchange_pipeline.py +2 -0
  274. infrahub/message_bus/messages/send_echo_request.py +1 -1
  275. infrahub/message_bus/operations/__init__.py +4 -13
  276. infrahub/message_bus/operations/check/__init__.py +2 -2
  277. infrahub/message_bus/operations/check/generator.py +1 -3
  278. infrahub/message_bus/operations/event/branch.py +7 -3
  279. infrahub/message_bus/operations/event/schema.py +1 -1
  280. infrahub/message_bus/operations/event/worker.py +0 -3
  281. infrahub/message_bus/operations/finalize/validator.py +1 -1
  282. infrahub/message_bus/operations/git/file.py +2 -2
  283. infrahub/message_bus/operations/git/repository.py +1 -1
  284. infrahub/message_bus/operations/requests/__init__.py +0 -4
  285. infrahub/message_bus/operations/requests/generator_definition.py +2 -4
  286. infrahub/message_bus/operations/requests/proposed_change.py +37 -20
  287. infrahub/message_bus/operations/send/echo.py +1 -1
  288. infrahub/message_bus/types.py +1 -1
  289. infrahub/permissions/globals.py +15 -0
  290. infrahub/pools/prefix.py +29 -165
  291. infrahub/prefect_server/__init__.py +0 -0
  292. infrahub/prefect_server/app.py +18 -0
  293. infrahub/prefect_server/database.py +20 -0
  294. infrahub/prefect_server/events.py +28 -0
  295. infrahub/prefect_server/models.py +46 -0
  296. infrahub/proposed_change/models.py +18 -1
  297. infrahub/proposed_change/tasks.py +195 -53
  298. infrahub/pytest_plugin.py +4 -4
  299. infrahub/server.py +13 -12
  300. infrahub/services/__init__.py +148 -63
  301. infrahub/services/adapters/cache/__init__.py +11 -11
  302. infrahub/services/adapters/cache/nats.py +42 -25
  303. infrahub/services/adapters/cache/redis.py +3 -11
  304. infrahub/services/adapters/event/__init__.py +10 -18
  305. infrahub/services/adapters/http/__init__.py +0 -5
  306. infrahub/services/adapters/http/httpx.py +22 -15
  307. infrahub/services/adapters/message_bus/__init__.py +25 -8
  308. infrahub/services/adapters/message_bus/local.py +9 -7
  309. infrahub/services/adapters/message_bus/nats.py +14 -8
  310. infrahub/services/adapters/message_bus/rabbitmq.py +23 -10
  311. infrahub/services/adapters/workflow/__init__.py +11 -8
  312. infrahub/services/adapters/workflow/local.py +27 -6
  313. infrahub/services/adapters/workflow/worker.py +23 -7
  314. infrahub/services/component.py +43 -40
  315. infrahub/services/protocols.py +7 -7
  316. infrahub/services/scheduler.py +30 -29
  317. infrahub/storage.py +2 -4
  318. infrahub/task_manager/constants.py +1 -1
  319. infrahub/task_manager/event.py +261 -0
  320. infrahub/task_manager/models.py +147 -3
  321. infrahub/task_manager/task.py +1 -1
  322. infrahub/tasks/artifact.py +19 -18
  323. infrahub/tasks/registry.py +1 -1
  324. infrahub/tasks/telemetry.py +13 -14
  325. infrahub/transformations/tasks.py +3 -5
  326. infrahub/trigger/__init__.py +0 -0
  327. infrahub/trigger/catalogue.py +16 -0
  328. infrahub/trigger/constants.py +9 -0
  329. infrahub/trigger/models.py +105 -0
  330. infrahub/trigger/tasks.py +91 -0
  331. infrahub/types.py +1 -1
  332. infrahub/utils.py +1 -1
  333. infrahub/webhook/constants.py +0 -2
  334. infrahub/webhook/models.py +161 -40
  335. infrahub/webhook/tasks.py +123 -202
  336. infrahub/webhook/triggers.py +27 -0
  337. infrahub/workers/infrahub_async.py +36 -25
  338. infrahub/workers/utils.py +63 -0
  339. infrahub/workflows/catalogue.py +71 -52
  340. infrahub/workflows/initialization.py +14 -8
  341. infrahub/workflows/models.py +28 -4
  342. infrahub/workflows/utils.py +1 -1
  343. infrahub_sdk/batch.py +2 -2
  344. infrahub_sdk/client.py +8 -0
  345. infrahub_sdk/config.py +1 -1
  346. infrahub_sdk/ctl/branch.py +3 -2
  347. infrahub_sdk/ctl/check.py +4 -4
  348. infrahub_sdk/ctl/cli_commands.py +16 -11
  349. infrahub_sdk/ctl/exceptions.py +0 -6
  350. infrahub_sdk/ctl/exporter.py +1 -1
  351. infrahub_sdk/ctl/generator.py +5 -5
  352. infrahub_sdk/ctl/importer.py +3 -2
  353. infrahub_sdk/ctl/menu.py +1 -1
  354. infrahub_sdk/ctl/object.py +1 -1
  355. infrahub_sdk/ctl/repository.py +23 -15
  356. infrahub_sdk/ctl/schema.py +2 -2
  357. infrahub_sdk/ctl/utils.py +6 -21
  358. infrahub_sdk/ctl/validate.py +2 -1
  359. infrahub_sdk/data.py +1 -1
  360. infrahub_sdk/exceptions.py +12 -0
  361. infrahub_sdk/generator.py +3 -0
  362. infrahub_sdk/node.py +5 -8
  363. infrahub_sdk/protocols.py +20 -8
  364. infrahub_sdk/schema/__init__.py +14 -5
  365. infrahub_sdk/schema/main.py +7 -0
  366. infrahub_sdk/task/__init__.py +1 -0
  367. infrahub_sdk/task/constants.py +3 -0
  368. infrahub_sdk/task/exceptions.py +25 -0
  369. infrahub_sdk/task/manager.py +545 -0
  370. infrahub_sdk/task/models.py +74 -0
  371. infrahub_sdk/testing/docker.py +30 -0
  372. infrahub_sdk/timestamp.py +134 -33
  373. infrahub_sdk/transfer/exporter/json.py +1 -1
  374. infrahub_sdk/utils.py +39 -1
  375. infrahub_sdk/yaml.py +2 -3
  376. {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/METADATA +7 -6
  377. {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/RECORD +383 -339
  378. infrahub_testcontainers/container.py +2 -3
  379. infrahub_testcontainers/docker-compose.test.yml +2 -2
  380. infrahub/core/branch/constants.py +0 -2
  381. infrahub/core/schema/definitions/core.py +0 -2274
  382. infrahub/graphql/query.py +0 -52
  383. infrahub/message_bus/messages/check_repository_checkdefinition.py +0 -20
  384. infrahub/message_bus/messages/check_repository_mergeconflicts.py +0 -16
  385. infrahub/message_bus/messages/check_repository_usercheck.py +0 -26
  386. infrahub/message_bus/messages/request_artifactdefinition_check.py +0 -17
  387. infrahub/message_bus/messages/request_repository_checks.py +0 -12
  388. infrahub/message_bus/messages/request_repository_userchecks.py +0 -18
  389. infrahub/message_bus/operations/check/repository.py +0 -293
  390. infrahub/message_bus/operations/requests/artifact_definition.py +0 -148
  391. infrahub/message_bus/operations/requests/repository.py +0 -133
  392. infrahub/schema/constants.py +0 -1
  393. infrahub/schema/tasks.py +0 -76
  394. infrahub/services/adapters/database/__init__.py +0 -9
  395. infrahub_sdk/ctl/_file.py +0 -13
  396. /infrahub/{schema → artifacts}/__init__.py +0 -0
  397. {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/LICENSE.txt +0 -0
  398. {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/WHEEL +0 -0
  399. {infrahub_server-1.1.7.dist-info → infrahub_server-1.2.0b1.dist-info}/entry_points.txt +0 -0
@@ -7,13 +7,14 @@ from typing import TYPE_CHECKING, Any, Optional, Union
7
7
 
8
8
  import netaddr
9
9
  import ujson
10
- from infrahub_sdk.timestamp import TimestampFormatError
10
+ from infrahub_sdk.exceptions import TimestampFormatError
11
11
  from infrahub_sdk.utils import is_valid_url
12
12
  from infrahub_sdk.uuidt import UUIDT
13
13
  from pydantic import BaseModel, Field
14
14
 
15
15
  from infrahub import config
16
16
  from infrahub.core import registry
17
+ from infrahub.core.changelog.models import AttributeChangelog
17
18
  from infrahub.core.constants import NULL_VALUE, AttributeDBNodeType, BranchSupportType, RelationshipStatus
18
19
  from infrahub.core.property import FlagPropertyMixin, NodePropertyData, NodePropertyMixin
19
20
  from infrahub.core.query.attribute import (
@@ -37,8 +38,6 @@ if TYPE_CHECKING:
37
38
  from infrahub.core.schema import AttributeSchema
38
39
  from infrahub.database import InfrahubDatabase
39
40
 
40
- # pylint: disable=redefined-builtin,c-extension-no-member,too-many-lines,too-many-public-methods
41
-
42
41
 
43
42
  # Use a more user-friendly threshold than Neo4j one (8167 bytes).
44
43
  MAX_STRING_LENGTH = 4096
@@ -81,7 +80,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
81
80
  _rel_to_node_label: str = RELATIONSHIP_TO_NODE_LABEL
82
81
  _rel_to_value_label: str = RELATIONSHIP_TO_VALUE_LABEL
83
82
 
84
- def __init__( # pylint: disable=too-many-branches
83
+ def __init__(
85
84
  self,
86
85
  name: str,
87
86
  schema: AttributeSchema,
@@ -218,7 +217,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
218
217
  value_to_check = value
219
218
  if schema.enum and isinstance(value, Enum):
220
219
  value_to_check = value.value
221
- if not isinstance(value_to_check, cls.type): # pylint: disable=isinstance-second-argument-not-valid-type
220
+ if not isinstance(value_to_check, cls.type):
222
221
  raise ValidationError({name: f"{value} is not a valid {schema.kind}"})
223
222
 
224
223
  @classmethod
@@ -267,7 +266,7 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
267
266
  @classmethod
268
267
  def deserialize_from_string(cls, value_as_string: str) -> Any:
269
268
  """Return a value corresponding to the attribute type given it formatted as a string."""
270
- return cls.type(value_as_string) # pylint: disable=not-callable
269
+ return cls.type(value_as_string)
271
270
 
272
271
  def to_db(self) -> dict[str, Any]:
273
272
  """Return the properties of the AttributeValue node in Dict format."""
@@ -318,19 +317,19 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
318
317
  """Deserialize the value coming from the database."""
319
318
  return data.value
320
319
 
321
- async def save(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> bool:
320
+ async def save(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> AttributeChangelog | None:
322
321
  """Create or Update the Attribute in the database."""
323
322
 
324
323
  save_at = Timestamp(at)
325
324
 
326
325
  if not self.id or self.is_from_profile:
327
- return False
326
+ return None
328
327
 
329
328
  return await self._update(at=save_at, db=db)
330
329
 
331
- async def delete(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> bool:
330
+ async def delete(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> AttributeChangelog | None:
332
331
  if not self.db_id:
333
- return False
332
+ return None
334
333
 
335
334
  delete_at = Timestamp(at)
336
335
 
@@ -339,7 +338,14 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
339
338
  results = query.get_results()
340
339
 
341
340
  if not results:
342
- return False
341
+ return None
342
+
343
+ changelog = AttributeChangelog(
344
+ name=self.name,
345
+ value=None,
346
+ value_previous=None,
347
+ kind=self.schema.kind,
348
+ )
343
349
 
344
350
  properties_to_delete = []
345
351
  branch = self.get_branch_based_on_support_type()
@@ -347,6 +353,8 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
347
353
  # Check all the relationship and update the one that are in the same branch
348
354
  rel_ids_to_update = set()
349
355
  for result in results:
356
+ if result.get_rel("r2").type == "HAS_VALUE":
357
+ changelog.value_previous = result.get_node("ap").get("value")
350
358
  properties_to_delete.append((result.get_rel("r2").type, result.get_node("ap").element_id))
351
359
 
352
360
  await add_relationship(
@@ -378,9 +386,9 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
378
386
  db=db,
379
387
  )
380
388
 
381
- return True
389
+ return changelog
382
390
 
383
- async def _update(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> bool:
391
+ async def _update(self, db: InfrahubDatabase, at: Optional[Timestamp] = None) -> AttributeChangelog | None:
384
392
  """Update the attribute in the database.
385
393
 
386
394
  Get the current value
@@ -420,6 +428,13 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
420
428
 
421
429
  branch = self.get_branch_based_on_support_type()
422
430
 
431
+ changelog = AttributeChangelog(
432
+ name=self.name,
433
+ value=self.to_db().get("value"),
434
+ value_previous=current_attr_data.value,
435
+ kind=self.schema.kind,
436
+ )
437
+
423
438
  # ---------- Update the Value ----------
424
439
  if current_attr_data.content != self.to_db():
425
440
  # Create the new AttributeValue and update the existing relationship
@@ -439,6 +454,11 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
439
454
 
440
455
  for flag_name, _, rel_name in SUPPORTED_FLAGS:
441
456
  if current_attr_data.flag_properties[flag_name] != getattr(self, flag_name):
457
+ changelog.add_property(
458
+ name=flag_name,
459
+ value_current=getattr(self, flag_name),
460
+ value_previous=current_attr_data.flag_properties[flag_name],
461
+ )
442
462
  query = await AttributeUpdateFlagQuery.init(db=db, attr=self, at=update_at, flag_name=flag_name)
443
463
  await query.execute(db=db)
444
464
 
@@ -452,6 +472,16 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
452
472
  prop_name in current_attr_data.node_properties
453
473
  and current_attr_data.node_properties[prop_name].uuid == getattr(self, f"{prop_name}_id")
454
474
  ):
475
+ previous_attribute_node_property = current_attr_data.node_properties.get(prop_name)
476
+ previous_value = None
477
+ if previous_attribute_node_property:
478
+ previous_value = previous_attribute_node_property.uuid
479
+
480
+ changelog.add_property(
481
+ name=prop_name,
482
+ value_current=getattr(self, f"{prop_name}_id"),
483
+ value_previous=previous_value,
484
+ )
455
485
  query = await AttributeUpdateNodePropertyQuery.init(
456
486
  db=db, attr=self, at=update_at, prop_name=prop_name, prop_id=getattr(self, f"{prop_name}_id")
457
487
  )
@@ -461,7 +491,8 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
461
491
  if rel and rel.get("branch") == branch.name:
462
492
  await update_relationships_to([rel.element_id], to=update_at, db=db)
463
493
 
464
- return True
494
+ if changelog.has_updates:
495
+ return changelog
465
496
 
466
497
  async def to_graphql(
467
498
  self,
@@ -473,7 +504,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
473
504
  include_properties: bool = True,
474
505
  ) -> dict:
475
506
  """Generate GraphQL Payload for this attribute."""
476
- # pylint: disable=too-many-branches
477
507
 
478
508
  response: dict[str, Any] = {"id": self.id}
479
509
 
@@ -530,11 +560,11 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
530
560
  field = field.value
531
561
  if isinstance(field, str):
532
562
  response[field_name] = self._filter_sensitive(value=field, filter_sensitive=filter_sensitive)
533
- elif isinstance(field, (int, bool, dict, list)):
563
+ elif isinstance(field, int | bool | dict | list):
534
564
  response[field_name] = field
535
565
 
536
- if related_node_ids and self.is_from_profile and getattr(self, "source_id"):
537
- related_node_ids.add(getattr(self, "source_id"))
566
+ if related_node_ids and self.is_from_profile and self.source_id:
567
+ related_node_ids.add(self.source_id)
538
568
 
539
569
  return response
540
570
 
@@ -592,7 +622,6 @@ class BaseAttribute(FlagPropertyMixin, NodePropertyMixin):
592
622
  return AttributeDBNodeType.DEFAULT
593
623
 
594
624
  def get_create_data(self) -> AttributeCreateData:
595
- # pylint: disable=no-member
596
625
  branch = self.branch
597
626
  hierarchy_level = branch.hierarchy_level
598
627
  if self.schema.branch == BranchSupportType.AGNOSTIC:
@@ -1162,7 +1191,7 @@ class ListAttribute(BaseAttribute):
1162
1191
 
1163
1192
  def deserialize_value(self, data: AttributeFromDB) -> Any:
1164
1193
  """Deserialize the value (potentially) coming from the database."""
1165
- if isinstance(data.value, (str, bytes)):
1194
+ if isinstance(data.value, str | bytes):
1166
1195
  return ujson.loads(data.value)
1167
1196
  return data.value
1168
1197
 
@@ -1198,7 +1227,7 @@ class JSONAttribute(BaseAttribute):
1198
1227
 
1199
1228
  def deserialize_value(self, data: AttributeFromDB) -> Any:
1200
1229
  """Deserialize the value (potentially) coming from the database."""
1201
- if data.value and isinstance(data.value, (str, bytes)):
1230
+ if data.value and isinstance(data.value, str | bytes):
1202
1231
  return ujson.loads(data.value)
1203
1232
  return data.value
1204
1233
 
@@ -25,7 +25,7 @@ if TYPE_CHECKING:
25
25
  from infrahub.database import InfrahubDatabase
26
26
 
27
27
 
28
- class Branch(StandardNode): # pylint: disable=too-many-public-methods
28
+ class Branch(StandardNode):
29
29
  name: str = Field(
30
30
  max_length=250, min_length=3, description="Name of the branch (git ref standard)", validate_default=True
31
31
  )
@@ -274,7 +274,7 @@ class Branch(StandardNode): # pylint: disable=too-many-public-methods
274
274
 
275
275
  for rel in rel_labels:
276
276
  filters_per_rel = []
277
- for idx, (branch_name, time_to_query) in enumerate(branches_times.items()):
277
+ for idx in range(len(branches_times)):
278
278
  filters_per_rel.append(
279
279
  f"({rel}.branch IN $branch{idx} AND {rel}.from <= $time{idx} AND {rel}.to IS NULL)"
280
280
  )
@@ -324,7 +324,7 @@ class Branch(StandardNode): # pylint: disable=too-many-public-methods
324
324
  params[f"time{idx}"] = time_to_query
325
325
 
326
326
  filters = []
327
- for idx, (branch_name, time_to_query) in enumerate(branches_times.items()):
327
+ for idx in range(len(branches_times)):
328
328
  filters.append(
329
329
  f"({variable_name}.branch IN $branch{idx} AND {variable_name}.from <= $time{idx} AND {variable_name}.to IS NULL)"
330
330
  )
@@ -404,7 +404,7 @@ class Branch(StandardNode): # pylint: disable=too-many-public-methods
404
404
 
405
405
  for rel in rel_labels:
406
406
  filters_per_rel = []
407
- for idx, branch_name in enumerate(start_times.keys()):
407
+ for idx in range(len(start_times)):
408
408
  filters_per_rel.extend(
409
409
  [
410
410
  f"""({rel}.branch = $branch{idx}
@@ -1,66 +1,62 @@
1
1
  from __future__ import annotations
2
2
 
3
- from datetime import timedelta
4
3
  from typing import Any
4
+ from uuid import uuid4
5
5
 
6
6
  import pydantic
7
7
  from prefect import flow, get_run_logger
8
- from prefect.automations import AutomationCore
9
- from prefect.client.orchestration import get_client
10
- from prefect.client.schemas.filters import DeploymentFilter, DeploymentFilterName
11
8
  from prefect.client.schemas.objects import State # noqa: TC002
12
- from prefect.events.actions import RunDeployment
13
- from prefect.events.schemas.automations import EventTrigger, Posture
14
9
  from prefect.states import Completed, Failed
15
10
 
16
11
  from infrahub import lock
12
+ from infrahub.context import InfrahubContext # noqa: TC001 needed for prefect flow
17
13
  from infrahub.core import registry
18
14
  from infrahub.core.branch import Branch
15
+ from infrahub.core.changelog.diff import DiffChangelogCollector, MigrationTracker
16
+ from infrahub.core.constants import MutationAction
19
17
  from infrahub.core.diff.coordinator import DiffCoordinator
20
18
  from infrahub.core.diff.ipam_diff_parser import IpamDiffParser
21
19
  from infrahub.core.diff.merger.merger import DiffMerger
22
- from infrahub.core.diff.model.path import BranchTrackingId
20
+ from infrahub.core.diff.model.path import BranchTrackingId, EnrichedDiffRoot, EnrichedDiffRootMetadata
23
21
  from infrahub.core.diff.repository.repository import DiffRepository
24
22
  from infrahub.core.merge import BranchMerger
25
23
  from infrahub.core.migrations.schema.models import SchemaApplyMigrationData
26
24
  from infrahub.core.migrations.schema.tasks import schema_apply_migrations
25
+ from infrahub.core.timestamp import Timestamp
27
26
  from infrahub.core.validators.determiner import ConstraintValidatorDeterminer
28
27
  from infrahub.core.validators.models.validate_migration import SchemaValidateMigrationData
29
28
  from infrahub.core.validators.tasks import schema_validate_migrations
30
29
  from infrahub.dependencies.registry import get_component_registry
31
- from infrahub.events.branch_action import BranchCreateEvent, BranchDeleteEvent, BranchRebaseEvent
30
+ from infrahub.events.branch_action import BranchCreatedEvent, BranchDeletedEvent, BranchMergedEvent, BranchRebasedEvent
31
+ from infrahub.events.models import EventMeta, InfrahubEvent
32
+ from infrahub.events.node_action import NodeMutatedEvent
32
33
  from infrahub.exceptions import BranchNotFoundError, MergeFailedError, ValidationError
33
34
  from infrahub.graphql.mutations.models import BranchCreateModel # noqa: TC001
34
35
  from infrahub.log import get_log_data
35
36
  from infrahub.message_bus import Meta, messages
36
- from infrahub.services import services
37
+ from infrahub.services import InfrahubServices # noqa: TC001 needed for prefect flow
37
38
  from infrahub.worker import WORKER_IDENTITY
38
39
  from infrahub.workflows.catalogue import (
39
40
  BRANCH_CANCEL_PROPOSED_CHANGES,
40
- COMPUTED_ATTRIBUTE_REMOVE_PYTHON,
41
- COMPUTED_ATTRIBUTE_SETUP_PYTHON,
42
41
  DIFF_REFRESH_ALL,
43
42
  GIT_REPOSITORIES_CREATE_BRANCH,
44
43
  IPAM_RECONCILIATION,
45
44
  )
46
- from infrahub.workflows.utils import add_branch_tag
47
-
48
- from .constants import AUTOMATION_NAME_CREATE, AUTOMATION_NAME_REMOVE
45
+ from infrahub.workflows.utils import add_tags
49
46
 
50
47
 
51
48
  @flow(name="branch-rebase", flow_run_name="Rebase branch {branch}")
52
- async def rebase_branch(branch: str) -> None:
53
- service = services.service
54
-
49
+ async def rebase_branch(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
55
50
  async with service.database.start_session() as db:
56
51
  log = get_run_logger()
57
- await add_branch_tag(branch_name=branch)
52
+ await add_tags(branches=[branch])
58
53
  obj = await Branch.get_by_name(db=db, name=branch)
59
54
  base_branch = await Branch.get_by_name(db=db, name=registry.default_branch)
60
55
  component_registry = get_component_registry()
61
56
  diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
62
57
  diff_coordinator = await component_registry.get_component(DiffCoordinator, db=db, branch=obj)
63
58
  diff_merger = await component_registry.get_component(DiffMerger, db=db, branch=obj)
59
+ initial_from_time = Timestamp(obj.get_branched_from())
64
60
  merger = BranchMerger(
65
61
  db=db,
66
62
  diff_coordinator=diff_coordinator,
@@ -69,7 +65,7 @@ async def rebase_branch(branch: str) -> None:
69
65
  source_branch=obj,
70
66
  service=service,
71
67
  )
72
- diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
68
+
73
69
  enriched_diff_metadata = await diff_coordinator.update_branch_diff(base_branch=base_branch, diff_branch=obj)
74
70
  async for _ in diff_repository.get_all_conflicts_for_diff(
75
71
  diff_branch_name=enriched_diff_metadata.diff_branch_name, diff_id=enriched_diff_metadata.uuid
@@ -94,14 +90,17 @@ async def rebase_branch(branch: str) -> None:
94
90
  constraints += await merger.calculate_validations(target_schema=candidate_schema)
95
91
  if constraints:
96
92
  responses = await schema_validate_migrations(
97
- message=SchemaValidateMigrationData(branch=obj, schema_branch=candidate_schema, constraints=constraints)
93
+ message=SchemaValidateMigrationData(
94
+ branch=obj, schema_branch=candidate_schema, constraints=constraints
95
+ ),
96
+ service=service,
98
97
  )
99
98
  error_messages = [violation.message for response in responses for violation in response.violations]
100
99
  if error_messages:
101
100
  raise ValidationError(",\n".join(error_messages))
102
101
 
103
102
  schema_in_main_before = merger.destination_schema.duplicate()
104
-
103
+ migrations = []
105
104
  async with lock.registry.global_graph_lock():
106
105
  async with db.start_transaction() as dbt:
107
106
  await obj.rebase(db=dbt)
@@ -132,11 +131,20 @@ async def rebase_branch(branch: str) -> None:
132
131
  new_schema=candidate_schema,
133
132
  previous_schema=schema_in_main_before,
134
133
  migrations=migrations,
135
- )
134
+ ),
135
+ service=service,
136
136
  )
137
137
  for error in errors:
138
138
  log.error(error)
139
139
 
140
+ default_branch_diff = await _get_diff_root(
141
+ diff_coordinator=diff_coordinator,
142
+ enriched_diff_metadata=enriched_diff_metadata,
143
+ diff_repository=diff_repository,
144
+ base_branch=base_branch,
145
+ target_from=initial_from_time,
146
+ )
147
+
140
148
  # -------------------------------------------------------------
141
149
  # Trigger the reconciliation of IPAM data after the rebase
142
150
  # -------------------------------------------------------------
@@ -147,28 +155,55 @@ async def rebase_branch(branch: str) -> None:
147
155
  )
148
156
  if ipam_node_details:
149
157
  await service.workflow.submit_workflow(
150
- workflow=IPAM_RECONCILIATION, parameters={"branch": obj.name, "ipam_node_details": ipam_node_details}
158
+ workflow=IPAM_RECONCILIATION,
159
+ context=context,
160
+ parameters={"branch": obj.name, "ipam_node_details": ipam_node_details},
151
161
  )
152
162
 
153
- await service.workflow.submit_workflow(workflow=DIFF_REFRESH_ALL, parameters={"branch_name": obj.name})
163
+ await service.workflow.submit_workflow(
164
+ workflow=DIFF_REFRESH_ALL, context=context, parameters={"branch_name": obj.name}
165
+ )
154
166
 
155
167
  # -------------------------------------------------------------
156
168
  # Generate an event to indicate that a branch has been rebased
157
169
  # -------------------------------------------------------------
158
- await service.event.send(event=BranchRebaseEvent(branch=obj.name, branch_id=obj.get_id()))
170
+ rebase_event = BranchRebasedEvent(
171
+ branch_name=obj.name, branch_id=str(obj.uuid), meta=EventMeta(branch=obj, context=context)
172
+ )
173
+ events: list[InfrahubEvent] = [rebase_event]
174
+ changelog_collector = DiffChangelogCollector(
175
+ diff=default_branch_diff, branch=obj, db=db, migration_tracker=MigrationTracker(migrations=migrations)
176
+ )
177
+ for action, node_changelog in changelog_collector.collect_changelogs():
178
+ mutate_event = NodeMutatedEvent(
179
+ kind=node_changelog.node_kind,
180
+ node_id=node_changelog.node_id,
181
+ data=node_changelog,
182
+ action=MutationAction.from_diff_action(diff_action=action),
183
+ fields=node_changelog.updated_fields,
184
+ meta=EventMeta.from_parent(parent=rebase_event, branch=obj),
185
+ )
186
+ events.append(mutate_event)
187
+
188
+ for event in events:
189
+ await service.event.send(event)
159
190
 
160
191
 
161
192
  @flow(name="branch-merge", flow_run_name="Merge branch {branch} into main")
162
- async def merge_branch(branch: str) -> None:
163
- service = services.service
193
+ async def merge_branch(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
164
194
  async with service.database.start_session() as db:
165
195
  log = get_run_logger()
166
196
 
167
- await add_branch_tag(branch_name=branch)
168
- await add_branch_tag(branch_name=registry.default_branch)
197
+ await add_tags(branches=[branch, registry.default_branch])
169
198
 
170
199
  obj = await Branch.get_by_name(db=db, name=branch)
200
+ default_branch = await registry.get_branch(db=db, branch=registry.default_branch)
171
201
  component_registry = get_component_registry()
202
+ merge_event = BranchMergedEvent(
203
+ branch_name=obj.name,
204
+ branch_id=str(obj.get_uuid()),
205
+ meta=EventMeta.from_context(context=context, branch=registry.get_global_branch()),
206
+ )
172
207
 
173
208
  merger: BranchMerger | None = None
174
209
  async with lock.registry.global_graph_lock():
@@ -186,13 +221,15 @@ async def merge_branch(branch: str) -> None:
186
221
  service=service,
187
222
  )
188
223
  try:
189
- await merger.merge()
224
+ branch_diff = await merger.merge()
190
225
  except Exception as exc:
191
226
  log.exception("Merge failed, beginning rollback")
192
227
  await merger.rollback()
193
228
  raise MergeFailedError(branch_name=branch) from exc
194
229
  await merger.update_schema()
195
230
 
231
+ changelog_collector = DiffChangelogCollector(diff=branch_diff, branch=obj, db=db)
232
+ node_events = changelog_collector.collect_changelogs()
196
233
  if merger and merger.migrations:
197
234
  errors = await schema_apply_migrations(
198
235
  message=SchemaApplyMigrationData(
@@ -200,7 +237,8 @@ async def merge_branch(branch: str) -> None:
200
237
  new_schema=merger.destination_schema,
201
238
  previous_schema=merger.initial_source_schema,
202
239
  migrations=merger.migrations,
203
- )
240
+ ),
241
+ service=service,
204
242
  )
205
243
  for error in errors:
206
244
  log.error(error)
@@ -216,6 +254,7 @@ async def merge_branch(branch: str) -> None:
216
254
  if ipam_node_details:
217
255
  await service.workflow.submit_workflow(
218
256
  workflow=IPAM_RECONCILIATION,
257
+ context=context,
219
258
  parameters={"branch": registry.default_branch, "ipam_node_details": ipam_node_details},
220
259
  )
221
260
  # -------------------------------------------------------------
@@ -234,24 +273,46 @@ async def merge_branch(branch: str) -> None:
234
273
  message = messages.EventBranchMerge(
235
274
  source_branch=obj.name,
236
275
  target_branch=registry.default_branch,
276
+ context=context,
237
277
  meta=Meta(initiator_id=WORKER_IDENTITY, request_id=request_id),
238
278
  )
239
- await service.send(message=message)
279
+ await service.message_bus.send(message=message)
280
+
281
+ events: list[InfrahubEvent] = [merge_event]
282
+
283
+ for action, node_changelog in node_events:
284
+ meta = EventMeta.from_parent(parent=merge_event, branch=default_branch)
285
+ mutate_event = NodeMutatedEvent(
286
+ kind=node_changelog.node_kind,
287
+ node_id=node_changelog.node_id,
288
+ data=node_changelog,
289
+ action=MutationAction.from_diff_action(diff_action=action),
290
+ fields=node_changelog.updated_fields,
291
+ meta=meta,
292
+ )
293
+ events.append(mutate_event)
240
294
 
295
+ for event in events:
296
+ await service.event.send(event=event)
241
297
 
242
- @flow(name="branch-delete", flow_run_name="Delete branch {branch}")
243
- async def delete_branch(branch: str) -> None:
244
- service = services.service
245
298
 
246
- await add_branch_tag(branch_name=branch)
299
+ @flow(name="branch-delete", flow_run_name="Delete branch {branch}")
300
+ async def delete_branch(branch: str, context: InfrahubContext, service: InfrahubServices) -> None:
301
+ await add_tags(branches=[branch])
247
302
 
248
303
  async with service.database.start_session() as db:
249
304
  obj = await Branch.get_by_name(db=db, name=str(branch))
250
- event = BranchDeleteEvent(branch=branch, branch_id=obj.get_id(), sync_with_git=obj.sync_with_git)
251
305
  await obj.delete(db=db)
252
306
 
307
+ event = BranchDeletedEvent(
308
+ branch_name=branch,
309
+ branch_id=str(obj.uuid),
310
+ sync_with_git=obj.sync_with_git,
311
+ meta=EventMeta.from_context(context=context, branch=registry.get_global_branch()),
312
+ )
313
+
253
314
  await service.workflow.submit_workflow(
254
- workflow=BRANCH_CANCEL_PROPOSED_CHANGES, parameters={"branch_name": branch}
315
+ workflow=BRANCH_CANCEL_PROPOSED_CHANGES, context=context, parameters={"branch_name": branch}
255
316
  )
256
317
 
257
318
  await service.event.send(event=event)
@@ -263,9 +324,8 @@ async def delete_branch(branch: str) -> None:
263
324
  description="Validate if the branch has some conflicts",
264
325
  persist_result=True,
265
326
  )
266
- async def validate_branch(branch: str) -> State:
267
- service = services.service
268
- await add_branch_tag(branch_name=branch)
327
+ async def validate_branch(branch: str, service: InfrahubServices) -> State:
328
+ await add_tags(branches=[branch])
269
329
 
270
330
  async with service.database.start_session() as db:
271
331
  obj = await Branch.get_by_name(db=db, name=branch)
@@ -281,9 +341,8 @@ async def validate_branch(branch: str) -> State:
281
341
 
282
342
 
283
343
  @flow(name="create-branch", flow_run_name="Create branch {model.name}")
284
- async def create_branch(model: BranchCreateModel) -> None:
285
- service = services.service
286
- await add_branch_tag(model.name)
344
+ async def create_branch(model: BranchCreateModel, context: InfrahubContext, service: InfrahubServices) -> None:
345
+ await add_tags(branches=[model.name])
287
346
 
288
347
  async with service.database.start_session() as db:
289
348
  try:
@@ -293,8 +352,7 @@ async def create_branch(model: BranchCreateModel) -> None:
293
352
  pass
294
353
 
295
354
  data_dict: dict[str, Any] = dict(model)
296
- if "is_isolated" in data_dict:
297
- del data_dict["is_isolated"]
355
+ data_dict.pop("is_isolated", None)
298
356
 
299
357
  try:
300
358
  obj = Branch(**data_dict)
@@ -314,93 +372,40 @@ async def create_branch(model: BranchCreateModel) -> None:
314
372
  registry.branch[obj.name] = obj
315
373
  await service.component.refresh_schema_hash(branches=[obj.name])
316
374
 
317
- event = BranchCreateEvent(branch=obj.name, branch_id=str(obj.uuid), sync_with_git=obj.sync_with_git)
375
+ event = BranchCreatedEvent(
376
+ branch_name=obj.name,
377
+ branch_id=str(obj.uuid),
378
+ sync_with_git=obj.sync_with_git,
379
+ meta=EventMeta.from_context(context=context, branch=registry.get_global_branch()),
380
+ )
318
381
  await service.event.send(event=event)
319
382
 
320
383
  if obj.sync_with_git:
321
384
  await service.workflow.submit_workflow(
322
385
  workflow=GIT_REPOSITORIES_CREATE_BRANCH,
386
+ context=context,
323
387
  parameters={"branch": obj.name, "branch_id": str(obj.uuid)},
324
388
  )
325
389
 
326
390
 
327
- @flow(name="branch-actions-setup", flow_run_name="Setup branch action events in task-manager")
328
- async def branch_actions_setup() -> None:
329
- log = get_run_logger()
330
-
331
- async with get_client(sync_client=False) as client:
332
- deployments = {
333
- item.name: item
334
- for item in await client.read_deployments(
335
- deployment_filter=DeploymentFilter(
336
- name=DeploymentFilterName(
337
- any_=[COMPUTED_ATTRIBUTE_SETUP_PYTHON.name, COMPUTED_ATTRIBUTE_REMOVE_PYTHON.name]
338
- )
339
- )
340
- )
341
- }
342
- deployment_id_computed_attribute_setup_python = deployments[COMPUTED_ATTRIBUTE_SETUP_PYTHON.name].id
343
- deployment_id_computed_attribute_remove_python = deployments[COMPUTED_ATTRIBUTE_REMOVE_PYTHON.name].id
344
-
345
- branch_create_automation = await client.find_automation(id_or_name=AUTOMATION_NAME_CREATE)
346
-
347
- automation = AutomationCore(
348
- name=AUTOMATION_NAME_CREATE,
349
- description="Trigger actions on branch create event",
350
- enabled=True,
351
- trigger=EventTrigger(
352
- posture=Posture.Reactive,
353
- expect={"infrahub.branch.created"},
354
- within=timedelta(0),
355
- threshold=1,
356
- ),
357
- actions=[
358
- RunDeployment(
359
- source="selected",
360
- deployment_id=deployment_id_computed_attribute_setup_python,
361
- parameters={
362
- "branch_name": "{{ event.resource['infrahub.branch.name'] }}",
363
- "trigger_updates": False,
364
- },
365
- job_variables={},
366
- ),
367
- ],
368
- )
369
-
370
- if branch_create_automation:
371
- await client.update_automation(automation_id=branch_create_automation.id, automation=automation)
372
- log.info(f"{AUTOMATION_NAME_CREATE} Updated")
373
- else:
374
- await client.create_automation(automation=automation)
375
- log.info(f"{AUTOMATION_NAME_CREATE} Created")
376
-
377
- branch_remove_automation = await client.find_automation(id_or_name=AUTOMATION_NAME_REMOVE)
378
-
379
- automation = AutomationCore(
380
- name=AUTOMATION_NAME_REMOVE,
381
- description="Trigger actions on branch delete event",
382
- enabled=True,
383
- trigger=EventTrigger(
384
- posture=Posture.Reactive,
385
- expect={"infrahub.branch.deleted"},
386
- within=timedelta(0),
387
- threshold=1,
388
- ),
389
- actions=[
390
- RunDeployment(
391
- source="selected",
392
- deployment_id=deployment_id_computed_attribute_remove_python,
393
- parameters={
394
- "branch_name": "{{ event.resource['infrahub.branch.name'] }}",
395
- },
396
- job_variables={},
397
- ),
398
- ],
391
+ async def _get_diff_root(
392
+ diff_coordinator: DiffCoordinator,
393
+ enriched_diff_metadata: EnrichedDiffRootMetadata,
394
+ diff_repository: DiffRepository,
395
+ base_branch: Branch,
396
+ target_from: Timestamp,
397
+ ) -> EnrichedDiffRoot:
398
+ default_branch_diff = await diff_coordinator.create_or_update_arbitrary_timeframe_diff(
399
+ base_branch=base_branch,
400
+ diff_branch=base_branch,
401
+ from_time=target_from,
402
+ to_time=enriched_diff_metadata.to_time,
403
+ name=str(uuid4()),
404
+ )
405
+ # make sure we have the actual diff with data and not just the metadata
406
+ if not isinstance(default_branch_diff, EnrichedDiffRoot):
407
+ default_branch_diff = await diff_repository.get_one(
408
+ diff_branch_name=base_branch.name, diff_id=default_branch_diff.uuid
399
409
  )
400
410
 
401
- if branch_remove_automation:
402
- await client.update_automation(automation_id=branch_remove_automation.id, automation=automation)
403
- log.info(f"{AUTOMATION_NAME_REMOVE} Updated")
404
- else:
405
- await client.create_automation(automation=automation)
406
- log.info(f"{AUTOMATION_NAME_REMOVE} Created")
411
+ return default_branch_diff