tinybird 0.0.1.dev199__tar.gz → 0.0.1.dev201__tar.gz

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.

Potentially problematic release.


This version of tinybird might be problematic. Click here for more details.

Files changed (110) hide show
  1. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/PKG-INFO +2 -1
  2. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/__cli__.py +2 -2
  3. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/build.py +15 -0
  4. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/connection.py +7 -7
  5. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/create.py +16 -0
  6. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/secret.py +61 -1
  7. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/test.py +4 -0
  8. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/watch.py +10 -1
  9. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird.egg-info/PKG-INFO +2 -1
  10. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird.egg-info/requires.txt +1 -0
  11. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/setup.cfg +0 -0
  12. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/__cli__.py +0 -0
  13. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/ch_utils/constants.py +0 -0
  14. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/ch_utils/engine.py +0 -0
  15. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/check_pypi.py +0 -0
  16. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/client.py +0 -0
  17. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/config.py +0 -0
  18. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/connectors.py +0 -0
  19. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/context.py +0 -0
  20. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/datafile.py +0 -0
  21. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/datatypes.py +0 -0
  22. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/feedback_manager.py +0 -0
  23. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/git_settings.py +0 -0
  24. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/prompts.py +0 -0
  25. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/sql.py +0 -0
  26. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/sql_template.py +0 -0
  27. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/sql_template_fmt.py +0 -0
  28. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/sql_toolset.py +0 -0
  29. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/syncasync.py +0 -0
  30. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/check_pypi.py +0 -0
  31. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/cli.py +0 -0
  32. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/client.py +0 -0
  33. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/config.py +0 -0
  34. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/cicd.py +0 -0
  35. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/cli.py +0 -0
  36. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/common.py +0 -0
  37. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/config.py +0 -0
  38. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/copy.py +0 -0
  39. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/build.py +0 -0
  40. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/build_common.py +0 -0
  41. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
  42. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
  43. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/common.py +0 -0
  44. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/diff.py +0 -0
  45. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/exceptions.py +0 -0
  46. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/fixture.py +0 -0
  47. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/format_common.py +0 -0
  48. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
  49. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
  50. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/parse_datasource.py +0 -0
  51. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/parse_pipe.py +0 -0
  52. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
  53. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/playground.py +0 -0
  54. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datafile/pull.py +0 -0
  55. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/datasource.py +0 -0
  56. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/deployment.py +0 -0
  57. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/deprecations.py +0 -0
  58. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/dev_server.py +0 -0
  59. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/endpoint.py +0 -0
  60. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/exceptions.py +0 -0
  61. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/feedback_manager.py +0 -0
  62. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/info.py +0 -0
  63. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/infra.py +0 -0
  64. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/job.py +0 -0
  65. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/llm.py +0 -0
  66. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/llm_utils.py +0 -0
  67. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/local.py +0 -0
  68. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/local_common.py +0 -0
  69. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/login.py +0 -0
  70. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/logout.py +0 -0
  71. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/materialization.py +0 -0
  72. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/mock.py +0 -0
  73. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/open.py +0 -0
  74. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/pipe.py +0 -0
  75. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/project.py +0 -0
  76. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/regions.py +0 -0
  77. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/shell.py +0 -0
  78. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/table.py +0 -0
  79. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/telemetry.py +0 -0
  80. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
  81. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
  82. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/token.py +0 -0
  83. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/workspace.py +0 -0
  84. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb/modules/workspace_members.py +0 -0
  85. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli.py +0 -0
  86. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/auth.py +0 -0
  87. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/branch.py +0 -0
  88. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/cicd.py +0 -0
  89. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/cli.py +0 -0
  90. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/common.py +0 -0
  91. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/config.py +0 -0
  92. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/connection.py +0 -0
  93. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/datasource.py +0 -0
  94. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/exceptions.py +0 -0
  95. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/fmt.py +0 -0
  96. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/job.py +0 -0
  97. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/pipe.py +0 -0
  98. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/regions.py +0 -0
  99. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/tag.py +0 -0
  100. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/telemetry.py +0 -0
  101. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/test.py +0 -0
  102. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
  103. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
  104. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/workspace.py +0 -0
  105. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tb_cli_modules/workspace_members.py +0 -0
  106. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird/tornado_template.py +0 -0
  107. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird.egg-info/SOURCES.txt +0 -0
  108. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird.egg-info/dependency_links.txt +0 -0
  109. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird.egg-info/entry_points.txt +0 -0
  110. {tinybird-0.0.1.dev199 → tinybird-0.0.1.dev201}/tinybird.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev199
