tinybird 4.5.4.dev0__tar.gz → 4.5.5.dev0__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.
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/PKG-INFO +6 -1
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/service_datasources.py +2 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/__cli__.py +2 -2
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/cli.py +1 -1
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/deployment.py +161 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/deployment_common.py +86 -8
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/branch.py +4 -5
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/cli.py +1 -3
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/common.py +5 -3
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/job.py +1 -3
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/tag.py +2 -3
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/workspace.py +10 -11
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird.egg-info/PKG-INFO +6 -1
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/setup.cfg +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/__cli__.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/ch_utils/constants.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/ch_utils/engine.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/check_pypi.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/client.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/config.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/context.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/datafile/common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/datafile/exceptions.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/datafile/parse_connection.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/datafile/parse_datasource.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/datafile/parse_pipe.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/datatypes.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/feedback_manager.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/git_settings.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/prompts.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/sql.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/sql_template.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/sql_template_fmt.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/sql_toolset.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/syncasync.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/check_pypi.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/cli.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/client.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/config.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/branch.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/build.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/build_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/cicd.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/config.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/connection.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/connection_kafka.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/connection_s3.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/copy.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/create.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/build.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/build_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/build_datasource.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/build_pipe.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/diff.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/fixture.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/format_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/format_connection.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/format_datasource.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/format_pipe.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/pipe_checker.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/playground.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/pull.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datasource.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/deprecations.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/endpoint.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/exceptions.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/feedback_manager.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/fmt.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/info.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/infra.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/job.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/job_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/llm.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/llm_utils.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/local.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/local_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/local_logs.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/login.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/login_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/logout.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/logs.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/materialization.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/open.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/pipe.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/preview.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/project.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/project_commands.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/py_project.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/query_output.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/regions.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/secret.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/secret_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/sink.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/table.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/telemetry.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/test.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/test_common.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/token.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/ts_project.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/watch.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/workspace.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/workspace_members.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/auth.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/cicd.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/config.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/connection.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/datasource.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/exceptions.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/fmt.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/pipe.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/regions.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/telemetry.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/test.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/workspace_members.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tornado_template.py +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird.egg-info/SOURCES.txt +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird.egg-info/dependency_links.txt +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird.egg-info/entry_points.txt +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird.egg-info/requires.txt +0 -0
- {tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.5.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,6 +52,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
+
4.5.4
|
|
56
|
+
*******
|
|
57
|
+
|
|
58
|
+
- `Added` `tb migrate-to-forward` to help users migrate Classic workspaces to Forward
|
|
59
|
+
|
|
55
60
|
4.5.3
|
|
56
61
|
*******
|
|
57
62
|
|
|
@@ -507,6 +507,8 @@ def get_tinybird_service_datasources() -> List[Dict[str, Any]]:
|
|
|
507
507
|
{"name": "ch_written_bytes", "type": "UInt64"},
|
|
508
508
|
{"name": "ch_cpu_time", "type": "Float32"},
|
|
509
509
|
{"name": "rate_limited", "type": "UInt8"},
|
|
510
|
+
{"name": "ips", "type": "SimpleAggregateFunction(groupUniqArrayArray, Array(String))"},
|
|
511
|
+
{"name": "tokens", "type": "SimpleAggregateFunction(groupUniqArrayArray, Array(String))"},
|
|
510
512
|
],
|
|
511
513
|
},
|
|
512
514
|
{
|
|
@@ -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__ = '4.5.
|
|
8
|
-
__revision__ = '
|
|
7
|
+
__version__ = '4.5.5.dev0'
|
|
8
|
+
__revision__ = 'eebce0e'
|
|
@@ -63,7 +63,7 @@ DEV_MODE_VALUES = {DEV_MODE_MANUAL, DEV_MODE_LOCAL, DEV_MODE_BRANCH}
|
|
|
63
63
|
DEV_MODE_ROUTED_COMMANDS = {"build", "deploy"}
|
|
64
64
|
SDK_PROJECT_ROUTED_COMMANDS = {"build", "deploy", "preview"}
|
|
65
65
|
TS_PROJECT_ROUTED_COMMANDS = SDK_PROJECT_ROUTED_COMMANDS
|
|
66
|
-
COMMANDS_ALWAYS_CLOUD = {"infra", "branch", "environment", "workspace", "preview"}
|
|
66
|
+
COMMANDS_ALWAYS_CLOUD = {"infra", "branch", "environment", "workspace", "preview", "migrate-to-forward"}
|
|
67
67
|
PROJECT_TYPE_TYPESCRIPT = "ts-sdk"
|
|
68
68
|
PROJECT_TYPE_PYTHON = "python-sdk"
|
|
69
69
|
PROJECT_TYPE_CLI = "cli"
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
+
import os
|
|
3
4
|
from datetime import datetime, timedelta, timezone
|
|
4
5
|
from pathlib import Path
|
|
5
6
|
from typing import Any, Dict, Optional
|
|
@@ -7,14 +8,17 @@ from typing import Any, Dict, Optional
|
|
|
7
8
|
import click
|
|
8
9
|
import requests
|
|
9
10
|
|
|
11
|
+
from tinybird.tb.client import TinyB
|
|
10
12
|
from tinybird.tb.modules.cli import cli
|
|
11
13
|
from tinybird.tb.modules.common import (
|
|
12
14
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
13
15
|
sys_exit,
|
|
14
16
|
)
|
|
17
|
+
from tinybird.tb.modules.create import persist_tinybird_config
|
|
15
18
|
from tinybird.tb.modules.deployment_common import (
|
|
16
19
|
create_deployment,
|
|
17
20
|
discard_deployment,
|
|
21
|
+
migrate_to_forward_workspace,
|
|
18
22
|
promote_deployment,
|
|
19
23
|
)
|
|
20
24
|
from tinybird.tb.modules.feedback_manager import FeedbackManager
|
|
@@ -151,6 +155,63 @@ def api_fetch(url: str, headers: dict, request_from: Optional[str] = None) -> di
|
|
|
151
155
|
return {}
|
|
152
156
|
|
|
153
157
|
|
|
158
|
+
def _get_classic_workspace_branches(client: TinyB, workspace_id: str) -> list[dict[str, Any]]:
|
|
159
|
+
branches: list[dict[str, Any]] = client.user_workspace_branches(version="v0").get("workspaces", [])
|
|
160
|
+
return [branch for branch in branches if str(branch.get("main")) == workspace_id]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def _get_non_live_classic_releases(client: TinyB, workspace_id: str) -> list[dict[str, Any]]:
|
|
164
|
+
releases: list[dict[str, Any]] = client.releases(workspace_id=workspace_id).get("releases", [])
|
|
165
|
+
return [release for release in releases if release.get("status") != "live"]
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _cleanup_classic_migration_blockers(client: TinyB, config: Dict[str, Any]) -> None:
|
|
169
|
+
workspace_id = str(config["id"])
|
|
170
|
+
workspace_name = str(config["name"])
|
|
171
|
+
branches = _get_classic_workspace_branches(client, workspace_id)
|
|
172
|
+
releases = _get_non_live_classic_releases(client, workspace_id)
|
|
173
|
+
|
|
174
|
+
if not branches and not releases:
|
|
175
|
+
return
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
for branch in branches:
|
|
179
|
+
client.delete_branch(id=str(branch["id"]))
|
|
180
|
+
|
|
181
|
+
for release in releases:
|
|
182
|
+
client.release_rm(
|
|
183
|
+
workspace_id=workspace_id,
|
|
184
|
+
semver=str(release["semver"]),
|
|
185
|
+
confirmation=workspace_name,
|
|
186
|
+
dry_run=False,
|
|
187
|
+
force=False,
|
|
188
|
+
)
|
|
189
|
+
except Exception as e:
|
|
190
|
+
message = f"Error cleaning up Classic branches or releases before migration: {str(e)}"
|
|
191
|
+
click.echo(FeedbackManager.error(message=message))
|
|
192
|
+
sys_exit("migration_error", message)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def _persist_migrate_to_forward_config(project: Project) -> None:
|
|
196
|
+
root_folder = os.getcwd()
|
|
197
|
+
project_folder = os.path.relpath(project.path.resolve(), root_folder)
|
|
198
|
+
|
|
199
|
+
config_changed, config_created = persist_tinybird_config(
|
|
200
|
+
root_folder=root_folder,
|
|
201
|
+
project_type="cli",
|
|
202
|
+
dev_mode="manual",
|
|
203
|
+
folder=project_folder,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
if not config_changed:
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
message = "Created tinybird.config.json for the Forward CLI"
|
|
210
|
+
if not config_created:
|
|
211
|
+
message = "Updated tinybird.config.json for the Forward CLI"
|
|
212
|
+
click.echo(FeedbackManager.info(message=message))
|
|
213
|
+
|
|
214
|
+
|
|
154
215
|
@cli.group(name="deployment")
|
|
155
216
|
def deployment_group() -> None:
|
|
156
217
|
"""
|
|
@@ -371,6 +432,104 @@ def deploy(
|
|
|
371
432
|
create_deployment_cmd(ctx, wait, auto, check, allow_destructive_operations, template, verbose)
|
|
372
433
|
|
|
373
434
|
|
|
435
|
+
@cli.command(name="migrate-to-forward")
|
|
436
|
+
@click.option(
|
|
437
|
+
"--allow-destructive-operations/--no-allow-destructive-operations",
|
|
438
|
+
is_flag=True,
|
|
439
|
+
default=False,
|
|
440
|
+
help="Allow destructive operations in deployments (for example replacing a Pipe with a Data Source).",
|
|
441
|
+
)
|
|
442
|
+
@click.pass_context
|
|
443
|
+
def migrate_to_forward(ctx: click.Context, allow_destructive_operations: bool) -> None:
|
|
444
|
+
"""Migrate a Tinybird Classic cloud workspace to Tinybird Forward."""
|
|
445
|
+
client = ctx.ensure_object(dict)["client"]
|
|
446
|
+
project: Project = ctx.ensure_object(dict)["project"]
|
|
447
|
+
config: Dict[str, Any] = ctx.ensure_object(dict)["config"]
|
|
448
|
+
env = ctx.ensure_object(dict)["env"]
|
|
449
|
+
output = ctx.ensure_object(dict)["output"]
|
|
450
|
+
|
|
451
|
+
try:
|
|
452
|
+
workspace_info = client.workspace_info(version="v0")
|
|
453
|
+
except Exception as e:
|
|
454
|
+
message = f"Error checking workspace status: {str(e)}"
|
|
455
|
+
click.echo(FeedbackManager.error(message=message))
|
|
456
|
+
sys_exit("migration_error", message)
|
|
457
|
+
|
|
458
|
+
if workspace_info.get("is_forward", False):
|
|
459
|
+
message = "This command is unavailable for Tinybird Forward workspaces."
|
|
460
|
+
click.echo(FeedbackManager.error(message=message))
|
|
461
|
+
sys_exit("migration_error", message)
|
|
462
|
+
|
|
463
|
+
click.echo(
|
|
464
|
+
FeedbackManager.warning(
|
|
465
|
+
message=(
|
|
466
|
+
"This operation is irreversible: once your workspace is migrated to Tinybird Forward, "
|
|
467
|
+
"you cannot switch it back to Tinybird Classic. It will also run your first Forward deployment."
|
|
468
|
+
)
|
|
469
|
+
)
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
if not click.confirm("Do you want to proceed and run the deployment check now?", default=False):
|
|
473
|
+
click.echo(FeedbackManager.info(message="Migration cancelled."))
|
|
474
|
+
return
|
|
475
|
+
|
|
476
|
+
check_result = create_deployment(
|
|
477
|
+
project,
|
|
478
|
+
client,
|
|
479
|
+
config,
|
|
480
|
+
wait=False,
|
|
481
|
+
auto=False,
|
|
482
|
+
verbose=False,
|
|
483
|
+
check=True,
|
|
484
|
+
allow_destructive_operations=allow_destructive_operations,
|
|
485
|
+
output=output,
|
|
486
|
+
env=env,
|
|
487
|
+
show_migrate_to_forward_hint=False,
|
|
488
|
+
return_check_result=True,
|
|
489
|
+
skip_forward_workspace_validation=True,
|
|
490
|
+
)
|
|
491
|
+
if not check_result:
|
|
492
|
+
message = "Deployment check did not complete. Migration cancelled."
|
|
493
|
+
click.echo(FeedbackManager.error(message=message))
|
|
494
|
+
sys_exit("migration_error", message)
|
|
495
|
+
|
|
496
|
+
if check_result and check_result.get("status") == "no_changes":
|
|
497
|
+
click.echo(
|
|
498
|
+
FeedbackManager.warning(
|
|
499
|
+
message=(
|
|
500
|
+
"No deployment changes were detected. Add this dummy pipe to your workspace and run "
|
|
501
|
+
"`tb migrate-to-forward` again:"
|
|
502
|
+
)
|
|
503
|
+
)
|
|
504
|
+
)
|
|
505
|
+
click.echo("NODE n\nSQL >\n select 'Forward'")
|
|
506
|
+
return
|
|
507
|
+
|
|
508
|
+
if not click.confirm(
|
|
509
|
+
"Do you want to continue with the migration? This will also delete your branches, releases and switch your workspace from Classic to Forward.",
|
|
510
|
+
default=False,
|
|
511
|
+
):
|
|
512
|
+
click.echo(FeedbackManager.info(message="Migration cancelled."))
|
|
513
|
+
return
|
|
514
|
+
|
|
515
|
+
_persist_migrate_to_forward_config(project)
|
|
516
|
+
_cleanup_classic_migration_blockers(client, config)
|
|
517
|
+
migrate_to_forward_workspace(client=client, output=output, dry_run=False)
|
|
518
|
+
create_deployment(
|
|
519
|
+
project,
|
|
520
|
+
client,
|
|
521
|
+
config,
|
|
522
|
+
wait=True,
|
|
523
|
+
auto=True,
|
|
524
|
+
verbose=False,
|
|
525
|
+
check=False,
|
|
526
|
+
allow_destructive_operations=allow_destructive_operations,
|
|
527
|
+
output=output,
|
|
528
|
+
env=env,
|
|
529
|
+
skip_forward_workspace_validation=True,
|
|
530
|
+
)
|
|
531
|
+
|
|
532
|
+
|
|
374
533
|
def create_deployment_cmd(
|
|
375
534
|
ctx: click.Context,
|
|
376
535
|
wait: bool,
|
|
@@ -381,6 +540,7 @@ def create_deployment_cmd(
|
|
|
381
540
|
verbose: bool = False,
|
|
382
541
|
) -> None:
|
|
383
542
|
output = ctx.ensure_object(dict)["output"]
|
|
543
|
+
env = ctx.ensure_object(dict)["env"]
|
|
384
544
|
project: Project = ctx.ensure_object(dict)["project"]
|
|
385
545
|
if template:
|
|
386
546
|
if project.get_project_files():
|
|
@@ -416,6 +576,7 @@ def create_deployment_cmd(
|
|
|
416
576
|
allow_destructive_operations,
|
|
417
577
|
ingest_hint=not is_web_analytics_starter_kit,
|
|
418
578
|
output=output,
|
|
579
|
+
env=env,
|
|
419
580
|
)
|
|
420
581
|
show_web_analytics_starter_kit_hints(client, is_web_analytics_starter_kit)
|
|
421
582
|
|
|
@@ -99,6 +99,22 @@ def api_post(
|
|
|
99
99
|
return {}
|
|
100
100
|
|
|
101
101
|
|
|
102
|
+
def _get_migrate_to_forward_error_message(result: dict[str, Any]) -> str:
|
|
103
|
+
error = result.get("error")
|
|
104
|
+
if error:
|
|
105
|
+
return str(error)
|
|
106
|
+
|
|
107
|
+
deployment = result.get("deployment") or {}
|
|
108
|
+
deployment_errors = deployment.get("errors") or []
|
|
109
|
+
error_messages = [
|
|
110
|
+
str(item.get("error")) for item in deployment_errors if isinstance(item, dict) and item.get("error")
|
|
111
|
+
]
|
|
112
|
+
if error_messages:
|
|
113
|
+
return "; ".join(error_messages)
|
|
114
|
+
|
|
115
|
+
return "Migration to Tinybird Forward failed"
|
|
116
|
+
|
|
117
|
+
|
|
102
118
|
def _is_first_deployment_with_seed_live(host: Optional[str], headers: dict) -> bool:
|
|
103
119
|
"""Best-effort check for first real deployment when seed deployment (id=0) is still live."""
|
|
104
120
|
try:
|
|
@@ -134,8 +150,43 @@ def _get_deployment_job(client: TinyB, deployment_id: Optional[Union[str, int]])
|
|
|
134
150
|
return None
|
|
135
151
|
|
|
136
152
|
|
|
153
|
+
def migrate_to_forward_workspace(client: TinyB, output: str = "human", dry_run: bool = False) -> None:
|
|
154
|
+
headers = {"Authorization": f"Bearer {client.token}"}
|
|
155
|
+
params = {"dry_run": dry_run}
|
|
156
|
+
result = api_post(f"{client.host}/v1/migrate-to-forward", headers=headers, params=params)
|
|
157
|
+
|
|
158
|
+
if result.get("result") != "success":
|
|
159
|
+
error_message = _get_migrate_to_forward_error_message(result)
|
|
160
|
+
if output == "json":
|
|
161
|
+
echo_json(result)
|
|
162
|
+
else:
|
|
163
|
+
click.echo(FeedbackManager.error(message=error_message))
|
|
164
|
+
sys_exit("deployment_error", error_message)
|
|
165
|
+
|
|
166
|
+
if dry_run:
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
if output == "json":
|
|
170
|
+
echo_json(result)
|
|
171
|
+
return
|
|
172
|
+
|
|
173
|
+
click.echo(FeedbackManager.success(message="✓ Workspace migrated to Tinybird Forward"))
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def _should_show_migrate_to_forward_hint(client: TinyB, env: Optional[str]) -> bool:
|
|
177
|
+
if env != "cloud":
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
try:
|
|
181
|
+
workspace_info = client.workspace_info(version="v0")
|
|
182
|
+
except Exception:
|
|
183
|
+
logging.exception("Error reading workspace info while deciding migrate-to-forward hint")
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
return not workspace_info.get("is_forward", False) and not workspace_info.get("is_branch", False)
|
|
187
|
+
|
|
188
|
+
|
|
137
189
|
# TODO(eclbg): This logic should be in the server, and there should be a dedicated endpoint for promoting a deployment
|
|
138
|
-
# potato
|
|
139
190
|
def promote_deployment(
|
|
140
191
|
host: Optional[str],
|
|
141
192
|
headers: dict,
|
|
@@ -285,9 +336,12 @@ def create_deployment(
|
|
|
285
336
|
check: Optional[bool] = None,
|
|
286
337
|
allow_destructive_operations: Optional[bool] = None,
|
|
287
338
|
ingest_hint: Optional[bool] = True,
|
|
339
|
+
show_migrate_to_forward_hint: bool = True,
|
|
288
340
|
output: Optional[str] = "human",
|
|
289
341
|
env: Optional[str] = "cloud",
|
|
290
|
-
|
|
342
|
+
return_check_result: bool = False,
|
|
343
|
+
skip_forward_workspace_validation: bool = False,
|
|
344
|
+
) -> Optional[Dict[str, Any]]:
|
|
291
345
|
# TODO: This code is duplicated in build_server.py
|
|
292
346
|
# Should be refactored to be shared
|
|
293
347
|
MULTIPART_BOUNDARY_DATA_PROJECT = "data_project://"
|
|
@@ -342,6 +396,8 @@ def create_deployment(
|
|
|
342
396
|
params["auto_promote"] = "true"
|
|
343
397
|
if allow_destructive_operations:
|
|
344
398
|
params["allow_destructive_operations"] = "true"
|
|
399
|
+
if skip_forward_workspace_validation:
|
|
400
|
+
params["skip_forward_workspace_validation"] = "true"
|
|
345
401
|
|
|
346
402
|
deployment_request_sent = True
|
|
347
403
|
result = api_post(
|
|
@@ -388,10 +444,27 @@ def create_deployment(
|
|
|
388
444
|
|
|
389
445
|
status = result.get("result")
|
|
390
446
|
if check:
|
|
391
|
-
if status
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
447
|
+
if status in {"success", "no_changes"}:
|
|
448
|
+
if status == "success":
|
|
449
|
+
click.echo(FeedbackManager.success(message="\n✓ Deployment is valid"))
|
|
450
|
+
|
|
451
|
+
if (
|
|
452
|
+
output == "human"
|
|
453
|
+
and show_migrate_to_forward_hint
|
|
454
|
+
and _should_show_migrate_to_forward_hint(client, env)
|
|
455
|
+
):
|
|
456
|
+
click.echo(
|
|
457
|
+
FeedbackManager.info(
|
|
458
|
+
message=(
|
|
459
|
+
"You can now migrate this Tinybird Classic workspace to Forward "
|
|
460
|
+
"with `tb migrate-to-forward`."
|
|
461
|
+
)
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
|
|
465
|
+
if return_check_result:
|
|
466
|
+
return {"status": status, "deployment": deployment}
|
|
467
|
+
|
|
395
468
|
sys.exit(0)
|
|
396
469
|
|
|
397
470
|
click.echo(FeedbackManager.error(message="\n✗ Deployment is not valid"))
|
|
@@ -439,7 +512,10 @@ def create_deployment(
|
|
|
439
512
|
except Exception as e:
|
|
440
513
|
click.echo(FeedbackManager.error_exception(error=e))
|
|
441
514
|
|
|
442
|
-
if
|
|
515
|
+
if check:
|
|
516
|
+
sys_exit("deployment_error", "Deployment check failed")
|
|
517
|
+
|
|
518
|
+
if not deployment:
|
|
443
519
|
sys_exit("deployment_error", "Deployment failed")
|
|
444
520
|
except KeyboardInterrupt:
|
|
445
521
|
if deployment_request_sent and not check:
|
|
@@ -468,7 +544,7 @@ def create_deployment(
|
|
|
468
544
|
if not deployment:
|
|
469
545
|
click.echo(FeedbackManager.error(message="Error parsing deployment from response"))
|
|
470
546
|
sys_exit("deployment_error", "Error parsing deployment from response")
|
|
471
|
-
return
|
|
547
|
+
return None
|
|
472
548
|
|
|
473
549
|
status = deployment.get("status")
|
|
474
550
|
errors = deployment.get("errors")
|
|
@@ -563,6 +639,8 @@ def create_deployment(
|
|
|
563
639
|
if output == "json" and deployment:
|
|
564
640
|
echo_json(deployment, 8)
|
|
565
641
|
|
|
642
|
+
return None
|
|
643
|
+
|
|
566
644
|
|
|
567
645
|
def _build_data_movement_message(kind: str, source_mv_name: Optional[str]) -> str:
|
|
568
646
|
if kind == "backfill_with_mv_queries":
|
|
@@ -58,11 +58,10 @@ async def release_ls() -> None:
|
|
|
58
58
|
async def print_releases(config: CLIConfig):
|
|
59
59
|
response = await config.get_client().releases(config["id"])
|
|
60
60
|
|
|
61
|
-
table: List[Tuple[str, str, str, str, str]] = [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
61
|
+
table: List[Tuple[str, str, str, str, str]] = [
|
|
62
|
+
(release["created_at"], release["semver"], release["status"], release["commit"], release["rollback"])
|
|
63
|
+
for release in response["releases"]
|
|
64
|
+
]
|
|
66
65
|
|
|
67
66
|
columns = ["created_at", "semver", "status", "commit", "rollback release"]
|
|
68
67
|
click.echo(FeedbackManager.info_releases())
|
|
@@ -867,9 +867,7 @@ async def sql(
|
|
|
867
867
|
if format_ == "json":
|
|
868
868
|
click.echo(json.dumps(res, indent=8))
|
|
869
869
|
else:
|
|
870
|
-
dd = []
|
|
871
|
-
for d in res["data"]:
|
|
872
|
-
dd.append(d.values())
|
|
870
|
+
dd = [d.values() for d in res["data"]]
|
|
873
871
|
echo_safe_humanfriendly_tables_format_smart_table(dd, column_names=res["data"][0].keys())
|
|
874
872
|
else:
|
|
875
873
|
click.echo(FeedbackManager.info_no_rows())
|
|
@@ -747,10 +747,12 @@ async def create_workspace_branch(
|
|
|
747
747
|
async def print_data_branch_summary(client, job_id, response=None):
|
|
748
748
|
response = await client.job(job_id) if job_id else response or {"partitions": []}
|
|
749
749
|
columns = ["Data Source", "Partition", "Status", "Error"]
|
|
750
|
-
table = []
|
|
750
|
+
table: list[list] = []
|
|
751
751
|
for partition in response["partitions"]:
|
|
752
|
-
|
|
753
|
-
|
|
752
|
+
table.extend(
|
|
753
|
+
[partition["datasource"]["name"], p["partition"], p["status"], p.get("error", "")]
|
|
754
|
+
for p in partition["partitions"]
|
|
755
|
+
)
|
|
754
756
|
echo_safe_humanfriendly_tables_format_smart_table(table, column_names=columns)
|
|
755
757
|
|
|
756
758
|
|
|
@@ -36,9 +36,7 @@ async def jobs_ls(ctx: Context, status: str) -> None:
|
|
|
36
36
|
jobs = await client.jobs(status=status)
|
|
37
37
|
columns = ["id", "kind", "status", "created at", "updated at", "job url"]
|
|
38
38
|
click.echo(FeedbackManager.info_jobs())
|
|
39
|
-
table = []
|
|
40
|
-
for j in jobs:
|
|
41
|
-
table.append([j[c.replace(" ", "_")] for c in columns])
|
|
39
|
+
table = [[j[c.replace(" ", "_")] for c in columns] for j in jobs]
|
|
42
40
|
echo_safe_humanfriendly_tables_format_smart_table(table, column_names=columns)
|
|
43
41
|
click.echo("\n")
|
|
44
42
|
|
|
@@ -28,11 +28,10 @@ async def tag_ls(ctx: Context, tag_name: Optional[str]) -> None:
|
|
|
28
28
|
the_tag = [tag for tag in response["tags"] if tag["name"] == tag_name]
|
|
29
29
|
|
|
30
30
|
columns = ["name", "id", "type"]
|
|
31
|
-
table = []
|
|
31
|
+
table: list[list] = []
|
|
32
32
|
|
|
33
33
|
if len(the_tag) > 0:
|
|
34
|
-
for resource in the_tag[0]["resources"]
|
|
35
|
-
table.append([resource["name"], resource["id"], resource["type"]])
|
|
34
|
+
table.extend([resource["name"], resource["id"], resource["type"]] for resource in the_tag[0]["resources"])
|
|
36
35
|
|
|
37
36
|
click.echo(FeedbackManager.info_tag_resources(tag_name=tag_name))
|
|
38
37
|
echo_safe_humanfriendly_tables_format_smart_table(table, column_names=columns)
|
|
@@ -55,19 +55,18 @@ async def workspace_ls(ctx: Context) -> None:
|
|
|
55
55
|
raise CLIWorkspaceException(FeedbackManager.error_unable_to_identify_main_workspace())
|
|
56
56
|
|
|
57
57
|
columns = ["name", "id", "role", "plan", "current"]
|
|
58
|
-
table = []
|
|
59
58
|
click.echo(FeedbackManager.info_workspaces())
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
[
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
60
|
+
table = [
|
|
61
|
+
[
|
|
62
|
+
workspace["name"],
|
|
63
|
+
workspace["id"],
|
|
64
|
+
workspace["role"],
|
|
65
|
+
_get_workspace_plan_name(workspace["plan"]),
|
|
66
|
+
current_main_workspace["id"] == workspace["id"],
|
|
67
|
+
]
|
|
68
|
+
for workspace in response["workspaces"]
|
|
69
|
+
]
|
|
71
70
|
|
|
72
71
|
echo_safe_humanfriendly_tables_format_smart_table(table, column_names=columns)
|
|
73
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: tinybird
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.5.dev0
|
|
4
4
|
Summary: Tinybird Command Line Tool
|
|
5
5
|
Home-page: https://www.tinybird.co/docs/forward/commands
|
|
6
6
|
Author: Tinybird
|
|
@@ -52,6 +52,11 @@ The Tinybird command-line tool allows you to use all the Tinybird functionality
|
|
|
52
52
|
Changelog
|
|
53
53
|
----------
|
|
54
54
|
|
|
55
|
+
4.5.4
|
|
56
|
+
*******
|
|
57
|
+
|
|
58
|
+
- `Added` `tb migrate-to-forward` to help users migrate Classic workspaces to Forward
|
|
59
|
+
|
|
55
60
|
4.5.3
|
|
56
61
|
*******
|
|
57
62
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/build_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/format_connection.py
RENAMED
|
File without changes
|
{tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb/modules/datafile/format_datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tinybird-4.5.4.dev0 → tinybird-4.5.5.dev0}/tinybird/tb_cli_modules/tinyunit/tinyunit_lib.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|