keboola-cli 0.63.4__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.
- keboola_agent_cli/__init__.py +34 -0
- keboola_agent_cli/__main__.py +5 -0
- keboola_agent_cli/_ui_dist/assets/arc-DhFYIddx.js +2 -0
- keboola_agent_cli/_ui_dist/assets/arc-DhFYIddx.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/architecture-7EHR7CIX-hNCijx_H.js +1 -0
- keboola_agent_cli/_ui_dist/assets/architectureDiagram-3BPJPVTR-C6hUlprM.js +37 -0
- keboola_agent_cli/_ui_dist/assets/architectureDiagram-3BPJPVTR-C6hUlprM.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/array-BifhSqXX.js +2 -0
- keboola_agent_cli/_ui_dist/assets/array-BifhSqXX.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/blockDiagram-GPEHLZMM-DC7qY9i4.js +133 -0
- keboola_agent_cli/_ui_dist/assets/blockDiagram-GPEHLZMM-DC7qY9i4.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/c4Diagram-AAUBKEIU-5Lh44evt.js +11 -0
- keboola_agent_cli/_ui_dist/assets/c4Diagram-AAUBKEIU-5Lh44evt.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/channel-DBMrXlxx.js +2 -0
- keboola_agent_cli/_ui_dist/assets/channel-DBMrXlxx.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-2J33WTMH-Coy82EBh.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-2J33WTMH-Coy82EBh.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-3OPIFGDE-BQC5CRHI.js +63 -0
- keboola_agent_cli/_ui_dist/assets/chunk-3OPIFGDE-BQC5CRHI.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-4BX2VUAB-DUuEt70o.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-4BX2VUAB-DUuEt70o.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-55IACEB6-BvR-6chF.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-55IACEB6-BvR-6chF.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-5ZQYHXKU-BjcTN7ul.js +3 -0
- keboola_agent_cli/_ui_dist/assets/chunk-5ZQYHXKU-BjcTN7ul.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-727SXJPM-C0zxqqRN.js +207 -0
- keboola_agent_cli/_ui_dist/assets/chunk-727SXJPM-C0zxqqRN.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-AQP2D5EJ-CXf7rIlZ.js +232 -0
- keboola_agent_cli/_ui_dist/assets/chunk-AQP2D5EJ-CXf7rIlZ.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-BSJP7CBP-Oj_FO9Q7.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-BSJP7CBP-Oj_FO9Q7.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-CSCIHK7Q-CcTsLrFc.js +124 -0
- keboola_agent_cli/_ui_dist/assets/chunk-CSCIHK7Q-CcTsLrFc.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-FMBD7UC4-FH-zLkkW.js +16 -0
- keboola_agent_cli/_ui_dist/assets/chunk-FMBD7UC4-FH-zLkkW.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-L5ZTLDWV-B1Ky_e7O.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-L5ZTLDWV-B1Ky_e7O.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-ND2GUHAM-BHz1rpbm.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-ND2GUHAM-BHz1rpbm.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-NNHCCRGN-DlpIbxXb.js +160 -0
- keboola_agent_cli/_ui_dist/assets/chunk-NNHCCRGN-DlpIbxXb.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-NZK2D7GU-tnrSoegS.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-NZK2D7GU-tnrSoegS.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-O5CBEL6O-DxxqDH0l.js +71 -0
- keboola_agent_cli/_ui_dist/assets/chunk-O5CBEL6O-DxxqDH0l.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/chunk-QZHKN3VN-CSjc2gjj.js +2 -0
- keboola_agent_cli/_ui_dist/assets/chunk-QZHKN3VN-CSjc2gjj.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/classDiagram-4FO5ZUOK-BuZcZu85.js +2 -0
- keboola_agent_cli/_ui_dist/assets/classDiagram-4FO5ZUOK-BuZcZu85.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/classDiagram-v2-Q7XG4LA2-BuZcZu85.js +2 -0
- keboola_agent_cli/_ui_dist/assets/classDiagram-v2-Q7XG4LA2-BuZcZu85.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/cose-bilkent-S5V4N54A-Y0L8LDMa.js +2 -0
- keboola_agent_cli/_ui_dist/assets/cose-bilkent-S5V4N54A-Y0L8LDMa.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/cytoscape.esm-C8YCVR3_.js +322 -0
- keboola_agent_cli/_ui_dist/assets/cytoscape.esm-C8YCVR3_.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/dagre-BM42HDAG-UZ-9BTqF.js +5 -0
- keboola_agent_cli/_ui_dist/assets/dagre-BM42HDAG-UZ-9BTqF.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/dagre-Bx709z4p.js +2 -0
- keboola_agent_cli/_ui_dist/assets/dagre-Bx709z4p.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/defaultLocale-C8Fc0cco.js +2 -0
- keboola_agent_cli/_ui_dist/assets/defaultLocale-C8Fc0cco.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/diagram-2AECGRRQ-DoDQ60wi.js +44 -0
- keboola_agent_cli/_ui_dist/assets/diagram-2AECGRRQ-DoDQ60wi.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/diagram-5GNKFQAL-CMGFxpUs.js +11 -0
- keboola_agent_cli/_ui_dist/assets/diagram-5GNKFQAL-CMGFxpUs.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/diagram-KO2AKTUF-1uGDa-Iu.js +4 -0
- keboola_agent_cli/_ui_dist/assets/diagram-KO2AKTUF-1uGDa-Iu.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/diagram-LMA3HP47-XtFH7B51.js +25 -0
- keboola_agent_cli/_ui_dist/assets/diagram-LMA3HP47-XtFH7B51.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/diagram-OG6HWLK6-B4_Te1T5.js +25 -0
- keboola_agent_cli/_ui_dist/assets/diagram-OG6HWLK6-B4_Te1T5.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/dist-Di6zmlv0.js +2 -0
- keboola_agent_cli/_ui_dist/assets/dist-Di6zmlv0.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/erDiagram-TEJ5UH35-NjQkrdFt.js +86 -0
- keboola_agent_cli/_ui_dist/assets/erDiagram-TEJ5UH35-NjQkrdFt.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/eventmodeling-FCH6USID-BrJMIks8.js +1 -0
- keboola_agent_cli/_ui_dist/assets/flowDiagram-I6XJVG4X-CIr8DWl7.js +163 -0
- keboola_agent_cli/_ui_dist/assets/flowDiagram-I6XJVG4X-CIr8DWl7.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/ganttDiagram-6RSMTGT7-C1VY_xbQ.js +293 -0
- keboola_agent_cli/_ui_dist/assets/ganttDiagram-6RSMTGT7-C1VY_xbQ.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/gitGraph-WXDBUCRP-COacYjo-.js +1 -0
- keboola_agent_cli/_ui_dist/assets/gitGraphDiagram-PVQCEYII-DQT8-kg2.js +107 -0
- keboola_agent_cli/_ui_dist/assets/gitGraphDiagram-PVQCEYII-DQT8-kg2.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/graphlib-B8gBHxth.js +2 -0
- keboola_agent_cli/_ui_dist/assets/graphlib-B8gBHxth.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/index-CMq50kkV.css +1 -0
- keboola_agent_cli/_ui_dist/assets/index-D8W97DAz.js +118 -0
- keboola_agent_cli/_ui_dist/assets/index-D8W97DAz.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/info-J43DQDTF-DdCTRIzU.js +1 -0
- keboola_agent_cli/_ui_dist/assets/infoDiagram-5YYISTIA-C77rsoTp.js +3 -0
- keboola_agent_cli/_ui_dist/assets/infoDiagram-5YYISTIA-C77rsoTp.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/init-D6jRqBbL.js +2 -0
- keboola_agent_cli/_ui_dist/assets/init-D6jRqBbL.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/ishikawaDiagram-YF4QCWOH-BcTbXaLy.js +71 -0
- keboola_agent_cli/_ui_dist/assets/ishikawaDiagram-YF4QCWOH-BcTbXaLy.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/journeyDiagram-JHISSGLW-BejeAJQ_.js +140 -0
- keboola_agent_cli/_ui_dist/assets/journeyDiagram-JHISSGLW-BejeAJQ_.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/kanban-definition-UN3LZRKU-BRNz_UrH.js +90 -0
- keboola_agent_cli/_ui_dist/assets/kanban-definition-UN3LZRKU-BRNz_UrH.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/katex-C4eR7coU.js +258 -0
- keboola_agent_cli/_ui_dist/assets/katex-C4eR7coU.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/line-CzAQKFbJ.js +2 -0
- keboola_agent_cli/_ui_dist/assets/line-CzAQKFbJ.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/linear-DUNFFdck.js +2 -0
- keboola_agent_cli/_ui_dist/assets/linear-DUNFFdck.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/mermaid-parser.core-CpuBOkFa.js +5 -0
- keboola_agent_cli/_ui_dist/assets/mermaid-parser.core-CpuBOkFa.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/mindmap-definition-RKZ34NQL-9EJQNjH0.js +97 -0
- keboola_agent_cli/_ui_dist/assets/mindmap-definition-RKZ34NQL-9EJQNjH0.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/ordinal-hYBb2elL.js +2 -0
- keboola_agent_cli/_ui_dist/assets/ordinal-hYBb2elL.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/packet-YPE3B663-DLiiw_B2.js +1 -0
- keboola_agent_cli/_ui_dist/assets/path-BWPyau1x.js +2 -0
- keboola_agent_cli/_ui_dist/assets/path-BWPyau1x.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/pie-LRSECV5Y-CRoO8G1g.js +1 -0
- keboola_agent_cli/_ui_dist/assets/pieDiagram-4H26LBE5-XH4cy6Cb.js +31 -0
- keboola_agent_cli/_ui_dist/assets/pieDiagram-4H26LBE5-XH4cy6Cb.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/quadrantDiagram-W4KKPZXB-fdhc93U8.js +8 -0
- keboola_agent_cli/_ui_dist/assets/quadrantDiagram-W4KKPZXB-fdhc93U8.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/radar-GUYGQ44K-DAlLVJHm.js +1 -0
- keboola_agent_cli/_ui_dist/assets/requirementDiagram-4Y6WPE33-a94eP3R9.js +85 -0
- keboola_agent_cli/_ui_dist/assets/requirementDiagram-4Y6WPE33-a94eP3R9.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/rough.esm-CSKSodPl.js +2 -0
- keboola_agent_cli/_ui_dist/assets/rough.esm-CSKSodPl.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/sankeyDiagram-5OEKKPKP-jcBa02sp.js +41 -0
- keboola_agent_cli/_ui_dist/assets/sankeyDiagram-5OEKKPKP-jcBa02sp.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/sequenceDiagram-3UESZ5HK-A5-GGM-e.js +163 -0
- keboola_agent_cli/_ui_dist/assets/sequenceDiagram-3UESZ5HK-A5-GGM-e.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/src-ZI-V_AF0.js +2 -0
- keboola_agent_cli/_ui_dist/assets/src-ZI-V_AF0.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/stateDiagram-AJRCARHV-BKAA5rqE.js +2 -0
- keboola_agent_cli/_ui_dist/assets/stateDiagram-AJRCARHV-BKAA5rqE.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/stateDiagram-v2-BHNVJYJU-DnJwJBsE.js +2 -0
- keboola_agent_cli/_ui_dist/assets/stateDiagram-v2-BHNVJYJU-DnJwJBsE.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/timeline-definition-PNZ67QCA-Cy39jp8b.js +121 -0
- keboola_agent_cli/_ui_dist/assets/timeline-definition-PNZ67QCA-Cy39jp8b.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/treeView-BLDUP644-DbLYl23-.js +1 -0
- keboola_agent_cli/_ui_dist/assets/treemap-LRROVOQU-Bp0eGlOt.js +1 -0
- keboola_agent_cli/_ui_dist/assets/vennDiagram-CIIHVFJN-BGECKubd.js +35 -0
- keboola_agent_cli/_ui_dist/assets/vennDiagram-CIIHVFJN-BGECKubd.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/wardley-L42UT6IY-D4yH4jqS.js +1 -0
- keboola_agent_cli/_ui_dist/assets/wardleyDiagram-YWT4CUSO-D6XRG3cZ.js +79 -0
- keboola_agent_cli/_ui_dist/assets/wardleyDiagram-YWT4CUSO-D6XRG3cZ.js.map +1 -0
- keboola_agent_cli/_ui_dist/assets/xychartDiagram-2RQKCTM6-DRre-pfZ.js +8 -0
- keboola_agent_cli/_ui_dist/assets/xychartDiagram-2RQKCTM6-DRre-pfZ.js.map +1 -0
- keboola_agent_cli/_ui_dist/index.html +50 -0
- keboola_agent_cli/ai_client.py +83 -0
- keboola_agent_cli/auto_update.py +550 -0
- keboola_agent_cli/changelog.py +1198 -0
- keboola_agent_cli/cli.py +448 -0
- keboola_agent_cli/client.py +3422 -0
- keboola_agent_cli/commands/__init__.py +0 -0
- keboola_agent_cli/commands/_data_app_git.py +343 -0
- keboola_agent_cli/commands/_helpers.py +377 -0
- keboola_agent_cli/commands/_metadata_input.py +49 -0
- keboola_agent_cli/commands/_semantic_layer_crud.py +632 -0
- keboola_agent_cli/commands/_semantic_layer_helpers.py +44 -0
- keboola_agent_cli/commands/_semantic_layer_reference_data.py +247 -0
- keboola_agent_cli/commands/agent.py +968 -0
- keboola_agent_cli/commands/branch.py +423 -0
- keboola_agent_cli/commands/changelog.py +168 -0
- keboola_agent_cli/commands/component.py +216 -0
- keboola_agent_cli/commands/config.py +2442 -0
- keboola_agent_cli/commands/context.py +1481 -0
- keboola_agent_cli/commands/data_app.py +1279 -0
- keboola_agent_cli/commands/dev_portal.py +584 -0
- keboola_agent_cli/commands/doctor.py +37 -0
- keboola_agent_cli/commands/encrypt.py +145 -0
- keboola_agent_cli/commands/feature.py +311 -0
- keboola_agent_cli/commands/flow.py +948 -0
- keboola_agent_cli/commands/http_client.py +157 -0
- keboola_agent_cli/commands/init.py +279 -0
- keboola_agent_cli/commands/job.py +661 -0
- keboola_agent_cli/commands/kai.py +301 -0
- keboola_agent_cli/commands/lineage.py +1464 -0
- keboola_agent_cli/commands/org.py +292 -0
- keboola_agent_cli/commands/permissions.py +360 -0
- keboola_agent_cli/commands/project.py +1192 -0
- keboola_agent_cli/commands/repl.py +243 -0
- keboola_agent_cli/commands/schedule.py +340 -0
- keboola_agent_cli/commands/search.py +178 -0
- keboola_agent_cli/commands/semantic_layer.py +939 -0
- keboola_agent_cli/commands/serve.py +272 -0
- keboola_agent_cli/commands/sharing.py +340 -0
- keboola_agent_cli/commands/storage.py +2630 -0
- keboola_agent_cli/commands/stream.py +266 -0
- keboola_agent_cli/commands/sync.py +1277 -0
- keboola_agent_cli/commands/tool.py +206 -0
- keboola_agent_cli/commands/version.py +186 -0
- keboola_agent_cli/commands/workspace.py +635 -0
- keboola_agent_cli/config_store.py +582 -0
- keboola_agent_cli/constants.py +528 -0
- keboola_agent_cli/data_science_client.py +342 -0
- keboola_agent_cli/dev_portal_client.py +323 -0
- keboola_agent_cli/errors.py +248 -0
- keboola_agent_cli/http_base.py +315 -0
- keboola_agent_cli/json_utils.py +126 -0
- keboola_agent_cli/lib.py +536 -0
- keboola_agent_cli/manage_client.py +324 -0
- keboola_agent_cli/metastore_client.py +214 -0
- keboola_agent_cli/models.py +427 -0
- keboola_agent_cli/output.py +1084 -0
- keboola_agent_cli/permissions.py +469 -0
- keboola_agent_cli/py.typed +3 -0
- keboola_agent_cli/result_models.py +271 -0
- keboola_agent_cli/server/__init__.py +34 -0
- keboola_agent_cli/server/agent_runner.py +1289 -0
- keboola_agent_cli/server/agents_store.py +325 -0
- keboola_agent_cli/server/app.py +764 -0
- keboola_agent_cli/server/auth.py +117 -0
- keboola_agent_cli/server/dependencies.py +149 -0
- keboola_agent_cli/server/pricing.py +303 -0
- keboola_agent_cli/server/routers/__init__.py +1 -0
- keboola_agent_cli/server/routers/agents.py +616 -0
- keboola_agent_cli/server/routers/ai_chat.py +129 -0
- keboola_agent_cli/server/routers/branches.py +133 -0
- keboola_agent_cli/server/routers/components.py +48 -0
- keboola_agent_cli/server/routers/configs.py +507 -0
- keboola_agent_cli/server/routers/data_apps.py +384 -0
- keboola_agent_cli/server/routers/dev_portal.py +67 -0
- keboola_agent_cli/server/routers/encrypt.py +35 -0
- keboola_agent_cli/server/routers/feature.py +179 -0
- keboola_agent_cli/server/routers/flows.py +204 -0
- keboola_agent_cli/server/routers/health.py +53 -0
- keboola_agent_cli/server/routers/jobs.py +175 -0
- keboola_agent_cli/server/routers/kai.py +80 -0
- keboola_agent_cli/server/routers/lineage.py +226 -0
- keboola_agent_cli/server/routers/mcp.py +70 -0
- keboola_agent_cli/server/routers/members.py +170 -0
- keboola_agent_cli/server/routers/org.py +96 -0
- keboola_agent_cli/server/routers/projects.py +106 -0
- keboola_agent_cli/server/routers/schedules.py +54 -0
- keboola_agent_cli/server/routers/search.py +30 -0
- keboola_agent_cli/server/routers/semantic_layer.py +650 -0
- keboola_agent_cli/server/routers/sharing.py +86 -0
- keboola_agent_cli/server/routers/storage.py +574 -0
- keboola_agent_cli/server/routers/stream.py +100 -0
- keboola_agent_cli/server/routers/workspaces.py +302 -0
- keboola_agent_cli/server/run_broadcaster.py +329 -0
- keboola_agent_cli/server/sse.py +25 -0
- keboola_agent_cli/services/__init__.py +0 -0
- keboola_agent_cli/services/_encryption.py +217 -0
- keboola_agent_cli/services/_semantic_layer_cascade.py +147 -0
- keboola_agent_cli/services/_semantic_layer_crud.py +382 -0
- keboola_agent_cli/services/_semantic_layer_internals.py +1078 -0
- keboola_agent_cli/services/_semantic_layer_lookup.py +181 -0
- keboola_agent_cli/services/_semantic_layer_reference_data.py +217 -0
- keboola_agent_cli/services/_sync_bindings.py +456 -0
- keboola_agent_cli/services/_sync_branch.py +191 -0
- keboola_agent_cli/services/_sync_bulk.py +228 -0
- keboola_agent_cli/services/_sync_clone.py +163 -0
- keboola_agent_cli/services/_sync_models.py +97 -0
- keboola_agent_cli/services/_sync_push_ops.py +369 -0
- keboola_agent_cli/services/_sync_storage.py +376 -0
- keboola_agent_cli/services/_sync_writeback.py +167 -0
- keboola_agent_cli/services/agent_service.py +458 -0
- keboola_agent_cli/services/base.py +175 -0
- keboola_agent_cli/services/branch_service.py +588 -0
- keboola_agent_cli/services/component_service.py +694 -0
- keboola_agent_cli/services/config_service.py +2099 -0
- keboola_agent_cli/services/data_app_git_service.py +224 -0
- keboola_agent_cli/services/data_app_service.py +2082 -0
- keboola_agent_cli/services/deep_lineage_service.py +1322 -0
- keboola_agent_cli/services/dev_portal_service.py +345 -0
- keboola_agent_cli/services/doctor_service.py +445 -0
- keboola_agent_cli/services/encrypt_service.py +87 -0
- keboola_agent_cli/services/feature_service.py +268 -0
- keboola_agent_cli/services/flow_service.py +769 -0
- keboola_agent_cli/services/flow_validation.py +188 -0
- keboola_agent_cli/services/http_forwarder_service.py +236 -0
- keboola_agent_cli/services/job_idempotency_store.py +285 -0
- keboola_agent_cli/services/job_service.py +797 -0
- keboola_agent_cli/services/kai_service.py +367 -0
- keboola_agent_cli/services/lineage_service.py +274 -0
- keboola_agent_cli/services/mcp_service.py +1498 -0
- keboola_agent_cli/services/mcp_transport.py +259 -0
- keboola_agent_cli/services/member_service.py +593 -0
- keboola_agent_cli/services/org_service.py +619 -0
- keboola_agent_cli/services/project_service.py +947 -0
- keboola_agent_cli/services/repo_validate_service.py +767 -0
- keboola_agent_cli/services/schedule_service.py +731 -0
- keboola_agent_cli/services/search_service.py +331 -0
- keboola_agent_cli/services/semantic_layer_service.py +1497 -0
- keboola_agent_cli/services/sharing_service.py +307 -0
- keboola_agent_cli/services/storage_service.py +2524 -0
- keboola_agent_cli/services/stream_service.py +395 -0
- keboola_agent_cli/services/sync_service.py +2244 -0
- keboola_agent_cli/services/variables_service.py +447 -0
- keboola_agent_cli/services/version_service.py +1038 -0
- keboola_agent_cli/services/workspace_service.py +1103 -0
- keboola_agent_cli/stream_client.py +217 -0
- keboola_agent_cli/sync/__init__.py +1 -0
- keboola_agent_cli/sync/branch_mapping.py +174 -0
- keboola_agent_cli/sync/clone.py +211 -0
- keboola_agent_cli/sync/code_extraction.py +655 -0
- keboola_agent_cli/sync/config_format.py +290 -0
- keboola_agent_cli/sync/diff_engine.py +566 -0
- keboola_agent_cli/sync/git_utils.py +93 -0
- keboola_agent_cli/sync/manifest.py +162 -0
- keboola_agent_cli/sync/naming.py +90 -0
- keboola_agent_cli/sync/secrets.py +62 -0
- keboola_agent_cli/sync/sql_split.py +134 -0
- keboola_cli-0.63.4.dist-info/METADATA +308 -0
- keboola_cli-0.63.4.dist-info/RECORD +306 -0
- keboola_cli-0.63.4.dist-info/WHEEL +4 -0
- keboola_cli-0.63.4.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
"""Push-time link backfill for the sync service (Phase C + Phase D).
|
|
2
|
+
|
|
3
|
+
Extracted from ``sync_service.py`` to keep that file under control. These are
|
|
4
|
+
free functions that take the ``SyncService`` as their first argument (for the
|
|
5
|
+
handful of on-disk helpers they need -- ``_read_config_file``,
|
|
6
|
+
``_write_config_file``, ``_compute_config_hashes``) rather than methods, so the
|
|
7
|
+
typing stays explicit and the binding logic is testable in isolation.
|
|
8
|
+
|
|
9
|
+
- **Phase C** (:func:`resolve_variable_bindings`): rebind a transformation's
|
|
10
|
+
``variables_id`` / ``variables_values_id`` placeholders to the ULIDs created
|
|
11
|
+
this push.
|
|
12
|
+
- **Phase D** (:func:`resolve_flow_task_bindings`): remap ``keboola.flow`` task
|
|
13
|
+
``configId``s to the ULIDs created this push.
|
|
14
|
+
|
|
15
|
+
Both run after the create passes, PUT the corrected config, rewrite the local
|
|
16
|
+
``_config.yml``, and refresh the manifest hashes so a re-push is clean.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import copy
|
|
22
|
+
import logging
|
|
23
|
+
from typing import TYPE_CHECKING, Any
|
|
24
|
+
|
|
25
|
+
from ..errors import ErrorCode, KeboolaApiError
|
|
26
|
+
from ..sync.code_extraction import merge_code_files
|
|
27
|
+
from ..sync.config_format import local_config_to_api
|
|
28
|
+
from ..sync.manifest import Manifest
|
|
29
|
+
from ._sync_models import (
|
|
30
|
+
FLOW_COMPONENT_ID,
|
|
31
|
+
VARIABLES_COMPONENT_ID,
|
|
32
|
+
CreatedConfig,
|
|
33
|
+
FlowBindingResult,
|
|
34
|
+
VariableBindingResult,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
from .sync_service import SyncService
|
|
39
|
+
|
|
40
|
+
logger = logging.getLogger(__name__)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
# Phase C: transformation -> variables links
|
|
45
|
+
# ---------------------------------------------------------------------------
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def resolve_variable_bindings(
|
|
49
|
+
service: SyncService,
|
|
50
|
+
client: Any,
|
|
51
|
+
*,
|
|
52
|
+
created_configs: list[CreatedConfig],
|
|
53
|
+
created_id_map: dict[tuple[str, str], str],
|
|
54
|
+
created_row_id_map: dict[str, str],
|
|
55
|
+
created_rows_by_parent: dict[str, list[str]],
|
|
56
|
+
manifest: Manifest,
|
|
57
|
+
branch_id: int | None,
|
|
58
|
+
) -> VariableBindingResult:
|
|
59
|
+
"""Rebind transformation -> variables links from placeholders to ULIDs.
|
|
60
|
+
|
|
61
|
+
On a fresh CREATE the transformation config is POSTed with its
|
|
62
|
+
``_configuration_extra.variables_id`` / ``variables_values_id`` still set to
|
|
63
|
+
the externally-authored placeholder strings (``config_format`` merges
|
|
64
|
+
``_configuration_extra`` into the API body verbatim). This pass, run after
|
|
65
|
+
the variables config and its values row have been created, resolves each
|
|
66
|
+
placeholder to the ULID assigned during this push, PUTs the corrected
|
|
67
|
+
configuration body, then rewrites the local file and refreshes the manifest
|
|
68
|
+
hashes so a re-push is clean (KFR-03).
|
|
69
|
+
|
|
70
|
+
Resolution is a no-op when no ``keboola.variables`` config was created this
|
|
71
|
+
push (the already-bound / UPDATE path). When the exact placeholder key
|
|
72
|
+
misses but exactly one ``keboola.variables`` config was created this push,
|
|
73
|
+
it binds to that one with a warning; zero or ambiguous (>1) matches
|
|
74
|
+
accumulate an error rather than writing a broken link.
|
|
75
|
+
"""
|
|
76
|
+
result = VariableBindingResult()
|
|
77
|
+
|
|
78
|
+
created_variables_ulids = [
|
|
79
|
+
ulid
|
|
80
|
+
for (component_id, _placeholder), ulid in created_id_map.items()
|
|
81
|
+
if component_id == VARIABLES_COMPONENT_ID
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
for created in created_configs:
|
|
85
|
+
if created.component_id == VARIABLES_COMPONENT_ID:
|
|
86
|
+
continue # the variables config itself never carries a link
|
|
87
|
+
local_data = service._read_config_file(created.config_dir)
|
|
88
|
+
if local_data is None:
|
|
89
|
+
continue
|
|
90
|
+
extra = local_data.get("_configuration_extra")
|
|
91
|
+
if not isinstance(extra, dict):
|
|
92
|
+
continue
|
|
93
|
+
vars_placeholder = extra.get("variables_id")
|
|
94
|
+
if not vars_placeholder or not isinstance(vars_placeholder, str):
|
|
95
|
+
continue
|
|
96
|
+
raw_vals = extra.get("variables_values_id")
|
|
97
|
+
vals_placeholder = raw_vals if isinstance(raw_vals, str) else ""
|
|
98
|
+
|
|
99
|
+
parent_ulid = _resolve_variables_parent(
|
|
100
|
+
created=created,
|
|
101
|
+
vars_placeholder=vars_placeholder,
|
|
102
|
+
created_id_map=created_id_map,
|
|
103
|
+
created_variables_ulids=created_variables_ulids,
|
|
104
|
+
errors=result.errors,
|
|
105
|
+
)
|
|
106
|
+
if parent_ulid is None:
|
|
107
|
+
continue
|
|
108
|
+
|
|
109
|
+
row_ulid = _resolve_variables_row(
|
|
110
|
+
created=created,
|
|
111
|
+
parent_ulid=parent_ulid,
|
|
112
|
+
vals_placeholder=vals_placeholder,
|
|
113
|
+
created_row_id_map=created_row_id_map,
|
|
114
|
+
created_rows_by_parent=created_rows_by_parent,
|
|
115
|
+
errors=result.errors,
|
|
116
|
+
)
|
|
117
|
+
# A missing-but-required values row already recorded an error.
|
|
118
|
+
if vals_placeholder and row_ulid is None:
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
_apply_variable_binding(
|
|
123
|
+
service,
|
|
124
|
+
client,
|
|
125
|
+
created=created,
|
|
126
|
+
local_data=local_data,
|
|
127
|
+
parent_ulid=parent_ulid,
|
|
128
|
+
row_ulid=row_ulid,
|
|
129
|
+
manifest=manifest,
|
|
130
|
+
branch_id=branch_id,
|
|
131
|
+
)
|
|
132
|
+
except KeboolaApiError as exc:
|
|
133
|
+
result.errors.append(
|
|
134
|
+
{
|
|
135
|
+
"change_type": "variable_link",
|
|
136
|
+
"error_code": ErrorCode.VARIABLE_LINK_UNRESOLVED,
|
|
137
|
+
"component_id": created.component_id,
|
|
138
|
+
"config_id": created.config_id,
|
|
139
|
+
"message": str(exc),
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
continue
|
|
143
|
+
result.configs_rewritten += 1
|
|
144
|
+
|
|
145
|
+
return result
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _resolve_variables_parent(
|
|
149
|
+
*,
|
|
150
|
+
created: CreatedConfig,
|
|
151
|
+
vars_placeholder: str,
|
|
152
|
+
created_id_map: dict[tuple[str, str], str],
|
|
153
|
+
created_variables_ulids: list[str],
|
|
154
|
+
errors: list[dict[str, str]],
|
|
155
|
+
) -> str | None:
|
|
156
|
+
"""Resolve a transformation's ``variables_id`` placeholder to a ULID.
|
|
157
|
+
|
|
158
|
+
Returns the ULID, or ``None`` when there is nothing to backfill
|
|
159
|
+
(already-bound path) or the link is ambiguous (an error is appended).
|
|
160
|
+
"""
|
|
161
|
+
parent_ulid = created_id_map.get((VARIABLES_COMPONENT_ID, vars_placeholder))
|
|
162
|
+
if parent_ulid is not None:
|
|
163
|
+
return parent_ulid
|
|
164
|
+
if not created_variables_ulids:
|
|
165
|
+
# No variables config created this push: the link is either already
|
|
166
|
+
# a ULID (UPDATE path) or points outside this push. Leave it.
|
|
167
|
+
return None
|
|
168
|
+
if len(created_variables_ulids) == 1:
|
|
169
|
+
parent_ulid = created_variables_ulids[0]
|
|
170
|
+
logger.warning(
|
|
171
|
+
"Transformation %s/%s variables_id placeholder %r did not match any "
|
|
172
|
+
"created variables config; binding to the single keboola.variables "
|
|
173
|
+
"config created this push (%s).",
|
|
174
|
+
created.component_id,
|
|
175
|
+
created.config_id,
|
|
176
|
+
vars_placeholder,
|
|
177
|
+
parent_ulid,
|
|
178
|
+
)
|
|
179
|
+
return parent_ulid
|
|
180
|
+
errors.append(
|
|
181
|
+
{
|
|
182
|
+
"change_type": "variable_link",
|
|
183
|
+
"error_code": ErrorCode.VARIABLE_LINK_UNRESOLVED,
|
|
184
|
+
"component_id": created.component_id,
|
|
185
|
+
"config_id": created.config_id,
|
|
186
|
+
"message": (
|
|
187
|
+
f"Cannot resolve variables_id placeholder {vars_placeholder!r}: "
|
|
188
|
+
f"{len(created_variables_ulids)} keboola.variables configs were "
|
|
189
|
+
"created this push and none matched by placeholder. Refusing to "
|
|
190
|
+
"write an ambiguous variables link."
|
|
191
|
+
),
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
return None
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def _resolve_variables_row(
|
|
198
|
+
*,
|
|
199
|
+
created: CreatedConfig,
|
|
200
|
+
parent_ulid: str,
|
|
201
|
+
vals_placeholder: str,
|
|
202
|
+
created_row_id_map: dict[str, str],
|
|
203
|
+
created_rows_by_parent: dict[str, list[str]],
|
|
204
|
+
errors: list[dict[str, str]],
|
|
205
|
+
) -> str | None:
|
|
206
|
+
"""Resolve a transformation's ``variables_values_id`` placeholder.
|
|
207
|
+
|
|
208
|
+
Returns the row ULID, or ``None`` when no values row was created (the link
|
|
209
|
+
is then left unset) or the choice is ambiguous (an error is appended only
|
|
210
|
+
when ``vals_placeholder`` was actually requested).
|
|
211
|
+
"""
|
|
212
|
+
if vals_placeholder:
|
|
213
|
+
mapped = created_row_id_map.get(vals_placeholder)
|
|
214
|
+
if mapped is not None:
|
|
215
|
+
return mapped
|
|
216
|
+
siblings = created_rows_by_parent.get(parent_ulid, [])
|
|
217
|
+
if len(siblings) == 1:
|
|
218
|
+
row_ulid = siblings[0]
|
|
219
|
+
if vals_placeholder:
|
|
220
|
+
logger.warning(
|
|
221
|
+
"Transformation %s/%s variables_values_id placeholder %r did not "
|
|
222
|
+
"match a created row; binding to the single row created under "
|
|
223
|
+
"variables config %s.",
|
|
224
|
+
created.component_id,
|
|
225
|
+
created.config_id,
|
|
226
|
+
vals_placeholder,
|
|
227
|
+
parent_ulid,
|
|
228
|
+
)
|
|
229
|
+
return row_ulid
|
|
230
|
+
if vals_placeholder:
|
|
231
|
+
errors.append(
|
|
232
|
+
{
|
|
233
|
+
"change_type": "variable_link",
|
|
234
|
+
"error_code": ErrorCode.VARIABLE_LINK_UNRESOLVED,
|
|
235
|
+
"component_id": created.component_id,
|
|
236
|
+
"config_id": created.config_id,
|
|
237
|
+
"message": (
|
|
238
|
+
f"Cannot resolve variables_values_id placeholder "
|
|
239
|
+
f"{vals_placeholder!r}: {len(siblings)} rows were created under "
|
|
240
|
+
f"variables config {parent_ulid}. Refusing to write an "
|
|
241
|
+
"ambiguous values link."
|
|
242
|
+
),
|
|
243
|
+
}
|
|
244
|
+
)
|
|
245
|
+
return None
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _apply_variable_binding(
|
|
249
|
+
service: SyncService,
|
|
250
|
+
client: Any,
|
|
251
|
+
*,
|
|
252
|
+
created: CreatedConfig,
|
|
253
|
+
local_data: dict[str, Any],
|
|
254
|
+
parent_ulid: str,
|
|
255
|
+
row_ulid: str | None,
|
|
256
|
+
manifest: Manifest,
|
|
257
|
+
branch_id: int | None,
|
|
258
|
+
) -> None:
|
|
259
|
+
"""PUT the resolved variables link, rewrite local, refresh manifest hashes.
|
|
260
|
+
|
|
261
|
+
``local_data`` is the pristine on-disk ``_config.yml`` dict; a deep copy is
|
|
262
|
+
code-merged to build the full PUT body so blocks/code stay only in their
|
|
263
|
+
companion files. Uses :meth:`KeboolaClient.update_config` (PUT) directly --
|
|
264
|
+
**not** ``set_variables``, which would create a *second* variables config.
|
|
265
|
+
"""
|
|
266
|
+
merged = copy.deepcopy(local_data)
|
|
267
|
+
merge_code_files(created.component_id, merged, created.config_dir)
|
|
268
|
+
_name, _description, configuration = local_config_to_api(merged)
|
|
269
|
+
configuration["variables_id"] = parent_ulid
|
|
270
|
+
if row_ulid:
|
|
271
|
+
configuration["variables_values_id"] = row_ulid
|
|
272
|
+
|
|
273
|
+
client.update_config(
|
|
274
|
+
component_id=created.component_id,
|
|
275
|
+
config_id=created.config_id,
|
|
276
|
+
configuration=configuration,
|
|
277
|
+
change_description="Resolve variables link via kbagent sync push",
|
|
278
|
+
branch_id=branch_id,
|
|
279
|
+
)
|
|
280
|
+
logger.info(
|
|
281
|
+
"Resolved variables link for %s/%s -> variables_id=%s variables_values_id=%s",
|
|
282
|
+
created.component_id,
|
|
283
|
+
created.config_id,
|
|
284
|
+
parent_ulid,
|
|
285
|
+
row_ulid,
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Rewrite the local _configuration_extra to the ULIDs (pristine data:
|
|
289
|
+
# no merged blocks leak into _config.yml).
|
|
290
|
+
extra = local_data.setdefault("_configuration_extra", {})
|
|
291
|
+
extra["variables_id"] = parent_ulid
|
|
292
|
+
if row_ulid:
|
|
293
|
+
extra["variables_values_id"] = row_ulid
|
|
294
|
+
service._write_config_file(created.config_dir, local_data)
|
|
295
|
+
|
|
296
|
+
# config_hash includes _configuration_extra, so refresh the stored
|
|
297
|
+
# hashes from the post-rewrite disk state or sync diff sees a conflict.
|
|
298
|
+
hashes = service._compute_config_hashes(created.config_dir, created.component_id)
|
|
299
|
+
target_branch = branch_id or 0
|
|
300
|
+
for cfg in manifest.configurations:
|
|
301
|
+
if (
|
|
302
|
+
cfg.branch_id == target_branch
|
|
303
|
+
and cfg.component_id == created.component_id
|
|
304
|
+
and cfg.id == created.config_id
|
|
305
|
+
):
|
|
306
|
+
cfg.metadata["pull_hash"] = hashes.file_hash
|
|
307
|
+
cfg.metadata["pull_config_hash"] = hashes.cfg_hash
|
|
308
|
+
cfg.metadata["pull_extra_hashes"] = hashes.extra_hashes
|
|
309
|
+
break
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
# ---------------------------------------------------------------------------
|
|
313
|
+
# Phase D: keboola.flow task configId remap (#426)
|
|
314
|
+
# ---------------------------------------------------------------------------
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def resolve_flow_task_bindings(
|
|
318
|
+
service: SyncService,
|
|
319
|
+
client: Any,
|
|
320
|
+
*,
|
|
321
|
+
created_configs: list[CreatedConfig],
|
|
322
|
+
created_id_map: dict[tuple[str, str], str],
|
|
323
|
+
manifest: Manifest,
|
|
324
|
+
branch_id: int | None,
|
|
325
|
+
) -> FlowBindingResult:
|
|
326
|
+
"""Remap keboola.flow task ``configId``s from source ids to ULIDs (Phase D).
|
|
327
|
+
|
|
328
|
+
A ``keboola.flow`` config runs other configs via
|
|
329
|
+
``configuration.tasks[].task.configId`` (job-type tasks only; on disk these
|
|
330
|
+
live under ``_configuration_extra.tasks``). When a flow is created in the
|
|
331
|
+
same push as the configs it targets -- e.g. a ``sync clone`` of a reference
|
|
332
|
+
project -- those task ``configId``s still point at the source config ids.
|
|
333
|
+
This pass (mirroring the Phase-C variable backfill) resolves each job task's
|
|
334
|
+
``(componentId, configId)`` via ``created_id_map`` to the ULID assigned this
|
|
335
|
+
push, PUTs the corrected flow, rewrites the local ``_config.yml``, and
|
|
336
|
+
refreshes the manifest hashes so a re-push is clean.
|
|
337
|
+
|
|
338
|
+
A no-op when no flow was created this push, or when no task references a
|
|
339
|
+
config created this push (the id is left untouched -- it may legitimately
|
|
340
|
+
point at a pre-existing config).
|
|
341
|
+
"""
|
|
342
|
+
result = FlowBindingResult()
|
|
343
|
+
for created in created_configs:
|
|
344
|
+
if created.component_id != FLOW_COMPONENT_ID:
|
|
345
|
+
continue
|
|
346
|
+
local_data = service._read_config_file(created.config_dir)
|
|
347
|
+
if local_data is None:
|
|
348
|
+
continue
|
|
349
|
+
extra = local_data.get("_configuration_extra")
|
|
350
|
+
if not isinstance(extra, dict):
|
|
351
|
+
continue
|
|
352
|
+
tasks = extra.get("tasks")
|
|
353
|
+
if not isinstance(tasks, list):
|
|
354
|
+
continue
|
|
355
|
+
|
|
356
|
+
remapped = remap_flow_tasks_in_place(tasks, created_id_map)
|
|
357
|
+
if not remapped:
|
|
358
|
+
continue
|
|
359
|
+
|
|
360
|
+
try:
|
|
361
|
+
_apply_flow_task_binding(
|
|
362
|
+
service,
|
|
363
|
+
client,
|
|
364
|
+
created=created,
|
|
365
|
+
local_data=local_data,
|
|
366
|
+
manifest=manifest,
|
|
367
|
+
branch_id=branch_id,
|
|
368
|
+
)
|
|
369
|
+
except KeboolaApiError as exc:
|
|
370
|
+
result.errors.append(
|
|
371
|
+
{
|
|
372
|
+
"change_type": "flow_task_link",
|
|
373
|
+
"error_code": ErrorCode.API_ERROR,
|
|
374
|
+
"component_id": created.component_id,
|
|
375
|
+
"config_id": created.config_id,
|
|
376
|
+
"message": str(exc),
|
|
377
|
+
}
|
|
378
|
+
)
|
|
379
|
+
continue
|
|
380
|
+
result.configs_rewritten += 1
|
|
381
|
+
result.tasks_remapped += remapped
|
|
382
|
+
return result
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def remap_flow_tasks_in_place(tasks: list[Any], created_id_map: dict[tuple[str, str], str]) -> int:
|
|
386
|
+
"""Rewrite job-task ``configId``s in a flow ``tasks`` list in place.
|
|
387
|
+
|
|
388
|
+
Returns the number of task references actually remapped. Only
|
|
389
|
+
``task.type == 'job'`` entries carry a ``configId``; notification and
|
|
390
|
+
variable tasks are skipped. A task is rewritten only when
|
|
391
|
+
``(componentId, configId)`` matches an entry created this push.
|
|
392
|
+
"""
|
|
393
|
+
remapped = 0
|
|
394
|
+
for task_entry in tasks:
|
|
395
|
+
if not isinstance(task_entry, dict):
|
|
396
|
+
continue
|
|
397
|
+
task = task_entry.get("task")
|
|
398
|
+
if not isinstance(task, dict) or task.get("type") != "job":
|
|
399
|
+
continue
|
|
400
|
+
comp = task.get("componentId")
|
|
401
|
+
old_cfg = task.get("configId")
|
|
402
|
+
if not isinstance(comp, str) or not isinstance(old_cfg, (str, int)):
|
|
403
|
+
continue
|
|
404
|
+
new_id = created_id_map.get((comp, str(old_cfg)))
|
|
405
|
+
if new_id and str(old_cfg) != new_id:
|
|
406
|
+
task["configId"] = new_id
|
|
407
|
+
remapped += 1
|
|
408
|
+
return remapped
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def _apply_flow_task_binding(
|
|
412
|
+
service: SyncService,
|
|
413
|
+
client: Any,
|
|
414
|
+
*,
|
|
415
|
+
created: CreatedConfig,
|
|
416
|
+
local_data: dict[str, Any],
|
|
417
|
+
manifest: Manifest,
|
|
418
|
+
branch_id: int | None,
|
|
419
|
+
) -> None:
|
|
420
|
+
"""PUT a remapped flow, rewrite local ``_config.yml``, refresh hashes.
|
|
421
|
+
|
|
422
|
+
``local_data`` already carries the remapped task ``configId``s (the caller
|
|
423
|
+
mutated ``_configuration_extra.tasks`` in place). A deep copy is code-merged
|
|
424
|
+
to build the PUT body (no-op for flows, which carry no code) so the API
|
|
425
|
+
receives the corrected ``configuration.tasks``.
|
|
426
|
+
"""
|
|
427
|
+
merged = copy.deepcopy(local_data)
|
|
428
|
+
merge_code_files(created.component_id, merged, created.config_dir)
|
|
429
|
+
_name, _description, configuration = local_config_to_api(merged)
|
|
430
|
+
|
|
431
|
+
client.update_config(
|
|
432
|
+
component_id=created.component_id,
|
|
433
|
+
config_id=created.config_id,
|
|
434
|
+
configuration=configuration,
|
|
435
|
+
change_description="Remap flow task configIds via kbagent sync push",
|
|
436
|
+
branch_id=branch_id,
|
|
437
|
+
)
|
|
438
|
+
logger.info(
|
|
439
|
+
"Remapped flow task configIds for %s/%s",
|
|
440
|
+
created.component_id,
|
|
441
|
+
created.config_id,
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
service._write_config_file(created.config_dir, local_data)
|
|
445
|
+
hashes = service._compute_config_hashes(created.config_dir, created.component_id)
|
|
446
|
+
target_branch = branch_id or 0
|
|
447
|
+
for cfg in manifest.configurations:
|
|
448
|
+
if (
|
|
449
|
+
cfg.branch_id == target_branch
|
|
450
|
+
and cfg.component_id == created.component_id
|
|
451
|
+
and cfg.id == created.config_id
|
|
452
|
+
):
|
|
453
|
+
cfg.metadata["pull_hash"] = hashes.file_hash
|
|
454
|
+
cfg.metadata["pull_config_hash"] = hashes.cfg_hash
|
|
455
|
+
cfg.metadata["pull_extra_hashes"] = hashes.extra_hashes
|
|
456
|
+
break
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"""Git-branch <-> Keboola-dev-branch linking (from sync_service.py).
|
|
2
|
+
|
|
3
|
+
Backs ``kbagent sync branch-link / branch-unlink / branch-status`` in
|
|
4
|
+
git-branching mode: maps the current git branch to a Keboola dev branch in
|
|
5
|
+
``.keboola/branch-mapping.json``. ``branch_link`` needs the ``SyncService`` (to
|
|
6
|
+
resolve the project + build a client); the read/unlink helpers are pure.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import TYPE_CHECKING, Any
|
|
13
|
+
|
|
14
|
+
from ..errors import ConfigError
|
|
15
|
+
from ..sync.branch_mapping import BranchMapping, load_branch_mapping, save_branch_mapping
|
|
16
|
+
from ..sync.manifest import load_manifest
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from .sync_service import SyncService
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def branch_link(
|
|
23
|
+
service: SyncService,
|
|
24
|
+
alias: str,
|
|
25
|
+
project_root: Path,
|
|
26
|
+
branch_id: int | None = None,
|
|
27
|
+
branch_name: str | None = None,
|
|
28
|
+
) -> dict[str, Any]:
|
|
29
|
+
"""Link the current git branch to a Keboola development branch.
|
|
30
|
+
|
|
31
|
+
If no ``branch_id`` or ``branch_name`` is given: read the current git branch,
|
|
32
|
+
search for an existing Keboola branch with the same name, create one if
|
|
33
|
+
absent, and save the mapping. Returns a dict with the link result.
|
|
34
|
+
"""
|
|
35
|
+
from ..sync.git_utils import get_current_branch
|
|
36
|
+
|
|
37
|
+
manifest = load_manifest(project_root)
|
|
38
|
+
if not manifest.git_branching.enabled:
|
|
39
|
+
raise ConfigError(
|
|
40
|
+
"Git-branching mode is not enabled. Run 'sync init --git-branching' first."
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
git_branch = get_current_branch(project_root)
|
|
44
|
+
if git_branch is None:
|
|
45
|
+
raise ConfigError("Cannot determine current git branch.")
|
|
46
|
+
|
|
47
|
+
default_branch = manifest.git_branching.default_branch
|
|
48
|
+
if git_branch == default_branch:
|
|
49
|
+
raise ConfigError(
|
|
50
|
+
f"Cannot link the default branch '{default_branch}'. "
|
|
51
|
+
"It is automatically linked to Keboola production."
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Load existing mapping
|
|
55
|
+
try:
|
|
56
|
+
mapping = load_branch_mapping(project_root)
|
|
57
|
+
except FileNotFoundError:
|
|
58
|
+
mapping = BranchMapping()
|
|
59
|
+
mapping.set(default_branch, None, "Main")
|
|
60
|
+
|
|
61
|
+
# Check if already linked
|
|
62
|
+
existing = mapping.get(git_branch)
|
|
63
|
+
if existing is not None:
|
|
64
|
+
return {
|
|
65
|
+
"status": "already_linked",
|
|
66
|
+
"git_branch": git_branch,
|
|
67
|
+
"keboola_branch_id": existing.keboola_id,
|
|
68
|
+
"keboola_branch_name": existing.name,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
projects = service.resolve_projects([alias])
|
|
72
|
+
project = projects[alias]
|
|
73
|
+
client = service._client_factory(project.stack_url, project.token)
|
|
74
|
+
|
|
75
|
+
with client:
|
|
76
|
+
if branch_id:
|
|
77
|
+
# Link to existing branch by ID
|
|
78
|
+
branches = client.list_dev_branches()
|
|
79
|
+
branch_info = next((b for b in branches if b["id"] == branch_id), None)
|
|
80
|
+
if branch_info is None:
|
|
81
|
+
raise ConfigError(f"Keboola branch {branch_id} not found.")
|
|
82
|
+
kbc_branch_id = int(branch_info["id"])
|
|
83
|
+
kbc_branch_name = branch_info.get("name", "")
|
|
84
|
+
elif branch_name:
|
|
85
|
+
# Search by name or create
|
|
86
|
+
branches = client.list_dev_branches()
|
|
87
|
+
branch_info = next((b for b in branches if b.get("name") == branch_name), None)
|
|
88
|
+
if branch_info:
|
|
89
|
+
kbc_branch_id = int(branch_info["id"])
|
|
90
|
+
kbc_branch_name = branch_info.get("name", "")
|
|
91
|
+
else:
|
|
92
|
+
result = client.create_dev_branch(name=branch_name)
|
|
93
|
+
kbc_branch_id = int(result["id"])
|
|
94
|
+
kbc_branch_name = branch_name
|
|
95
|
+
else:
|
|
96
|
+
# Default: use git branch name to search/create
|
|
97
|
+
branches = client.list_dev_branches()
|
|
98
|
+
branch_info = next((b for b in branches if b.get("name") == git_branch), None)
|
|
99
|
+
if branch_info:
|
|
100
|
+
kbc_branch_id = int(branch_info["id"])
|
|
101
|
+
kbc_branch_name = branch_info.get("name", "")
|
|
102
|
+
else:
|
|
103
|
+
result = client.create_dev_branch(name=git_branch)
|
|
104
|
+
kbc_branch_id = int(result["id"])
|
|
105
|
+
kbc_branch_name = git_branch
|
|
106
|
+
|
|
107
|
+
mapping.set(git_branch, kbc_branch_id, kbc_branch_name)
|
|
108
|
+
save_branch_mapping(project_root, mapping)
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
"status": "linked",
|
|
112
|
+
"git_branch": git_branch,
|
|
113
|
+
"keboola_branch_id": kbc_branch_id,
|
|
114
|
+
"keboola_branch_name": kbc_branch_name,
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def branch_unlink(project_root: Path) -> dict[str, Any]:
|
|
119
|
+
"""Remove the branch mapping for the current git branch."""
|
|
120
|
+
from ..sync.git_utils import get_current_branch
|
|
121
|
+
|
|
122
|
+
manifest = load_manifest(project_root)
|
|
123
|
+
if not manifest.git_branching.enabled:
|
|
124
|
+
raise ConfigError("Git-branching mode is not enabled.")
|
|
125
|
+
|
|
126
|
+
git_branch = get_current_branch(project_root)
|
|
127
|
+
if git_branch is None:
|
|
128
|
+
raise ConfigError("Cannot determine current git branch.")
|
|
129
|
+
|
|
130
|
+
default_branch = manifest.git_branching.default_branch
|
|
131
|
+
if git_branch == default_branch:
|
|
132
|
+
raise ConfigError(
|
|
133
|
+
f"Cannot unlink the default branch '{default_branch}'. "
|
|
134
|
+
"It is permanently linked to Keboola production."
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
mapping = load_branch_mapping(project_root)
|
|
138
|
+
existing = mapping.get(git_branch)
|
|
139
|
+
if existing is None:
|
|
140
|
+
return {
|
|
141
|
+
"status": "not_linked",
|
|
142
|
+
"git_branch": git_branch,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
kbc_id = existing.keboola_id
|
|
146
|
+
kbc_name = existing.name
|
|
147
|
+
mapping.remove(git_branch)
|
|
148
|
+
save_branch_mapping(project_root, mapping)
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
"status": "unlinked",
|
|
152
|
+
"git_branch": git_branch,
|
|
153
|
+
"keboola_branch_id": kbc_id,
|
|
154
|
+
"keboola_branch_name": kbc_name,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def branch_status(project_root: Path) -> dict[str, Any]:
|
|
159
|
+
"""Show the branch mapping status for the current git branch."""
|
|
160
|
+
from ..sync.git_utils import get_current_branch
|
|
161
|
+
|
|
162
|
+
manifest = load_manifest(project_root)
|
|
163
|
+
if not manifest.git_branching.enabled:
|
|
164
|
+
return {"git_branching": False}
|
|
165
|
+
|
|
166
|
+
git_branch = get_current_branch(project_root)
|
|
167
|
+
try:
|
|
168
|
+
mapping = load_branch_mapping(project_root)
|
|
169
|
+
except FileNotFoundError:
|
|
170
|
+
return {
|
|
171
|
+
"git_branching": True,
|
|
172
|
+
"git_branch": git_branch,
|
|
173
|
+
"linked": False,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
entry = mapping.get(git_branch) if git_branch else None
|
|
177
|
+
if entry is None:
|
|
178
|
+
return {
|
|
179
|
+
"git_branching": True,
|
|
180
|
+
"git_branch": git_branch,
|
|
181
|
+
"linked": False,
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
"git_branching": True,
|
|
186
|
+
"git_branch": git_branch,
|
|
187
|
+
"linked": True,
|
|
188
|
+
"keboola_branch_id": entry.keboola_id,
|
|
189
|
+
"keboola_branch_name": entry.name,
|
|
190
|
+
"is_production": entry.is_production(),
|
|
191
|
+
}
|