3
+ Version: 0.0.1.dev201
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/forward/commands
6
6
  Author: Tinybird
@@ -34,6 +34,7 @@ Requires-Dist: wheel
34
34
  Requires-Dist: packaging<24,>=23.1
35
35
  Requires-Dist: llm>=0.19
36
36
  Requires-Dist: thefuzz==0.22.1
37
+ Requires-Dist: python-dotenv==1.1.0
37
38
  Dynamic: author
38
39
  Dynamic: author-email
39
40
  Dynamic: description
@@ -4,5 +4,5 @@ __description__ = 'Tinybird Command Line Tool'
4
4
  __url__ = 'https://www.tinybird.co/docs/forward/commands'
5
5
  __author__ = 'Tinybird'
6
6
  __author_email__ = 'support@tinybird.co'
7
- __version__ = '0.0.1.dev199'
8
- __revision__ = '191261b'
7
+ __version__ = '0.0.1.dev201'
8
+ __revision__ = '8d22235'
@@ -25,6 +25,7 @@ from tinybird.tb.modules.datafile.playground import folder_playground
25
25
  from tinybird.tb.modules.dev_server import BuildStatus, start_server
26
26
  from tinybird.tb.modules.feedback_manager import FeedbackManager
27
27
  from tinybird.tb.modules.project import Project
28
+ from tinybird.tb.modules.secret import load_secrets
28
29
  from tinybird.tb.modules.shell import Shell, print_table_formatted
29
30
  from tinybird.tb.modules.watch import watch_files, watch_project
30
31
 
@@ -47,6 +48,7 @@ def build(ctx: click.Context, watch: bool) -> None:
47
48
  )
48
49
  )
49
50
 
51
+ load_secrets(project, tb_client)
50
52
  click.echo(FeedbackManager.highlight_building_project())
51
53
  process(project=project, tb_client=tb_client, watch=False)
52
54
  if watch:
@@ -74,6 +76,8 @@ def dev(ctx: click.Context, data_origin: str, ui: bool) -> None:
74
76
  server_thread.start()
75
77
  # Wait for the server to start
76
78
  time.sleep(0.5)
79
+
80
+ load_secrets(project, tb_client)
77
81
  click.echo(FeedbackManager.highlight_building_project())
78
82
  process(project=project, tb_client=tb_client, watch=True, build_status=build_status)
