@dataif/cli 0.1.0

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 (183) hide show
  1. package/README.md +16 -0
  2. package/bin/dataif.js +623 -0
  3. package/package.json +26 -0
  4. package/scripts/build-template.mjs +72 -0
  5. package/templates/dataif/README.md +157 -0
  6. package/templates/dataif/infra/.env.example +119 -0
  7. package/templates/dataif/infra/.env.stg.example +119 -0
  8. package/templates/dataif/infra/airflow/Dockerfile +11 -0
  9. package/templates/dataif/infra/airflow/Dockerfile.release +17 -0
  10. package/templates/dataif/infra/airflow/requirements.txt +3 -0
  11. package/templates/dataif/infra/docker-compose.yml +306 -0
  12. package/templates/dataif/infra/init-db/01-init-dataif.sh +129 -0
  13. package/templates/dataif/infra/init-db/pnp-curated-views.sqlinc +444 -0
  14. package/templates/dataif/infra/init-db/pnp-raw-staging-curated.sqlinc +701 -0
  15. package/templates/dataif/infra/keycloak/Dockerfile +4 -0
  16. package/templates/dataif/infra/keycloak/realm-dataif.json +73 -0
  17. package/templates/dataif/infra/ollama/Dockerfile +9 -0
  18. package/templates/dataif/infra/ollama/bootstrap-model.sh +100 -0
  19. package/templates/dataif/infra/ollama/sabia-7b.Modelfile +14 -0
  20. package/templates/dataif/infra/postgres/Dockerfile +4 -0
  21. package/templates/dataif/pipelines/airflow/dags/generated/.gitkeep +1 -0
  22. package/templates/dataif/pipelines/airflow/dags/generated/2020_financeiro_fcc6f1f3_sync.py +9 -0
  23. package/templates/dataif/pipelines/dataif_pipelines/__init__.py +1 -0
  24. package/templates/dataif/pipelines/dataif_pipelines/airflow/__init__.py +1 -0
  25. package/templates/dataif/pipelines/dataif_pipelines/airflow/pnp_pipeline_factory.py +167 -0
  26. package/templates/dataif/pipelines/dataif_pipelines/connectors/__init__.py +1 -0
  27. package/templates/dataif/pipelines/dataif_pipelines/connectors/base/__init__.py +1 -0
  28. package/templates/dataif/pipelines/dataif_pipelines/connectors/base/connector.py +28 -0
  29. package/templates/dataif/pipelines/dataif_pipelines/connectors/base/types.py +14 -0
  30. package/templates/dataif/pipelines/dataif_pipelines/connectors/nilo_pecanha/__init__.py +1 -0
  31. package/templates/dataif/pipelines/dataif_pipelines/connectors/nilo_pecanha/config.py +19 -0
  32. package/templates/dataif/pipelines/dataif_pipelines/connectors/nilo_pecanha/connector.py +558 -0
  33. package/templates/dataif/pipelines/dataif_pipelines/connectors/nilo_pecanha/powerbi_microdados.py +728 -0
  34. package/templates/dataif/pipelines/dataif_pipelines/connectors/nilo_pecanha/transform.py +296 -0
  35. package/templates/dataif/pipelines/dataif_pipelines/jobs/__init__.py +1 -0
  36. package/templates/dataif/pipelines/dataif_pipelines/jobs/nilo_pipeline.py +112 -0
  37. package/templates/dataif/pipelines/dataif_pipelines/orchestration/__init__.py +21 -0
  38. package/templates/dataif/pipelines/dataif_pipelines/orchestration/pnp_workflow.py +783 -0
  39. package/templates/dataif/pipelines/dataif_pipelines/repositories/__init__.py +1 -0
  40. package/templates/dataif/pipelines/dataif_pipelines/repositories/pnp_raw_repository.py +860 -0
  41. package/templates/dataif/pipelines/dataif_pipelines/services/__init__.py +19 -0
  42. package/templates/dataif/pipelines/dataif_pipelines/services/pnp_curated_service.py +66 -0
  43. package/templates/dataif/pipelines/dataif_pipelines/services/pnp_download_service.py +534 -0
  44. package/templates/dataif/pipelines/dataif_pipelines/services/pnp_quality_service.py +9 -0
  45. package/templates/dataif/pipelines/dataif_pipelines/services/pnp_raw_ingestion_service.py +124 -0
  46. package/templates/dataif/pipelines/dataif_pipelines/services/pnp_staging_service.py +271 -0
  47. package/templates/dataif/pipelines/dataif_pipelines/services/powerbi_catalog_service.py +159 -0
  48. package/templates/dataif/pipelines/sql/staging/020_pnp_matriculas.sql +112 -0
  49. package/templates/dataif/pipelines/sql/staging/030_pnp_eficiencia_academica.sql +83 -0
  50. package/templates/dataif/pipelines/sql/staging/040_pnp_servidores.sql +90 -0
  51. package/templates/dataif/pipelines/sql/staging/050_pnp_financeiro.sql +72 -0
  52. package/templates/dataif/pipelines/sql/views_curated/004_mv_pnp_dashboard_fast.sql +204 -0
  53. package/templates/dataif/pipelines/sql/views_curated/010_vw_pnp_admin_ingestao.sql +51 -0
  54. package/templates/dataif/pipelines/sql/views_curated/020_vw_pnp_qualidade_dados.sql +114 -0
  55. package/templates/dataif/pipelines/sql/views_curated/030_vw_pnp_matriculas.sql +67 -0
  56. package/templates/dataif/pipelines/sql/views_curated/040_vw_pnp_eficiencia.sql +33 -0
  57. package/templates/dataif/pipelines/sql/views_curated/050_vw_pnp_servidores.sql +30 -0
  58. package/templates/dataif/pipelines/sql/views_curated/060_vw_pnp_financeiro.sql +22 -0
  59. package/templates/dataif/pipelines/sql/views_curated/070_vw_pnp_vanna.sql +115 -0
  60. package/templates/dataif/scripts/configure-env.sh +149 -0
  61. package/templates/dataif/scripts/create_metabase_pnp_dashboard.py +943 -0
  62. package/templates/dataif/scripts/create_metabase_pnp_matriculas_dashboard.py +580 -0
  63. package/templates/dataif/scripts/deploy.sh +79 -0
  64. package/templates/dataif/scripts/fix_metabase_template_tag_ids.py +91 -0
  65. package/templates/dataif/scripts/pnp_powerbi_microdados_probe.py +14 -0
  66. package/templates/dataif/scripts/pnp_validate_raw_run.py +330 -0
  67. package/templates/dataif/scripts/publish-images.sh +31 -0
  68. package/templates/dataif/scripts/sync_metabase_dashboard_field_filters.py +241 -0
  69. package/templates/dataif/scripts/use-vanna-ollama.sh +139 -0
  70. package/templates/dataif/services/api/.dockerignore +18 -0
  71. package/templates/dataif/services/api/Dockerfile +12 -0
  72. package/templates/dataif/services/api/app/__init__.py +1 -0
  73. package/templates/dataif/services/api/app/auth.py +48 -0
  74. package/templates/dataif/services/api/app/config.py +59 -0
  75. package/templates/dataif/services/api/app/keycloak_admin.py +215 -0
  76. package/templates/dataif/services/api/app/main.py +2432 -0
  77. package/templates/dataif/services/api/app/metabase_admin.py +191 -0
  78. package/templates/dataif/services/api/app/metabase_bootstrap.py +44 -0
  79. package/templates/dataif/services/api/app/metabase_embed.py +15 -0
  80. package/templates/dataif/services/api/app/pnp_dag_provisioner.py +113 -0
  81. package/templates/dataif/services/api/app/pnp_instance_repository.py +951 -0
  82. package/templates/dataif/services/api/app/pnp_powerbi.py +438 -0
  83. package/templates/dataif/services/api/app/vanna_client.py +32 -0
  84. package/templates/dataif/services/api/requirements.txt +9 -0
  85. package/templates/dataif/services/vanna/.dockerignore +18 -0
  86. package/templates/dataif/services/vanna/Dockerfile +12 -0
  87. package/templates/dataif/services/vanna/app/config.py +57 -0
  88. package/templates/dataif/services/vanna/app/main.py +108 -0
  89. package/templates/dataif/services/vanna/app/runtime_config.py +114 -0
  90. package/templates/dataif/services/vanna/app/sql_guard.py +123 -0
  91. package/templates/dataif/services/vanna/app/vanna_engine.py +382 -0
  92. package/templates/dataif/services/vanna/requirements.txt +8 -0
  93. package/templates/dataif/services/web/.dockerignore +13 -0
  94. package/templates/dataif/services/web/Dockerfile +16 -0
  95. package/templates/dataif/services/web/index.html +12 -0
  96. package/templates/dataif/services/web/nginx.conf +74 -0
  97. package/templates/dataif/services/web/package-lock.json +4397 -0
  98. package/templates/dataif/services/web/package.json +32 -0
  99. package/templates/dataif/services/web/postcss.config.mjs +5 -0
  100. package/templates/dataif/services/web/src/App.jsx +2817 -0
  101. package/templates/dataif/services/web/src/adminAuth.js +245 -0
  102. package/templates/dataif/services/web/src/assets/avatar_placeholder.png +0 -0
  103. package/templates/dataif/services/web/src/assets/github_logo_icon_229278.svg +1 -0
  104. package/templates/dataif/services/web/src/assets/if-logo.png +0 -0
  105. package/templates/dataif/services/web/src/assets/if.svg +0 -0
  106. package/templates/dataif/services/web/src/assets/pnp-horizontal.svg +1 -0
  107. package/templates/dataif/services/web/src/components/AppHeader.jsx +233 -0
  108. package/templates/dataif/services/web/src/components/application/app-navigation/base-components/mobile-header.tsx +56 -0
  109. package/templates/dataif/services/web/src/components/application/app-navigation/base-components/nav-account-card.tsx +209 -0
  110. package/templates/dataif/services/web/src/components/application/app-navigation/base-components/nav-item-button.tsx +67 -0
  111. package/templates/dataif/services/web/src/components/application/app-navigation/base-components/nav-item.tsx +108 -0
  112. package/templates/dataif/services/web/src/components/application/app-navigation/base-components/nav-list.tsx +83 -0
  113. package/templates/dataif/services/web/src/components/application/app-navigation/config.ts +23 -0
  114. package/templates/dataif/services/web/src/components/application/app-navigation/header-navigation.tsx +240 -0
  115. package/templates/dataif/services/web/src/components/application/pagination/pagination-base.tsx +376 -0
  116. package/templates/dataif/services/web/src/components/application/pagination/pagination-dot.tsx +52 -0
  117. package/templates/dataif/services/web/src/components/application/pagination/pagination-line.tsx +48 -0
  118. package/templates/dataif/services/web/src/components/application/pagination/pagination.tsx +328 -0
  119. package/templates/dataif/services/web/src/components/application/tabs/tabs.tsx +223 -0
  120. package/templates/dataif/services/web/src/components/base/avatar/avatar-label-group.tsx +28 -0
  121. package/templates/dataif/services/web/src/components/base/avatar/avatar.tsx +129 -0
  122. package/templates/dataif/services/web/src/components/base/avatar/base-components/avatar-add-button.tsx +32 -0
  123. package/templates/dataif/services/web/src/components/base/avatar/base-components/avatar-company-icon.tsx +24 -0
  124. package/templates/dataif/services/web/src/components/base/avatar/base-components/avatar-online-indicator.tsx +29 -0
  125. package/templates/dataif/services/web/src/components/base/avatar/base-components/index.tsx +4 -0
  126. package/templates/dataif/services/web/src/components/base/avatar/base-components/verified-tick.tsx +32 -0
  127. package/templates/dataif/services/web/src/components/base/badges/badge-types.ts +264 -0
  128. package/templates/dataif/services/web/src/components/base/badges/badges.tsx +415 -0
  129. package/templates/dataif/services/web/src/components/base/button-group/button-group.tsx +104 -0
  130. package/templates/dataif/services/web/src/components/base/buttons/button.tsx +267 -0
  131. package/templates/dataif/services/web/src/components/base/input/hint-text.tsx +31 -0
  132. package/templates/dataif/services/web/src/components/base/input/input.tsx +269 -0
  133. package/templates/dataif/services/web/src/components/base/input/label.tsx +48 -0
  134. package/templates/dataif/services/web/src/components/base/radio-buttons/radio-buttons.tsx +127 -0
  135. package/templates/dataif/services/web/src/components/base/select/combobox.tsx +150 -0
  136. package/templates/dataif/services/web/src/components/base/select/multi-select.tsx +361 -0
  137. package/templates/dataif/services/web/src/components/base/select/popover.tsx +32 -0
  138. package/templates/dataif/services/web/src/components/base/select/select-item.tsx +95 -0
  139. package/templates/dataif/services/web/src/components/base/select/select-native.tsx +67 -0
  140. package/templates/dataif/services/web/src/components/base/select/select.tsx +144 -0
  141. package/templates/dataif/services/web/src/components/base/tags/base-components/tag-close-x.tsx +32 -0
  142. package/templates/dataif/services/web/src/components/base/tooltip/tooltip.tsx +107 -0
  143. package/templates/dataif/services/web/src/components/foundations/dot-icon.tsx +22 -0
  144. package/templates/dataif/services/web/src/components/foundations/logo/untitledui-logo-minimal.tsx +170 -0
  145. package/templates/dataif/services/web/src/components/foundations/logo/untitledui-logo.tsx +58 -0
  146. package/templates/dataif/services/web/src/hooks/use-breakpoint.ts +34 -0
  147. package/templates/dataif/services/web/src/hooks/use-resize-observer.ts +67 -0
  148. package/templates/dataif/services/web/src/main.jsx +14 -0
  149. package/templates/dataif/services/web/src/providers/theme-provider.jsx +62 -0
  150. package/templates/dataif/services/web/src/styles/globals.css +60 -0
  151. package/templates/dataif/services/web/src/styles/theme.css +1326 -0
  152. package/templates/dataif/services/web/src/styles/typography.css +430 -0
  153. package/templates/dataif/services/web/src/styles.css +1287 -0
  154. package/templates/dataif/services/web/src/utils/cx.ts +24 -0
  155. package/templates/dataif/services/web/src/utils/is-react-component.ts +33 -0
  156. package/templates/dataif/services/web/vite.config.js +14 -0
  157. package/templates/dataif/sql/ddl/001_schemas.sql +6 -0
  158. package/templates/dataif/sql/ddl/003_pnp_raw_staging_curated.sql +699 -0
  159. package/templates/dataif/sql/migrations/001_pnp_phase1_backfill.sql +3 -0
  160. package/templates/dataif/sql/migrations/002_pnp_phase2_admin_config_backfill.sql +184 -0
  161. package/templates/dataif/sql/migrations/003_pnp_phase3_raw_tabular_backfill.sql +3 -0
  162. package/templates/dataif/sql/migrations/004_pnp_phase3_raw_backfill_support_index.sql +3 -0
  163. package/templates/dataif/sql/migrations/005_pnp_phase7_staging_support_indexes.sql +2 -0
  164. package/templates/dataif/sql/migrations/006_pnp_phase7_staging_autovacuum_tuning.sql +2 -0
  165. package/templates/dataif/sql/migrations/007_pnp_phase7b_run_packages.sql +20 -0
  166. package/templates/dataif/sql/migrations/008_pnp_phase7a_pipeline_endpoints.sql +169 -0
  167. package/templates/dataif/sql/migrations/009_pnp_phase8_curated.sql +35 -0
  168. package/templates/dataif/sql/migrations/010_pnp_phase10_staging_incremental_upsert.sql +3 -0
  169. package/templates/dataif/sql/migrations/010_pnp_pipeline_uuid.sql +51 -0
  170. package/templates/dataif/sql/migrations/011_app_settings.sql +7 -0
  171. package/templates/dataif/sql/staging/020_pnp_matriculas.sql +112 -0
  172. package/templates/dataif/sql/staging/030_pnp_eficiencia_academica.sql +83 -0
  173. package/templates/dataif/sql/staging/040_pnp_servidores.sql +90 -0
  174. package/templates/dataif/sql/staging/050_pnp_financeiro.sql +72 -0
  175. package/templates/dataif/sql/views_curated/003_vw_pnp_microdados_admin.sql +160 -0
  176. package/templates/dataif/sql/views_curated/004_mv_pnp_dashboard_fast.sql +204 -0
  177. package/templates/dataif/sql/views_curated/010_vw_pnp_admin_ingestao.sql +51 -0
  178. package/templates/dataif/sql/views_curated/020_vw_pnp_qualidade_dados.sql +114 -0
  179. package/templates/dataif/sql/views_curated/030_vw_pnp_matriculas.sql +67 -0
  180. package/templates/dataif/sql/views_curated/040_vw_pnp_eficiencia.sql +33 -0
  181. package/templates/dataif/sql/views_curated/050_vw_pnp_servidores.sql +30 -0
  182. package/templates/dataif/sql/views_curated/060_vw_pnp_financeiro.sql +22 -0
  183. package/templates/dataif/sql/views_curated/070_vw_pnp_vanna.sql +115 -0