79
83
  run_watch(
@@ -302,8 +306,19 @@ def process(
302
306
  build_status.building = True
303
307
  if file_changed and (file_changed.endswith(FixtureExtension.NDJSON) or file_changed.endswith(FixtureExtension.CSV)):
304
308
  rebuild_fixture(project, tb_client, file_changed)
309
+ if build_status:
310
+ build_status.building = False
311
+ build_status.error = None
305
312
  elif file_changed and file_changed.endswith(".sql"):
306
313
  rebuild_fixture_sql(project, tb_client, file_changed)
314
+ if build_status:
315
+ build_status.building = False
316
+ build_status.error = None
317
+ elif file_changed and (file_changed.endswith(".env.local") or file_changed.endswith(".env")):
318
+ load_secrets(project, tb_client)
319
+ if build_status:
320
+ build_status.building = False
321
+ build_status.error = None
307
322
  else:
308
323
  try:
309
324
  build_result = build_project(project, tb_client, silent)
@@ -38,6 +38,7 @@ from tinybird.tb.modules.create import (
38
38
  from tinybird.tb.modules.exceptions import CLIConnectionException
39
39
  from tinybird.tb.modules.feedback_manager import FeedbackManager
40
40
  from tinybird.tb.modules.project import Project
41
+ from tinybird.tb.modules.secret import save_secret_to_env_file
41
42
 
42
43
  DATA_CONNECTOR_SETTINGS: Dict[DataConnectorType, List[str]] = {
43
44
  DataConnectorType.KAFKA: [
@@ -356,7 +357,6 @@ async def connection_create_kafka(
356
357
  security_protocol="SASL_SSL",
357
358
  skip_secrets=False,
358
359
  ) -> Tuple[str, str, str, str, str, str, str, str, List[str]]:
359
- client: TinyB = ctx.ensure_object(dict)["client"]
360
360
  obj: Dict[str, Any] = ctx.ensure_object(dict)
361
361
  click.echo(FeedbackManager.gray(message="\n» Creating Kafka connection..."))
362
362
  project: Project = ctx.ensure_object(dict)["project"]
@@ -374,7 +374,7 @@ async def connection_create_kafka(
374
374
 
375
375
  validate_kafka_bootstrap_servers(bootstrap_servers)
376
376
  secret_required = not skip_secrets and click.confirm(
377
- FeedbackManager.highlight(message=" ? Do you want to store the bootstrap server in a Tinybird Secret? [Y/n]"),
377
+ FeedbackManager.highlight(message=" ? Do you want to store the bootstrap server in a .env.local file? [Y/n]"),
378
378
  default=True,
379
379
  show_default=False,
380
380
  )
@@ -385,7 +385,7 @@ async def connection_create_kafka(
385
385
  if secret_required:
386
386
  tb_secret_bootstrap_servers = str(click.prompt(FeedbackManager.highlight(message=" ? Secret name")))
387
387
  try:
388
- await client.create_secret(name=tb_secret_bootstrap_servers, value=bootstrap_servers)
388
+ save_secret_to_env_file(project=project, name=tb_secret_bootstrap_servers, value=bootstrap_servers)
389
389
  except Exception as e:
390
390
  raise CLIConnectionException(FeedbackManager.error(message=str(e)))
391
391
 
@@ -395,7 +395,7 @@ async def connection_create_kafka(
395
395
  validate_kafka_key(key)
396
396
 
397
397
  secret_required = not skip_secrets and click.confirm(
398
- FeedbackManager.highlight(message=" ? Do you want to store the Kafka key in a Tinybird Secret? [Y/n]"),
398
+ FeedbackManager.highlight(message=" ? Do you want to store the Kafka key in a .env.local file? [Y/n]"),
399
399
  default=True,
400
400
  show_default=False,
401
401
  )
@@ -403,7 +403,7 @@ async def connection_create_kafka(
403
403
  if secret_required:
404
404
  tb_secret_key = str(click.prompt(FeedbackManager.highlight(message=" ? Secret name")))
405
405
  try:
406
- await client.create_secret(name=tb_secret_key, value=key)
406
+ save_secret_to_env_file(project=project, name=tb_secret_key, value=key)
407
407
  except Exception as e:
408
408
  raise CLIConnectionException(FeedbackManager.error(message=str(e)))
409
409
 
@@ -413,7 +413,7 @@ async def connection_create_kafka(
413
413
  validate_kafka_secret(secret)
414
414
 
415
415
  secret_required = not skip_secrets and click.confirm(
416
- FeedbackManager.highlight(message=" ? Do you want to store the Kafka secret in a Tinybird Secret? [Y/n]"),
416
+ FeedbackManager.highlight(message=" ? Do you want to store the Kafka secret in a .env.local file? [Y/n]"),
417
417
  default=True,
418
418
  show_default=False,
419
419
  )
@@ -421,7 +421,7 @@ async def connection_create_kafka(
421
421
  if secret_required:
422
422
  tb_secret_secret = str(click.prompt(FeedbackManager.highlight(message=" ? Secret name")))
423
423
  try:
424
- await client.create_secret(name=tb_secret_secret, value=secret)
424
+ save_secret_to_env_file(project=project, name=tb_secret_secret, value=secret)
425
425
  except Exception as e:
426
426
  raise CLIConnectionException(FeedbackManager.error(message=str(e)))
427
427
 
@@ -124,6 +124,12 @@ async def create(
124
124
  if data or prompt:
125
125
  click.echo(FeedbackManager.success(message="✓ Resources created!\n"))
126
126
 
127
+ if not already_has_env_file(root_folder):
128
+ click.echo(FeedbackManager.highlight(message="\n» Creating .env.local file..."))
129
+ create_env_file(root_folder)
130
+ click.echo(FeedbackManager.success(message="✓ Done!\n"))
131
+ created_something = True
132
+
127
133
  if not already_has_cicd(root_folder):
128
134
  click.echo(FeedbackManager.highlight(message="\n» Creating CI/CD files for GitHub and GitLab..."))
129
135
  init_git(root_folder)
@@ -230,6 +236,11 @@ def already_has_cursor_rules(folder: str) -> bool:
230
236
  return any((Path(folder) / path).exists() for path in cursor_rules_paths)
231
237
 
232
238
 
239
+ def already_has_env_file(folder: str) -> bool:
240
+ env_file_pattern = ".env.*"
241
+ return any((Path(folder) / path).exists() for path in glob.glob(env_file_pattern))
242
+
243
+
233
244
  def create_project_structure(folder: str):
234
245
  folder_path = Path(folder)
235
246
  PROJECT_PATHS_DESCRIPTIONS = {
@@ -433,6 +444,11 @@ GCS_SERVICE_ACCOUNT_CREDENTIALS_JSON {{{{ tb_secret("{svc_account_creds}") }}}}
433
444
  return file_path
434
445
 
435
446
 
447
+ def create_env_file(folder: str):
448
+ env_file = Path(folder) / ".env.local"
449
+ env_file.write_text("")
450
+
451
+
436
452
  def create_rules(folder: str, source: str, agent: str):
437
453
  if agent == "cursor":
438
454
  extension = ".cursorrules"
@@ -1,12 +1,15 @@
1
1
  import re
2
- from typing import Optional
2
+ from typing import Dict, Optional
3
3
 
4
4
  import click
5
+ from dotenv import dotenv_values, set_key
5
6
 
7
+ from tinybird.syncasync import async_to_sync
6
8
  from tinybird.tb.client import TinyB
7
9
  from tinybird.tb.modules.cli import cli
8
10
  from tinybird.tb.modules.common import coro, echo_safe_humanfriendly_tables_format_smart_table
9
11
  from tinybird.tb.modules.feedback_manager import FeedbackManager
12
+ from tinybird.tb.modules.project import Project
10
13
 
11
14
 
12
15
  @cli.group()
@@ -86,3 +89,60 @@ async def secret_rm(ctx: click.Context, name: str):
86
89
  click.echo(FeedbackManager.success(message=f"\n✓ Secret '{name}' deleted"))
87
90
  except Exception as e:
88
91
  click.echo(FeedbackManager.error(message=f"✗ Error: {e}"))
92
+
93
+
94
+ def load_secrets(project: Project, client: TinyB):
95
+ try:
96
+ env_vars: Dict[str, str] = {}
97
+
98
+ # Load secrets from .env file
99
+ env_file = ".env"
100
+ env_path = project.path / env_file
101
+
102
+ if env_path.exists():
103
+ env_values = dotenv_values(env_path)
104
+ if env_values:
105
+ env_vars.update({k: v for k, v in env_values.items() if v is not None})
106
+
107
+ # Load secrets from .env.local file
108
+ env_file = ".env.local"
109
+ env_path = project.path / env_file
110
+
111
+ if env_path.exists():
112
+ env_values = dotenv_values(env_path)
113
+ if env_values:
114
+ env_vars.update({k: v for k, v in env_values.items() if v is not None})
115
+
116
+ if len(env_vars.keys()) == 0:
117
+ return
118
+
119
+ click.echo(FeedbackManager.highlight(message="\n» Loading secrets from .env files..."))
120
+
121
+ for name, value in env_vars.items():
122
+ if not value:
123
+ continue
124
+
125
+ try:
126
+ existing_secret = async_to_sync(client.get_secret)(name)
127
+ except Exception:
128
+ existing_secret = None
129
+ try:
130
+ if existing_secret:
131
+ async_to_sync(client.update_secret)(name, value)
132
+ else:
133
+ async_to_sync(client.create_secret)(name, value)
134
+ except Exception as e:
135
+ click.echo(FeedbackManager.error(message=f"✗ Error setting secret '{name}': {e}"))
136
+
137
+ click.echo(FeedbackManager.success(message="✓ Secrets loaded!"))
138
+ except Exception as e:
139
+ click.echo(FeedbackManager.error(message=f"✗ Error: {e}"))
140
+
141
+
142
+ def save_secret_to_env_file(project: Project, name: str, value: str):
143
+ env_path = project.path / ".env.local"
144
+
145
+ if not env_path.exists():
146
+ env_path.touch()
147
+
148
+ set_key(env_path, key_to_set=name, value_to_set=value)
@@ -27,6 +27,7 @@ from tinybird.tb.modules.llm import LLM
27
27
  from tinybird.tb.modules.llm_utils import extract_xml, parse_xml
28
28
  from tinybird.tb.modules.local_common import get_local_tokens, get_test_workspace_name
29
29
  from tinybird.tb.modules.project import Project
30
+ from tinybird.tb.modules.secret import load_secrets
30
31
 
31
32
  yaml.SafeDumper.org_represent_str = yaml.SafeDumper.represent_str # type: ignore[attr-defined]
32
33
 
@@ -78,6 +79,7 @@ def test_create(ctx: click.Context, name_or_filename: str, prompt: str) -> None:
78
79
  try:
79
80
  project: Project = ctx.ensure_object(dict)["project"]
80
81
  client: TinyB = ctx.ensure_object(dict)["client"]
82
+ load_secrets(project=project, client=client)
81
83
  click.echo(FeedbackManager.highlight(message="\n» Building project"))
82
84
  build_project(project=project, tb_client=client, watch=False, silent=True)
83
85
  click.echo(FeedbackManager.info(message="✓ Done!\n"))
@@ -156,6 +158,7 @@ def test_update(ctx: click.Context, pipe: str) -> None:
156
158
  client: TinyB = ctx.ensure_object(dict)["client"]
157
159
  project: Project = ctx.ensure_object(dict)["project"]
158
160
  folder = project.folder
161
+ load_secrets(project=project, client=client)
159
162
  click.echo(FeedbackManager.highlight(message="\n» Building project"))
160
163
  build_project(project=project, tb_client=client, watch=False, silent=True)
161
164
  click.echo(FeedbackManager.info(message="✓ Done!"))
@@ -208,6 +211,7 @@ def run_tests(ctx: click.Context, name: Tuple[str, ...]) -> None:
208
211
  try:
209
212
  client: TinyB = ctx.ensure_object(dict)["client"]
210
213
  project: Project = ctx.ensure_object(dict)["project"]
214
+ load_secrets(project=project, client=client)
211
215
  click.echo(FeedbackManager.highlight(message="\n» Building project"))
212
216
  build_project(project=project, tb_client=client, watch=False, silent=True)
213
217
  click.echo(FeedbackManager.info(message="✓ Done!"))
@@ -23,7 +23,16 @@ from tinybird.tb.modules.shell import Shell
23
23
 
24
24
 
25
25
  class WatchProjectHandler(PatternMatchingEventHandler):
26
- valid_extensions = [".datasource", ".pipe", "connection", FixtureExtension.CSV, FixtureExtension.NDJSON, ".sql"]
26
+ valid_extensions = [
27
+ ".datasource",
28
+ ".pipe",
29
+ "connection",
30
+ FixtureExtension.CSV,
31
+ FixtureExtension.NDJSON,
32
+ ".sql",
33
+ ".env",
34
+ ".env.local",
35
+ ]
27
36
 
28
37
  def __init__(self, shell: Shell, project: Project, process: Callable):
29
38
  self.shell = shell
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinybird
3
- Version: 0.0.1.dev199
3
+ Version: 0.0.1.dev201
4
4
  Summary: Tinybird Command Line Tool
5
5
  Home-page: https://www.tinybird.co/docs/forward/commands
6
6
  Author: Tinybird
@@ -34,6 +34,7 @@ Requires-Dist: wheel
34
34
  Requires-Dist: packaging<24,>=23.1
35
35
  Requires-Dist: llm>=0.19
36
36
  Requires-Dist: thefuzz==0.22.1
37
+ Requires-Dist: python-dotenv==1.1.0
37
38
  Dynamic: author
38
39
  Dynamic: author-email
39
40
  Dynamic: description
@@ -25,3 +25,4 @@ wheel
25
25
  packaging<24,>=23.1
26
26
  llm>=0.19
27
27
  thefuzz==0.22.1
28
+ python-dotenv==1.1.0