@@ -0,0 +1,306 @@
1
+ x-airflow-common:
2
+ &airflow-common
3
+ build:
4
+ context: ./airflow
5
+ dockerfile: Dockerfile
6
+ env_file:
7
+ - .env
8
+ environment:
9
+ AIRFLOW__CORE__EXECUTOR: LocalExecutor
10
+ AIRFLOW__CORE__PARALLELISM: ${AIRFLOW_PARALLELISM:-1}
11
+ AIRFLOW__CORE__MAX_ACTIVE_TASKS_PER_DAG: ${AIRFLOW_MAX_ACTIVE_TASKS_PER_DAG:-1}
12
+ AIRFLOW__CORE__MAX_ACTIVE_RUNS_PER_DAG: ${AIRFLOW_MAX_ACTIVE_RUNS_PER_DAG:-1}
13
+ AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: postgresql+psycopg2://${AIRFLOW_DB_USER}:${AIRFLOW_DB_PASSWORD}@postgres:5432/${AIRFLOW_DB_NAME}
14
+ AIRFLOW__CORE__LOAD_EXAMPLES: "False"
15
+ AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: "False"
16
+ AIRFLOW__API__AUTH_BACKENDS: airflow.api.auth.backend.basic_auth
17
+ AIRFLOW__SCHEDULER__PARSING_PROCESSES: ${AIRFLOW_PARSING_PROCESSES:-1}
18
+ AIRFLOW__SCHEDULER__MAX_TIS_PER_QUERY: ${AIRFLOW_MAX_TIS_PER_QUERY:-1}
19
+ AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL: ${AIRFLOW_DAG_DIR_LIST_INTERVAL:-5}
20
+ AIRFLOW__SCHEDULER__MIN_FILE_PROCESS_INTERVAL: ${AIRFLOW_MIN_FILE_PROCESS_INTERVAL:-5}
21
+ AIRFLOW__WEBSERVER__RBAC: "True"
22
+ AIRFLOW__WEBSERVER__DEFAULT_UI_TIMEZONE: UTC
23
+ AIRFLOW__WEBSERVER__BASE_URL: http://localhost:${WEB_PORT}/airflow
24
+ AIRFLOW__WEBSERVER__ENABLE_PROXY_FIX: "True"
25
+ AIRFLOW_UID: ${AIRFLOW_UID}
26
+ PYTHONPATH: /opt/airflow/pipelines
27
+ WAREHOUSE_DSN: postgresql://${DATAIF_ETL_USER}:${DATAIF_ETL_PASSWORD}@postgres:5432/${DATAIF_DB_NAME}
28
+ NILO_PECANHA_ENDPOINT: ${NILO_PECANHA_ENDPOINT}
29
+ NILO_TIMEOUT_SECONDS: ${NILO_TIMEOUT_SECONDS}
30
+ volumes:
31
+ - ../pipelines/airflow/dags:/opt/airflow/dags
32
+ - ../pipelines/dataif_pipelines:/opt/airflow/pipelines/dataif_pipelines
33
+ - ../pipelines/sql:/opt/airflow/pipelines/sql
34
+ - airflow_logs:/opt/airflow/logs
35
+ mem_limit: ${AIRFLOW_MEM_LIMIT:-1024m}
36
+ depends_on:
37
+ postgres:
38
+ condition: service_healthy
39
+
40
+ services:
41
+ postgres:
42
+ image: postgres:16-alpine
43
+ env_file:
44
+ - .env
45
+ environment:
46
+ POSTGRES_USER: ${POSTGRES_SUPERUSER}
47
+ POSTGRES_PASSWORD: ${POSTGRES_SUPERUSER_PASSWORD}
48
+ POSTGRES_DB: postgres
49
+ DATAIF_DB_NAME: ${DATAIF_DB_NAME}
50
+ AIRFLOW_DB_NAME: ${AIRFLOW_DB_NAME}
51
+ METABASE_APP_DB_NAME: ${METABASE_APP_DB_NAME}
52
+ DATAIF_ETL_USER: ${DATAIF_ETL_USER}
53
+ DATAIF_ETL_PASSWORD: ${DATAIF_ETL_PASSWORD}
54
+ DATAIF_METABASE_USER: ${DATAIF_METABASE_USER}
55
+ DATAIF_METABASE_PASSWORD: ${DATAIF_METABASE_PASSWORD}
56
+ DATAIF_VANNA_USER: ${DATAIF_VANNA_USER}
57
+ DATAIF_VANNA_PASSWORD: ${DATAIF_VANNA_PASSWORD}
58
+ AIRFLOW_DB_USER: ${AIRFLOW_DB_USER}
59
+ AIRFLOW_DB_PASSWORD: ${AIRFLOW_DB_PASSWORD}
60
+ METABASE_APP_DB_USER: ${METABASE_APP_DB_USER}
61
+ METABASE_APP_DB_PASSWORD: ${METABASE_APP_DB_PASSWORD}
62
+ ports:
63
+ - "${POSTGRES_EXPOSE_PORT:-5433}:5432"
64
+ volumes:
65
+ - postgres_data:/var/lib/postgresql/data
66
+ - ./init-db:/docker-entrypoint-initdb.d:ro
67
+ mem_limit: ${POSTGRES_MEM_LIMIT:-1024m}
68
+ healthcheck:
69
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_SUPERUSER} -d postgres"]
70
+ interval: 10s
71
+ timeout: 5s
72
+ retries: 10
73
+
74
+ airflow-init:
75
+ <<: *airflow-common
76
+ mem_limit: ${AIRFLOW_INIT_MEM_LIMIT:-768m}
77
+ command: >
78
+ bash -c "
79
+ airflow db migrate &&
80
+ (airflow users create
81
+ --username ${AIRFLOW_ADMIN_USER}
82
+ --password ${AIRFLOW_ADMIN_PASSWORD}
83
+ --firstname Airflow
84
+ --lastname Admin
85
+ --role Admin
86
+ --email ${AIRFLOW_ADMIN_EMAIL} || true)
87
+ "
88
+ restart: "no"
89
+
90
+ airflow-webserver:
91
+ <<: *airflow-common
92
+ command: webserver
93
+ ports:
94
+ - "${AIRFLOW_PORT}:8080"
95
+ depends_on:
96
+ airflow-init:
97
+ condition: service_completed_successfully
98
+
99
+ airflow-scheduler:
100
+ <<: *airflow-common
101
+ command: scheduler
102
+ depends_on:
103
+ airflow-init:
104
+ condition: service_completed_successfully
105
+
106
+ metabase:
107
+ image: metabase/metabase:${METABASE_IMAGE_TAG:-v0.60.1}
108
+ env_file:
109
+ - .env
110
+ environment:
111
+ MB_DB_TYPE: postgres
112
+ MB_DB_HOST: postgres
113
+ MB_DB_PORT: 5432
114
+ MB_DB_DBNAME: ${METABASE_APP_DB_NAME}
115
+ MB_DB_USER: ${METABASE_APP_DB_USER}
116
+ MB_DB_PASS: ${METABASE_APP_DB_PASSWORD}
117
+ MB_SITE_URL: ${METABASE_SITE_URL}
118
+ MB_EMBEDDING_SECRET_KEY: ${METABASE_EMBED_SECRET}
119
+ JAVA_TIMEZONE: UTC
120
+ ports:
121
+ - "${METABASE_PORT}:3000"
122
+ volumes:
123
+ - metabase_data:/metabase-data
124
+ mem_limit: ${METABASE_MEM_LIMIT:-1536m}
125
+ depends_on:
126
+ postgres:
127
+ condition: service_healthy
128
+ healthcheck:
129
+ test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/health || exit 1"]
130
+ interval: 20s
131
+ timeout: 10s
132
+ retries: 12
133
+
134
+ metabase-bootstrap:
135
+ build:
136
+ context: ../services/api
137
+ dockerfile: Dockerfile
138
+ env_file:
139
+ - .env
140
+ environment:
141
+ METABASE_API_URL: ${METABASE_API_URL:-http://metabase:3000}
142
+ METABASE_ADMIN_EMAIL: ${METABASE_ADMIN_EMAIL:-admin@dataif.local}
143
+ METABASE_ADMIN_PASSWORD: ${METABASE_ADMIN_PASSWORD:-admin}
144
+ METABASE_ADMIN_FIRST_NAME: ${METABASE_ADMIN_FIRST_NAME:-DataIF}
145
+ METABASE_ADMIN_LAST_NAME: ${METABASE_ADMIN_LAST_NAME:-Metabase}
146
+ METABASE_SITE_NAME: ${METABASE_SITE_NAME:-dataif}
147
+ METABASE_ALLOW_TRACKING: ${METABASE_ALLOW_TRACKING:-false}
148
+ NILO_TIMEOUT_SECONDS: ${NILO_TIMEOUT_SECONDS}
149
+ command: ["python", "-m", "app.metabase_bootstrap"]
150
+ depends_on:
151
+ metabase:
152
+ condition: service_healthy
153
+ restart: "no"
154
+
155
+ keycloak:
156
+ image: quay.io/keycloak/keycloak:26.2
157
+ env_file:
158
+ - .env
159
+ environment:
160
+ KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
161
+ KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
162
+ command: ["start-dev", "--import-realm"]
163
+ ports:
164
+ - "${KEYCLOAK_PORT}:8080"
165
+ volumes:
166
+ - ./keycloak/realm-dataif.json:/opt/keycloak/data/import/realm-dataif.json:ro
167
+ mem_limit: ${KEYCLOAK_MEM_LIMIT:-1024m}
168
+
169
+ vanna:
170
+ build:
171
+ context: ../services/vanna
172
+ dockerfile: Dockerfile
173
+ env_file:
174
+ - .env
175
+ environment:
176
+ VANNA_HOST: 0.0.0.0
177
+ VANNA_PORT: 9000
178
+ VANNA_DSN: postgresql://${DATAIF_VANNA_USER}:${DATAIF_VANNA_PASSWORD}@postgres:5432/${DATAIF_DB_NAME}
179
+ VANNA_LLM_PROVIDER: ${VANNA_LLM_PROVIDER:-ollama}
180
+ VANNA_OLLAMA_BASE_URL: ${VANNA_OLLAMA_BASE_URL:-http://ollama:11434}
181
+ VANNA_OLLAMA_MODEL: ${VANNA_OLLAMA_MODEL:-sabia-7b}
182
+ VANNA_MARITACA_API_URL: ${VANNA_MARITACA_API_URL:-https://chat.maritaca.ai/api/chat/completions}
183
+ VANNA_MARITACA_API_KEY: ${VANNA_MARITACA_API_KEY:-}
184
+ VANNA_MARITACA_MODEL: ${VANNA_MARITACA_MODEL:-sabia-4}
185
+ VANNA_MARITACA_TIMEOUT_SECONDS: ${VANNA_MARITACA_TIMEOUT_SECONDS:-60}
186
+ VANNA_VECTORSTORE_PATH: ${VANNA_VECTORSTORE_PATH:-/data/vanna/chroma}
187
+ VANNA_AUTO_TRAIN: ${VANNA_AUTO_TRAIN:-true}
188
+ VANNA_ALLOWED_SCHEMA: ${VANNA_ALLOWED_SCHEMA:-curated}
189
+ ALLOWED_CURATED_VIEWS: ${ALLOWED_CURATED_VIEWS:-}
190
+ VANNA_MAX_ROWS: ${VANNA_MAX_ROWS}
191
+ ports:
192
+ - "${VANNA_PORT}:9000"
193
+ volumes:
194
+ - vanna_data:/data/vanna
195
+ mem_limit: ${VANNA_MEM_LIMIT:-512m}
196
+ depends_on:
197
+ postgres:
198
+ condition: service_healthy
199
+
200
+ ollama:
201
+ image: ollama/ollama:${OLLAMA_IMAGE_TAG:-latest}
202
+ profiles: ["llm"]
203
+ ports:
204
+ - "${OLLAMA_PORT:-11434}:11434"
205
+ volumes:
206
+ - ollama_data:/root/.ollama
207
+ - ollama_models:/models:ro
208
+ mem_limit: ${OLLAMA_MEM_LIMIT:-8192m}
209
+
210
+ ollama-model-bootstrap:
211
+ build:
212
+ context: ./ollama
213
+ dockerfile: Dockerfile
214
+ profiles: ["llm"]
215
+ environment:
216
+ OLLAMA_BASE_URL: http://ollama:11434
217
+ OLLAMA_MODEL_BOOTSTRAP_ENABLED: ${OLLAMA_MODEL_BOOTSTRAP_ENABLED:-true}
218
+ OLLAMA_MODEL_NAME: ${OLLAMA_MODEL_NAME:-sabia-7b}
219
+ OLLAMA_MODEL_GGUF_URL: ${OLLAMA_MODEL_GGUF_URL:-https://huggingface.co/QuantFactory/sabia-7b-GGUF/resolve/main/sabia-7b.Q4_K_M.gguf}
220
+ OLLAMA_MODEL_GGUF_FILE: ${OLLAMA_MODEL_GGUF_FILE:-sabia-7b.Q4_K_M.gguf}
221
+ HF_TOKEN: ${HF_TOKEN:-}
222
+ volumes:
223
+ - ollama_models:/models
224
+ depends_on:
225
+ ollama:
226
+ condition: service_started
227
+ restart: "no"
228
+
229
+ api:
230
+ build:
231
+ context: ../services/api
232
+ dockerfile: Dockerfile
233
+ env_file:
234
+ - .env
235
+ environment:
236
+ API_HOST: 0.0.0.0
237
+ API_PORT: 8000
238
+ WAREHOUSE_DSN: postgresql://${DATAIF_ETL_USER}:${DATAIF_ETL_PASSWORD}@postgres:5432/${DATAIF_DB_NAME}
239
+ METABASE_SITE_URL: ${METABASE_SITE_URL}
240
+ METABASE_API_URL: ${METABASE_API_URL:-http://metabase:3000}
241
+ METABASE_EMBED_SECRET: ${METABASE_EMBED_SECRET}
242
+ METABASE_ALLOWED_DASHBOARD_IDS: ${METABASE_ALLOWED_DASHBOARD_IDS}
243
+ METABASE_DEFAULT_DASHBOARD_ID: ${METABASE_DEFAULT_DASHBOARD_ID:-}
244
+ METABASE_ADMIN_EMAIL: ${METABASE_ADMIN_EMAIL:-admin@dataif.local}
245
+ METABASE_ADMIN_PASSWORD: ${METABASE_ADMIN_PASSWORD:-admin}
246
+ METABASE_ADMIN_FIRST_NAME: ${METABASE_ADMIN_FIRST_NAME:-DataIF}
247
+ METABASE_ADMIN_LAST_NAME: ${METABASE_ADMIN_LAST_NAME:-Metabase}
248
+ METABASE_SITE_NAME: ${METABASE_SITE_NAME:-dataif}
249
+ METABASE_ALLOW_TRACKING: ${METABASE_ALLOW_TRACKING:-false}
250
+ VANNA_SERVICE_URL: http://vanna:9000
251
+ KEYCLOAK_URL: ${KEYCLOAK_URL}
252
+ KEYCLOAK_REALM: ${KEYCLOAK_REALM}
253
+ KEYCLOAK_AUDIENCE: ${KEYCLOAK_AUDIENCE}
254
+ KEYCLOAK_ADMIN_REALM: ${KEYCLOAK_ADMIN_REALM:-master}
255
+ KEYCLOAK_ADMIN_CLIENT_ID: ${KEYCLOAK_ADMIN_CLIENT_ID:-admin-cli}
256
+ KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN}
257
+ KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
258
+ VANNA_LLM_PROVIDER: ${VANNA_LLM_PROVIDER:-ollama}
259
+ VANNA_OLLAMA_BASE_URL: ${VANNA_OLLAMA_BASE_URL:-http://ollama:11434}
260
+ VANNA_OLLAMA_MODEL: ${VANNA_OLLAMA_MODEL:-sabia-7b}
261
+ VANNA_MARITACA_API_URL: ${VANNA_MARITACA_API_URL:-https://chat.maritaca.ai/api/chat/completions}
262
+ VANNA_MARITACA_API_KEY: ${VANNA_MARITACA_API_KEY:-}
263
+ VANNA_MARITACA_MODEL: ${VANNA_MARITACA_MODEL:-sabia-4}
264
+ VANNA_MARITACA_TIMEOUT_SECONDS: ${VANNA_MARITACA_TIMEOUT_SECONDS:-60}
265
+ AIRFLOW_API_URL: ${AIRFLOW_API_URL:-http://airflow-webserver:8080/airflow}
266
+ AIRFLOW_ADMIN_USER: ${AIRFLOW_ADMIN_USER}
267
+ AIRFLOW_ADMIN_PASSWORD: ${AIRFLOW_ADMIN_PASSWORD}
268
+ CORS_ALLOW_ORIGINS: http://localhost:${WEB_PORT}
269
+ NILO_TIMEOUT_SECONDS: ${NILO_TIMEOUT_SECONDS}
270
+ ports:
271
+ - "${API_PORT}:8000"
272
+ volumes:
273
+ - ../services/api/app:/app/app
274
+ - ../pipelines/airflow/dags:/app/pipelines/airflow/dags
275
+ mem_limit: ${API_MEM_LIMIT:-512m}
276
+ restart: unless-stopped
277
+ depends_on:
278
+ metabase-bootstrap:
279
+ condition: service_completed_successfully
280
+ vanna:
281
+ condition: service_started
282
+
283
+ web:
284
+ build:
285
+ context: ../services/web
286
+ dockerfile: Dockerfile
287
+ args:
288
+ VITE_API_BASE_URL: ""
289
+ ports:
290
+ - "${WEB_PORT}:80"
291
+ mem_limit: ${WEB_MEM_LIMIT:-256m}
292
+ depends_on:
293
+ api:
294
+ condition: service_started
295
+ airflow-webserver:
296
+ condition: service_started
297
+ metabase:
298
+ condition: service_started
299
+
300
+ volumes:
301
+ postgres_data:
302
+ airflow_logs:
303
+ metabase_data:
304
+ vanna_data:
305
+ ollama_data:
306
+ ollama_models:
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ create_database_if_missing() {
5
+ local db_name="$1"
6
+ local exists
7
+
8
+ exists="$(
9
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres \
10
+ -tAc "SELECT 1 FROM pg_database WHERE datname = '${db_name}'" | tr -d '[:space:]'
11
+ )"
12
+
13
+ if [ "$exists" != "1" ]; then
14
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres \
15
+ --command "CREATE DATABASE \"${db_name}\";"
16
+ fi
17
+ }
18
+
19
+ create_database_if_missing "${DATAIF_DB_NAME}"
20
+ create_database_if_missing "${AIRFLOW_DB_NAME}"
21
+ create_database_if_missing "${METABASE_APP_DB_NAME}"
22
+
23
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname postgres <<EOSQL
24
+ DO \$\$
25
+ BEGIN
26
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${DATAIF_ETL_USER}') THEN
27
+ EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', '${DATAIF_ETL_USER}', '${DATAIF_ETL_PASSWORD}');
28
+ END IF;
29
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${DATAIF_METABASE_USER}') THEN
30
+ EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', '${DATAIF_METABASE_USER}', '${DATAIF_METABASE_PASSWORD}');
31
+ END IF;
32
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${DATAIF_VANNA_USER}') THEN
33
+ EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', '${DATAIF_VANNA_USER}', '${DATAIF_VANNA_PASSWORD}');
34
+ END IF;
35
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${AIRFLOW_DB_USER}') THEN
36
+ EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', '${AIRFLOW_DB_USER}', '${AIRFLOW_DB_PASSWORD}');
37
+ END IF;
38
+ IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = '${METABASE_APP_DB_USER}') THEN
39
+ EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', '${METABASE_APP_DB_USER}', '${METABASE_APP_DB_PASSWORD}');
40
+ END IF;
41
+ END
42
+ \$\$;
43
+
44
+ GRANT ALL PRIVILEGES ON DATABASE ${AIRFLOW_DB_NAME} TO ${AIRFLOW_DB_USER};
45
+ GRANT ALL PRIVILEGES ON DATABASE ${METABASE_APP_DB_NAME} TO ${METABASE_APP_DB_USER};
46
+ GRANT CONNECT ON DATABASE ${DATAIF_DB_NAME} TO ${DATAIF_ETL_USER}, ${DATAIF_METABASE_USER}, ${DATAIF_VANNA_USER};
47
+ EOSQL
48
+
49
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$AIRFLOW_DB_NAME" <<EOSQL
50
+ ALTER SCHEMA public OWNER TO ${AIRFLOW_DB_USER};
51
+ GRANT ALL ON SCHEMA public TO ${AIRFLOW_DB_USER};
52
+ EOSQL
53
+
54
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$METABASE_APP_DB_NAME" <<EOSQL
55
+ ALTER SCHEMA public OWNER TO ${METABASE_APP_DB_USER};
56
+ GRANT ALL ON SCHEMA public TO ${METABASE_APP_DB_USER};
57
+ EOSQL
58
+
59
+ psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DATAIF_DB_NAME" <<EOSQL
60
+ CREATE SCHEMA IF NOT EXISTS config AUTHORIZATION ${DATAIF_ETL_USER};
61
+ CREATE SCHEMA IF NOT EXISTS raw AUTHORIZATION ${DATAIF_ETL_USER};
62
+ CREATE SCHEMA IF NOT EXISTS staging AUTHORIZATION ${DATAIF_ETL_USER};
63
+ CREATE SCHEMA IF NOT EXISTS mart AUTHORIZATION ${DATAIF_ETL_USER};
64
+ CREATE SCHEMA IF NOT EXISTS curated AUTHORIZATION ${DATAIF_ETL_USER};
65
+ CREATE SCHEMA IF NOT EXISTS audit AUTHORIZATION ${DATAIF_ETL_USER};
66
+
67
+ \i /docker-entrypoint-initdb.d/pnp-raw-staging-curated.sqlinc
68
+ \i /docker-entrypoint-initdb.d/pnp-curated-views.sqlinc
69
+
70
+ ALTER TABLE config.app_settings OWNER TO ${DATAIF_ETL_USER};
71
+ ALTER TABLE raw.pnp_connections OWNER TO ${DATAIF_ETL_USER};
72
+ ALTER TABLE raw.pnp_instances OWNER TO ${DATAIF_ETL_USER};
73
+ ALTER TABLE raw.pnp_instance_selection OWNER TO ${DATAIF_ETL_USER};
74
+ ALTER TABLE raw.pnp_endpoint_tables OWNER TO ${DATAIF_ETL_USER};
75
+ ALTER TABLE raw.pnp_pipeline_endpoints OWNER TO ${DATAIF_ETL_USER};
76
+ ALTER TABLE raw.pnp_runs OWNER TO ${DATAIF_ETL_USER};
77
+ ALTER TABLE raw.pnp_run_steps OWNER TO ${DATAIF_ETL_USER};
78
+ ALTER TABLE raw.pnp_run_packages OWNER TO ${DATAIF_ETL_USER};
79
+ ALTER TABLE raw.pnp_catalog_entries OWNER TO ${DATAIF_ETL_USER};
80
+ ALTER TABLE raw.pnp_run_selection OWNER TO ${DATAIF_ETL_USER};
81
+ ALTER TABLE raw.pnp_downloads OWNER TO ${DATAIF_ETL_USER};
82
+ ALTER TABLE raw.pnp_download_columns OWNER TO ${DATAIF_ETL_USER};
83
+ ALTER TABLE raw.pnp_ingestion_quarantine OWNER TO ${DATAIF_ETL_USER};
84
+ ALTER TABLE raw.pnp_matriculas_src OWNER TO ${DATAIF_ETL_USER};
85
+ ALTER TABLE raw.pnp_eficiencia_academica_src OWNER TO ${DATAIF_ETL_USER};
86
+ ALTER TABLE raw.pnp_financeiro_src OWNER TO ${DATAIF_ETL_USER};
87
+ ALTER TABLE raw.pnp_servidores_src OWNER TO ${DATAIF_ETL_USER};
88
+ ALTER TABLE staging.pnp_ingestion_runs OWNER TO ${DATAIF_ETL_USER};
89
+ ALTER TABLE staging.pnp_matriculas OWNER TO ${DATAIF_ETL_USER};
90
+ ALTER TABLE staging.pnp_eficiencia_academica OWNER TO ${DATAIF_ETL_USER};
91
+ ALTER TABLE staging.pnp_servidores OWNER TO ${DATAIF_ETL_USER};
92
+ ALTER TABLE staging.pnp_financeiro OWNER TO ${DATAIF_ETL_USER};
93
+ ALTER VIEW curated.vw_pnp_admin_ingestao OWNER TO ${DATAIF_ETL_USER};
94
+ ALTER VIEW curated.vw_pnp_qualidade_dados OWNER TO ${DATAIF_ETL_USER};
95
+ ALTER VIEW curated.vw_pnp_matriculas_perfil OWNER TO ${DATAIF_ETL_USER};
96
+ ALTER VIEW curated.vw_pnp_matriculas_oferta OWNER TO ${DATAIF_ETL_USER};
97
+ ALTER VIEW curated.vw_pnp_eficiencia_situacao OWNER TO ${DATAIF_ETL_USER};
98
+ ALTER VIEW curated.vw_pnp_servidores_quadro OWNER TO ${DATAIF_ETL_USER};
99
+ ALTER VIEW curated.vw_pnp_financeiro_execucao OWNER TO ${DATAIF_ETL_USER};
100
+ ALTER VIEW curated.vw_pnp_vanna_catalogo OWNER TO ${DATAIF_ETL_USER};
101
+ ALTER VIEW curated.vw_pnp_vanna_resumo OWNER TO ${DATAIF_ETL_USER};
102
+ ALTER MATERIALIZED VIEW curated.mv_pnp_dashboard_matriculas OWNER TO ${DATAIF_ETL_USER};
103
+ ALTER MATERIALIZED VIEW curated.mv_pnp_dashboard_eficiencia OWNER TO ${DATAIF_ETL_USER};
104
+ ALTER MATERIALIZED VIEW curated.mv_pnp_dashboard_servidores OWNER TO ${DATAIF_ETL_USER};
105
+ ALTER MATERIALIZED VIEW curated.mv_pnp_dashboard_financeiro OWNER TO ${DATAIF_ETL_USER};
106
+ ALTER MATERIALIZED VIEW curated.mv_pnp_dashboard_qualidade OWNER TO ${DATAIF_ETL_USER};
107
+ ALTER MATERIALIZED VIEW curated.mv_pnp_dashboard_ingestao OWNER TO ${DATAIF_ETL_USER};
108
+ ALTER FUNCTION raw.touch_updated_at() OWNER TO ${DATAIF_ETL_USER};
109
+
110
+ GRANT USAGE ON SCHEMA config, raw, staging, mart, audit, curated TO ${DATAIF_ETL_USER};
111
+ GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA config, raw, staging, mart, audit TO ${DATAIF_ETL_USER};
112
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA config, raw, staging, mart, audit TO ${DATAIF_ETL_USER};
113
+
114
+ ALTER DEFAULT PRIVILEGES IN SCHEMA config GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${DATAIF_ETL_USER};
115
+ ALTER DEFAULT PRIVILEGES IN SCHEMA raw GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${DATAIF_ETL_USER};
116
+ ALTER DEFAULT PRIVILEGES IN SCHEMA staging GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${DATAIF_ETL_USER};
117
+ ALTER DEFAULT PRIVILEGES IN SCHEMA mart GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${DATAIF_ETL_USER};
118
+ ALTER DEFAULT PRIVILEGES IN SCHEMA audit GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${DATAIF_ETL_USER};
119
+
120
+ ALTER DEFAULT PRIVILEGES IN SCHEMA config GRANT USAGE, SELECT ON SEQUENCES TO ${DATAIF_ETL_USER};
121
+ ALTER DEFAULT PRIVILEGES IN SCHEMA raw GRANT USAGE, SELECT ON SEQUENCES TO ${DATAIF_ETL_USER};
122
+ ALTER DEFAULT PRIVILEGES IN SCHEMA staging GRANT USAGE, SELECT ON SEQUENCES TO ${DATAIF_ETL_USER};
123
+ ALTER DEFAULT PRIVILEGES IN SCHEMA mart GRANT USAGE, SELECT ON SEQUENCES TO ${DATAIF_ETL_USER};
124
+ ALTER DEFAULT PRIVILEGES IN SCHEMA audit GRANT USAGE, SELECT ON SEQUENCES TO ${DATAIF_ETL_USER};
125
+
126
+ GRANT USAGE ON SCHEMA curated TO ${DATAIF_METABASE_USER}, ${DATAIF_VANNA_USER};
127
+ GRANT SELECT ON ALL TABLES IN SCHEMA curated TO ${DATAIF_METABASE_USER}, ${DATAIF_VANNA_USER};
128
+ ALTER DEFAULT PRIVILEGES FOR ROLE ${DATAIF_ETL_USER} IN SCHEMA curated GRANT SELECT ON TABLES TO ${DATAIF_METABASE_USER}, ${DATAIF_VANNA_USER};
129
+ EOSQL