tinybird 0.0.1.dev4__py3-none-any.whl → 0.0.1.dev6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tinybird might be problematic. Click here for more details.
- tinybird/__cli__.py +7 -8
- tinybird/check_pypi.py +1 -1
- tinybird/feedback_manager.py +2 -2
- tinybird/tb/cli.py +28 -0
- tinybird/{tb_cli_modules → tb/modules}/auth.py +5 -5
- tinybird/{tb_cli_modules → tb/modules}/branch.py +6 -5
- tinybird/{tb_cli_modules → tb/modules}/build.py +8 -26
- tinybird/tb/modules/cicd.py +271 -0
- tinybird/{tb_cli_modules → tb/modules}/cli.py +24 -91
- tinybird/tb/modules/common.py +2098 -0
- tinybird/tb/modules/config.py +352 -0
- tinybird/{tb_cli_modules → tb/modules}/connection.py +4 -4
- tinybird/{tb_cli_modules → tb/modules}/create.py +11 -7
- tinybird/{datafile.py → tb/modules/datafile.py} +6 -7
- tinybird/{tb_cli_modules → tb/modules}/datasource.py +7 -6
- tinybird/tb/modules/exceptions.py +91 -0
- tinybird/{tb_cli_modules → tb/modules}/fmt.py +3 -3
- tinybird/{tb_cli_modules → tb/modules}/job.py +3 -3
- tinybird/{tb_cli_modules → tb/modules}/llm.py +14 -13
- tinybird/{tb_cli_modules → tb/modules}/local.py +11 -6
- tinybird/tb/modules/mock.py +53 -0
- tinybird/{tb_cli_modules → tb/modules}/pipe.py +5 -5
- tinybird/{tb_cli_modules → tb/modules}/prompts.py +3 -0
- tinybird/tb/modules/regions.py +9 -0
- tinybird/tb/modules/table.py +185 -0
- tinybird/{tb_cli_modules → tb/modules}/tag.py +2 -2
- tinybird/tb/modules/telemetry.py +310 -0
- tinybird/{tb_cli_modules → tb/modules}/test.py +5 -5
- tinybird/{tb_cli_modules → tb/modules}/tinyunit/tinyunit.py +1 -1
- tinybird/{tb_cli_modules → tb/modules}/token.py +3 -3
- tinybird/{tb_cli_modules → tb/modules}/workspace.py +5 -5
- tinybird/{tb_cli_modules → tb/modules}/workspace_members.py +4 -4
- tinybird/tb_cli_modules/common.py +9 -7
- tinybird/tb_cli_modules/config.py +0 -8
- {tinybird-0.0.1.dev4.dist-info → tinybird-0.0.1.dev6.dist-info}/METADATA +1 -1
- tinybird-0.0.1.dev6.dist-info/RECORD +58 -0
- tinybird-0.0.1.dev6.dist-info/entry_points.txt +2 -0
- tinybird/tb_cli.py +0 -27
- tinybird-0.0.1.dev4.dist-info/RECORD +0 -50
- tinybird-0.0.1.dev4.dist-info/entry_points.txt +0 -2
- /tinybird/{tb_cli_modules → tb/modules}/tinyunit/tinyunit_lib.py +0 -0
- {tinybird-0.0.1.dev4.dist-info → tinybird-0.0.1.dev6.dist-info}/WHEEL +0 -0
- {tinybird-0.0.1.dev4.dist-info → tinybird-0.0.1.dev6.dist-info}/top_level.txt +0 -0
tinybird/__cli__.py
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
__revision__ = '388c81a'
|
|
1
|
+
__name__ = "tinybird-cli"
|
|
2
|
+
__description__ = "Tinybird Command Line Tool"
|
|
3
|
+
__url__ = "https://www.tinybird.co/docs/cli/introduction.html"
|
|
4
|
+
__author__ = "Tinybird"
|
|
5
|
+
__author_email__ = "support@tinybird.co"
|
|
6
|
+
__version__ = "x.y.z"
|
|
7
|
+
__revision__ = "xxxxxxxxx"
|
tinybird/check_pypi.py
CHANGED
|
@@ -6,7 +6,7 @@ from tinybird.feedback_manager import FeedbackManager
|
|
|
6
6
|
from tinybird.syncasync import sync_to_async
|
|
7
7
|
from tinybird.tb_cli_modules.common import CLIException, getenv_bool
|
|
8
8
|
|
|
9
|
-
PYPY_URL = "https://pypi.org/pypi/tinybird
|
|
9
|
+
PYPY_URL = "https://pypi.org/pypi/tinybird/json"
|
|
10
10
|
requests_get = sync_to_async(requests.get, thread_sensitive=False)
|
|
11
11
|
|
|
12
12
|
|
tinybird/feedback_manager.py
CHANGED
|
@@ -565,9 +565,9 @@ Ready? """
|
|
|
565
565
|
)
|
|
566
566
|
warning_fixture_not_found = warning_message("** Warning: No fixture found for the datasource {datasource_name}")
|
|
567
567
|
warning_update_version = warning_message(
|
|
568
|
-
'** UPDATE AVAILABLE: please run "pip install tinybird
|
|
568
|
+
'** UPDATE AVAILABLE: please run "pip install tinybird=={latest_version}" to update or `export TB_VERSION_WARNING=0` to skip the check.'
|
|
569
569
|
)
|
|
570
|
-
warning_current_version = warning_message("** current: tinybird
|
|
570
|
+
warning_current_version = warning_message("** current: tinybird {current_version}\n")
|
|
571
571
|
warning_confirm_truncate_datasource = prompt_message(
|
|
572
572
|
"Do you want to truncate {datasource}? Once truncated, your data can't be recovered"
|
|
573
573
|
)
|
tinybird/tb/cli.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
if sys.platform == "win32":
|
|
5
|
+
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
|
6
|
+
|
|
7
|
+
import tinybird.tb.modules.auth
|
|
8
|
+
import tinybird.tb.modules.branch
|
|
9
|
+
import tinybird.tb.modules.build
|
|
10
|
+
import tinybird.tb.modules.cli
|
|
11
|
+
import tinybird.tb.modules.common
|
|
12
|
+
import tinybird.tb.modules.connection
|
|
13
|
+
import tinybird.tb.modules.create
|
|
14
|
+
import tinybird.tb.modules.datasource
|
|
15
|
+
import tinybird.tb.modules.fmt
|
|
16
|
+
import tinybird.tb.modules.job
|
|
17
|
+
import tinybird.tb.modules.mock
|
|
18
|
+
import tinybird.tb.modules.pipe
|
|
19
|
+
import tinybird.tb.modules.tag
|
|
20
|
+
import tinybird.tb.modules.test
|
|
21
|
+
import tinybird.tb.modules.token
|
|
22
|
+
import tinybird.tb.modules.workspace
|
|
23
|
+
import tinybird.tb.modules.workspace_members
|
|
24
|
+
|
|
25
|
+
cli = tinybird.tb.modules.cli.cli
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
cli()
|
|
@@ -11,8 +11,8 @@ import humanfriendly.tables
|
|
|
11
11
|
|
|
12
12
|
from tinybird.config import get_display_host
|
|
13
13
|
from tinybird.feedback_manager import FeedbackManager
|
|
14
|
-
from tinybird.
|
|
15
|
-
from tinybird.
|
|
14
|
+
from tinybird.tb.modules.cli import cli
|
|
15
|
+
from tinybird.tb.modules.common import (
|
|
16
16
|
configure_connector,
|
|
17
17
|
coro,
|
|
18
18
|
echo_safe_humanfriendly_tables_format_smart_table,
|
|
@@ -21,9 +21,9 @@ from tinybird.tb_cli_modules.common import (
|
|
|
21
21
|
try_authenticate,
|
|
22
22
|
try_update_config_with_remote,
|
|
23
23
|
)
|
|
24
|
-
from tinybird.
|
|
25
|
-
from tinybird.
|
|
26
|
-
from tinybird.
|
|
24
|
+
from tinybird.tb.modules.config import CLIConfig, ConfigValueOrigin
|
|
25
|
+
from tinybird.tb.modules.exceptions import CLIAuthException
|
|
26
|
+
from tinybird.tb.modules.regions import Region
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
@cli.group(invoke_without_command=True)
|
|
@@ -11,10 +11,9 @@ import aiofiles
|
|
|
11
11
|
import click
|
|
12
12
|
import yaml
|
|
13
13
|
|
|
14
|
-
from tinybird.datafile import create_release, wait_job
|
|
15
14
|
from tinybird.feedback_manager import FeedbackManager
|
|
16
|
-
from tinybird.
|
|
17
|
-
from tinybird.
|
|
15
|
+
from tinybird.tb.modules.cli import cli
|
|
16
|
+
from tinybird.tb.modules.common import (
|
|
18
17
|
MAIN_BRANCH,
|
|
19
18
|
OLDEST_ROLLBACK,
|
|
20
19
|
coro,
|
|
@@ -35,9 +34,11 @@ from tinybird.tb_cli_modules.common import (
|
|
|
35
34
|
switch_to_workspace_by_user_workspace_data,
|
|
36
35
|
switch_workspace,
|
|
37
36
|
try_update_config_with_remote,
|
|
37
|
+
wait_job,
|
|
38
38
|
)
|
|
39
|
-
from tinybird.
|
|
40
|
-
from tinybird.
|
|
39
|
+
from tinybird.tb.modules.config import CLIConfig
|
|
40
|
+
from tinybird.tb.modules.datafile import create_release
|
|
41
|
+
from tinybird.tb.modules.exceptions import CLIBranchException, CLIException, CLIReleaseException
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
@cli.group(hidden=True)
|
|
@@ -13,7 +13,12 @@ from watchdog.observers import Observer
|
|
|
13
13
|
import tinybird.context as context
|
|
14
14
|
from tinybird.client import TinyB
|
|
15
15
|
from tinybird.config import FeatureFlags
|
|
16
|
-
from tinybird.
|
|
16
|
+
from tinybird.feedback_manager import FeedbackManager, bcolors
|
|
17
|
+
from tinybird.tb.modules.cli import cli
|
|
18
|
+
from tinybird.tb.modules.common import (
|
|
19
|
+
coro,
|
|
20
|
+
)
|
|
21
|
+
from tinybird.tb.modules.datafile import (
|
|
17
22
|
ParseException,
|
|
18
23
|
folder_build,
|
|
19
24
|
get_project_filenames,
|
|
@@ -21,17 +26,10 @@ from tinybird.datafile import (
|
|
|
21
26
|
parse_datasource,
|
|
22
27
|
parse_pipe,
|
|
23
28
|
)
|
|
24
|
-
from tinybird.
|
|
25
|
-
from tinybird.tb_cli_modules.cli import cli
|
|
26
|
-
from tinybird.tb_cli_modules.common import (
|
|
27
|
-
coro,
|
|
28
|
-
)
|
|
29
|
-
from tinybird.tb_cli_modules.config import CLIConfig
|
|
30
|
-
from tinybird.tb_cli_modules.llm import LLM
|
|
31
|
-
from tinybird.tb_cli_modules.local import (
|
|
29
|
+
from tinybird.tb.modules.local import (
|
|
32
30
|
get_tinybird_local_client,
|
|
33
31
|
)
|
|
34
|
-
from tinybird.
|
|
32
|
+
from tinybird.tb.modules.table import format_table
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
class FileChangeHandler(FileSystemEventHandler):
|
|
@@ -153,22 +151,6 @@ async def build(
|
|
|
153
151
|
only_pipes=only_pipes,
|
|
154
152
|
)
|
|
155
153
|
|
|
156
|
-
for filename in filenames:
|
|
157
|
-
if filename.endswith(".datasource") and not skip_datasources:
|
|
158
|
-
ds_path = Path(filename)
|
|
159
|
-
ds_name = ds_path.stem
|
|
160
|
-
datasource_content = ds_path.read_text()
|
|
161
|
-
llm_config = CLIConfig.get_llm_config()
|
|
162
|
-
llm = LLM(key=llm_config["api_key"])
|
|
163
|
-
has_json_path = "`json:" in datasource_content
|
|
164
|
-
|
|
165
|
-
if has_json_path:
|
|
166
|
-
await llm.generate_sql_sample_data(
|
|
167
|
-
tb_client=tb_client,
|
|
168
|
-
datasource_name=ds_name,
|
|
169
|
-
datasource_content=datasource_content,
|
|
170
|
-
)
|
|
171
|
-
|
|
172
154
|
if watch:
|
|
173
155
|
filename = filenames[0]
|
|
174
156
|
if filename.endswith(".pipe"):
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from os import getcwd
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Dict, List, Optional, Type, Union
|
|
5
|
+
|
|
6
|
+
import click
|
|
7
|
+
from tornado.template import Template
|
|
8
|
+
|
|
9
|
+
from tinybird.feedback_manager import FeedbackManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Provider(Enum):
|
|
13
|
+
GitHub = 0
|
|
14
|
+
GitLab = 1
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
WORKFLOW_VERSION = "v3.1.0"
|
|
18
|
+
|
|
19
|
+
DEFAULT_REQUIREMENTS_FILE = "tinybird-cli>=5,<6"
|
|
20
|
+
|
|
21
|
+
GITHUB_CI_YML = """
|
|
22
|
+
name: Tinybird - CI Workflow
|
|
23
|
+
|
|
24
|
+
on:
|
|
25
|
+
workflow_dispatch:
|
|
26
|
+
pull_request:
|
|
27
|
+
branches:
|
|
28
|
+
- main
|
|
29
|
+
- master
|
|
30
|
+
types: [opened, reopened, labeled, unlabeled, synchronize, closed]{% if data_project_dir != '.' %}
|
|
31
|
+
paths:
|
|
32
|
+
- '{{ data_project_dir }}/**'{% end %}
|
|
33
|
+
|
|
34
|
+
concurrency: ${{! github.workflow }}-${{! github.event.pull_request.number }}
|
|
35
|
+
|
|
36
|
+
jobs:
|
|
37
|
+
ci:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
defaults:
|
|
40
|
+
run:
|
|
41
|
+
working-directory: '{{ data_project_dir }}'
|
|
42
|
+
services:
|
|
43
|
+
tinybird:
|
|
44
|
+
image: tinybirdco/tinybird-local:latest
|
|
45
|
+
ports:
|
|
46
|
+
- 80:80
|
|
47
|
+
steps:
|
|
48
|
+
- uses: actions/checkout@v3
|
|
49
|
+
- name: Install Tinybird CLI
|
|
50
|
+
run: curl -LsSf https://api.tinybird.co/static/install.sh | sh
|
|
51
|
+
- name: Build project
|
|
52
|
+
run: tb build
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
GITLAB_YML = """
|
|
57
|
+
include:
|
|
58
|
+
- local: .gitlab/tinybird/*.yml
|
|
59
|
+
|
|
60
|
+
stages:
|
|
61
|
+
- tests
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
GITLAB_CI_YML = """
|
|
66
|
+
tinybird_ci_workflow:
|
|
67
|
+
stage: tests
|
|
68
|
+
interruptible: true
|
|
69
|
+
needs: []
|
|
70
|
+
rules:
|
|
71
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event"{% if data_project_dir != '.' %}
|
|
72
|
+
changes:
|
|
73
|
+
- .gitlab/tinybird/*
|
|
74
|
+
- {{ data_project_dir }}/*
|
|
75
|
+
- {{ data_project_dir }}/**/*{% end %}
|
|
76
|
+
before_script:
|
|
77
|
+
- curl -LsSf https://api.tinybird.co/static/install.sh | sh
|
|
78
|
+
script:
|
|
79
|
+
- cd $CI_PROJECT_DIR/{{ data_project_dir }}
|
|
80
|
+
- tb build
|
|
81
|
+
services:
|
|
82
|
+
- name: tinybirdco/tinybird-local:latest
|
|
83
|
+
alias: tinybird-local
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
EXEC_TEST_SH = """
|
|
88
|
+
#!/usr/bin/env bash
|
|
89
|
+
set -euxo pipefail
|
|
90
|
+
|
|
91
|
+
export TB_VERSION_WARNING=0
|
|
92
|
+
|
|
93
|
+
run_test() {
|
|
94
|
+
t=$1
|
|
95
|
+
echo "** Running $t **"
|
|
96
|
+
echo "** $(cat $t)"
|
|
97
|
+
tmpfile=$(mktemp)
|
|
98
|
+
retries=0
|
|
99
|
+
TOTAL_RETRIES=3
|
|
100
|
+
|
|
101
|
+
# When appending fixtures, we need to retry in case of the data is not replicated in time
|
|
102
|
+
while [ $retries -lt $TOTAL_RETRIES ]; do
|
|
103
|
+
# Run the test and store the output in a temporary file
|
|
104
|
+
bash $t $2 >$tmpfile
|
|
105
|
+
exit_code=$?
|
|
106
|
+
if [ "$exit_code" -eq 0 ]; then
|
|
107
|
+
# If the test passed, break the loop
|
|
108
|
+
if diff -B ${t}.result $tmpfile >/dev/null 2>&1; then
|
|
109
|
+
break
|
|
110
|
+
# If the test failed, increment the retries counter and try again
|
|
111
|
+
else
|
|
112
|
+
retries=$((retries+1))
|
|
113
|
+
fi
|
|
114
|
+
# If the bash command failed, print an error message and break the loop
|
|
115
|
+
else
|
|
116
|
+
break
|
|
117
|
+
fi
|
|
118
|
+
done
|
|
119
|
+
|
|
120
|
+
if diff -B ${t}.result $tmpfile >/dev/null 2>&1; then
|
|
121
|
+
echo "✅ Test $t passed"
|
|
122
|
+
rm $tmpfile
|
|
123
|
+
return 0
|
|
124
|
+
elif [ $retries -eq $TOTAL_RETRIES ]; then
|
|
125
|
+
echo "🚨 ERROR: Test $t failed, diff:";
|
|
126
|
+
diff -B ${t}.result $tmpfile
|
|
127
|
+
rm $tmpfile
|
|
128
|
+
return 1
|
|
129
|
+
else
|
|
130
|
+
echo "🚨 ERROR: Test $t failed with bash command exit code $?"
|
|
131
|
+
cat $tmpfile
|
|
132
|
+
rm $tmpfile
|
|
133
|
+
return 1
|
|
134
|
+
fi
|
|
135
|
+
echo ""
|
|
136
|
+
}
|
|
137
|
+
export -f run_test
|
|
138
|
+
|
|
139
|
+
fail=0
|
|
140
|
+
find ./tests -name "*.test" -print0 | xargs -0 -I {} -P 4 bash -c 'run_test "$@"' _ {} || fail=1
|
|
141
|
+
|
|
142
|
+
if [ $fail == 1 ]; then
|
|
143
|
+
exit -1;
|
|
144
|
+
fi
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
APPEND_FIXTURES_SH = """
|
|
148
|
+
#!/usr/bin/env bash
|
|
149
|
+
set -euxo pipefail
|
|
150
|
+
|
|
151
|
+
directory="datasources/fixtures"
|
|
152
|
+
extensions=("csv" "ndjson")
|
|
153
|
+
|
|
154
|
+
absolute_directory=$(realpath "$directory")
|
|
155
|
+
|
|
156
|
+
for extension in "${extensions[@]}"; do
|
|
157
|
+
file_list=$(find "$absolute_directory" -type f -name "*.$extension")
|
|
158
|
+
|
|
159
|
+
for file_path in $file_list; do
|
|
160
|
+
file_name=$(basename "$file_path")
|
|
161
|
+
file_name_without_extension="${file_name%.*}"
|
|
162
|
+
|
|
163
|
+
command="tb datasource append $file_name_without_extension datasources/fixtures/$file_name"
|
|
164
|
+
echo $command
|
|
165
|
+
$command
|
|
166
|
+
done
|
|
167
|
+
done
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class CICDFile:
|
|
172
|
+
def __init__(
|
|
173
|
+
self,
|
|
174
|
+
template: str,
|
|
175
|
+
file_name: str,
|
|
176
|
+
dir_path: Optional[str] = None,
|
|
177
|
+
warning_message: Optional[str] = None,
|
|
178
|
+
):
|
|
179
|
+
self.template = template
|
|
180
|
+
self.file_name = file_name
|
|
181
|
+
self.dir_path = dir_path
|
|
182
|
+
self.warning_message = warning_message
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def full_path(self) -> str:
|
|
186
|
+
return f"{self.dir_path}/{self.file_name}" if self.dir_path else self.file_name
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class CICDGeneratorBase:
|
|
190
|
+
cicd_files: List[CICDFile] = []
|
|
191
|
+
|
|
192
|
+
def __call__(self, path: str, params: Dict[str, Any]):
|
|
193
|
+
for cicd_file in self.cicd_files:
|
|
194
|
+
if cicd_file.dir_path:
|
|
195
|
+
Path(f"{path}/{cicd_file.dir_path}").mkdir(parents=True, exist_ok=True)
|
|
196
|
+
content = Template(cicd_file.template).generate(**params)
|
|
197
|
+
if Path(f"{path}/{cicd_file.full_path}").exists():
|
|
198
|
+
continue
|
|
199
|
+
with open(f"{path}/{cicd_file.full_path}", "wb") as f:
|
|
200
|
+
f.write(content)
|
|
201
|
+
click.echo(FeedbackManager.info_cicd_file_generated(file_path=cicd_file.full_path))
|
|
202
|
+
if cicd_file.warning_message is not None:
|
|
203
|
+
return FeedbackManager.warning_for_cicd_file(
|
|
204
|
+
file_name=cicd_file.file_name, warning_message=cicd_file.warning_message.format(**params)
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
def is_already_generated(self, path: str) -> bool:
|
|
208
|
+
for cicd_file in self.cicd_files:
|
|
209
|
+
if cicd_file.file_name and Path(f"{path}/{cicd_file.full_path}").exists():
|
|
210
|
+
return True
|
|
211
|
+
return False
|
|
212
|
+
|
|
213
|
+
@classmethod
|
|
214
|
+
def build_generator(cls, provider: str) -> Union["GitHubCICDGenerator", "GitLabCICDGenerator"]:
|
|
215
|
+
builder: Dict[str, Union[Type[GitHubCICDGenerator], Type[GitLabCICDGenerator]]] = {
|
|
216
|
+
Provider.GitHub.name: GitHubCICDGenerator,
|
|
217
|
+
Provider.GitLab.name: GitLabCICDGenerator,
|
|
218
|
+
}
|
|
219
|
+
return builder[provider]()
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
class GitHubCICDGenerator(CICDGeneratorBase):
|
|
223
|
+
cicd_files = [
|
|
224
|
+
CICDFile(
|
|
225
|
+
template=GITHUB_CI_YML,
|
|
226
|
+
file_name="tinybird-ci.yml",
|
|
227
|
+
dir_path=".github/workflows",
|
|
228
|
+
),
|
|
229
|
+
]
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
class GitLabCICDGenerator(CICDGeneratorBase):
|
|
233
|
+
cicd_files = [
|
|
234
|
+
CICDFile(
|
|
235
|
+
template=GITLAB_YML,
|
|
236
|
+
file_name=".gitlab-ci.yml",
|
|
237
|
+
dir_path=".",
|
|
238
|
+
),
|
|
239
|
+
CICDFile(
|
|
240
|
+
template=GITLAB_CI_YML,
|
|
241
|
+
file_name="tinybird-ci.yml",
|
|
242
|
+
dir_path=".gitlab/tinybird",
|
|
243
|
+
warning_message="Make sure to import the file in your .gitlab-ci.yml file, e.g., `include: '.gitlab/tinybird/*.yml'`.",
|
|
244
|
+
),
|
|
245
|
+
]
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
async def init_cicd(
|
|
249
|
+
path: Optional[str] = None,
|
|
250
|
+
data_project_dir: Optional[str] = None,
|
|
251
|
+
):
|
|
252
|
+
for provider in Provider:
|
|
253
|
+
path = path if path else getcwd()
|
|
254
|
+
data_project_dir = data_project_dir if data_project_dir else "."
|
|
255
|
+
generator = CICDGeneratorBase.build_generator(provider.name)
|
|
256
|
+
params = {
|
|
257
|
+
"data_project_dir": data_project_dir,
|
|
258
|
+
"workflow_version": WORKFLOW_VERSION,
|
|
259
|
+
}
|
|
260
|
+
warning_message = generator(path, params)
|
|
261
|
+
if warning_message:
|
|
262
|
+
click.echo(warning_message)
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
async def check_cicd_exists(path: Optional[str] = None) -> Optional[Provider]:
|
|
266
|
+
path = path if path else getcwd()
|
|
267
|
+
for provider in Provider:
|
|
268
|
+
generator = CICDGeneratorBase.build_generator(provider.name)
|
|
269
|
+
if generator.is_already_generated(path):
|
|
270
|
+
return provider
|
|
271
|
+
return None
|
|
@@ -10,14 +10,12 @@ import pprint
|
|
|
10
10
|
import re
|
|
11
11
|
import shutil
|
|
12
12
|
import sys
|
|
13
|
-
from datetime import datetime
|
|
14
13
|
from os import environ, getcwd
|
|
15
14
|
from pathlib import Path
|
|
16
15
|
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
|
|
17
16
|
|
|
18
17
|
import click
|
|
19
18
|
import humanfriendly
|
|
20
|
-
import requests
|
|
21
19
|
from click import Context
|
|
22
20
|
from packaging import version
|
|
23
21
|
|
|
@@ -30,7 +28,28 @@ from tinybird.client import (
|
|
|
30
28
|
TinyB,
|
|
31
29
|
)
|
|
32
30
|
from tinybird.config import CURRENT_VERSION, SUPPORTED_CONNECTORS, VERSION, FeatureFlags, get_config
|
|
33
|
-
from tinybird.
|
|
31
|
+
from tinybird.feedback_manager import FeedbackManager
|
|
32
|
+
from tinybird.tb.modules.cicd import check_cicd_exists, init_cicd
|
|
33
|
+
from tinybird.tb.modules.common import (
|
|
34
|
+
OLDEST_ROLLBACK,
|
|
35
|
+
CatchAuthExceptions,
|
|
36
|
+
CLIException,
|
|
37
|
+
_get_tb_client,
|
|
38
|
+
coro,
|
|
39
|
+
create_tb_client,
|
|
40
|
+
echo_safe_format_table,
|
|
41
|
+
folder_init,
|
|
42
|
+
get_current_main_workspace,
|
|
43
|
+
getenv_bool,
|
|
44
|
+
is_major_semver,
|
|
45
|
+
is_post_semver,
|
|
46
|
+
load_connector_config,
|
|
47
|
+
remove_release,
|
|
48
|
+
try_update_config_with_remote,
|
|
49
|
+
wait_job,
|
|
50
|
+
)
|
|
51
|
+
from tinybird.tb.modules.config import CLIConfig
|
|
52
|
+
from tinybird.tb.modules.datafile import (
|
|
34
53
|
AlreadyExistsException,
|
|
35
54
|
CLIGitRelease,
|
|
36
55
|
CLIGitReleaseException,
|
|
@@ -47,30 +66,8 @@ from tinybird.datafile import (
|
|
|
47
66
|
parse_datasource,
|
|
48
67
|
parse_pipe,
|
|
49
68
|
parse_token,
|
|
50
|
-
wait_job,
|
|
51
69
|
)
|
|
52
|
-
from tinybird.
|
|
53
|
-
from tinybird.tb_cli_modules.cicd import check_cicd_exists, init_cicd
|
|
54
|
-
from tinybird.tb_cli_modules.common import (
|
|
55
|
-
OLDEST_ROLLBACK,
|
|
56
|
-
CatchAuthExceptions,
|
|
57
|
-
CLIException,
|
|
58
|
-
_get_tb_client,
|
|
59
|
-
coro,
|
|
60
|
-
create_tb_client,
|
|
61
|
-
echo_safe_humanfriendly_tables_format_smart_table,
|
|
62
|
-
folder_init,
|
|
63
|
-
get_current_main_workspace,
|
|
64
|
-
getenv_bool,
|
|
65
|
-
is_major_semver,
|
|
66
|
-
is_post_semver,
|
|
67
|
-
load_connector_config,
|
|
68
|
-
remove_release,
|
|
69
|
-
try_update_config_with_remote,
|
|
70
|
-
)
|
|
71
|
-
from tinybird.tb_cli_modules.config import CLIConfig
|
|
72
|
-
from tinybird.tb_cli_modules.prompts import sample_data_prompt
|
|
73
|
-
from tinybird.tb_cli_modules.telemetry import add_telemetry_event
|
|
70
|
+
from tinybird.tb.modules.telemetry import add_telemetry_event
|
|
74
71
|
|
|
75
72
|
__old_click_echo = click.echo
|
|
76
73
|
__old_click_secho = click.secho
|
|
@@ -927,7 +924,7 @@ async def sql(
|
|
|
927
924
|
dd = []
|
|
928
925
|
for d in res["data"]:
|
|
929
926
|
dd.append(d.values())
|
|
930
|
-
|
|
927
|
+
echo_safe_format_table(dd, columns=res["meta"])
|
|
931
928
|
else:
|
|
932
929
|
click.echo(FeedbackManager.info_no_rows())
|
|
933
930
|
|
|
@@ -1572,67 +1569,3 @@ async def deploy(
|
|
|
1572
1569
|
raise
|
|
1573
1570
|
except Exception as e:
|
|
1574
1571
|
raise CLIException(str(e))
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
@cli.command()
|
|
1578
|
-
@click.argument("datasource_file", type=click.Path(exists=True))
|
|
1579
|
-
@click.option("--count", type=int, default=10, help="Number of events to send")
|
|
1580
|
-
@click.option("--model", type=str, default=None, help="Model to use for data generation")
|
|
1581
|
-
@click.option("--print-data", is_flag=True, default=False, help="Print the data being sent")
|
|
1582
|
-
@click.pass_context
|
|
1583
|
-
def load_sample_data(ctx: Context, datasource_file: str, count: int, model: Optional[str], print_data: bool) -> None:
|
|
1584
|
-
"""Load sample data into a datasource.
|
|
1585
|
-
|
|
1586
|
-
Args:
|
|
1587
|
-
ctx: Click context object
|
|
1588
|
-
datasource_file: Path to the datasource file to load sample data into
|
|
1589
|
-
"""
|
|
1590
|
-
import llm
|
|
1591
|
-
|
|
1592
|
-
try:
|
|
1593
|
-
# TODO(eclbg): allow passing a datasource name instead of a file
|
|
1594
|
-
datasource_path = Path(datasource_file)
|
|
1595
|
-
if datasource_path.suffix != ".datasource":
|
|
1596
|
-
raise CLIException(FeedbackManager.error_file_extension(filename=datasource_file))
|
|
1597
|
-
|
|
1598
|
-
datasource_name = datasource_path.stem
|
|
1599
|
-
|
|
1600
|
-
response = requests.get("http://localhost:80/tokens")
|
|
1601
|
-
token = response.json()["workspace_admin_token"]
|
|
1602
|
-
|
|
1603
|
-
with open(datasource_file) as f:
|
|
1604
|
-
content = f.read()
|
|
1605
|
-
schema_start = next(i for i, line in enumerate(content.splitlines()) if line.strip().startswith("SCHEMA >"))
|
|
1606
|
-
schema_end = next(
|
|
1607
|
-
i
|
|
1608
|
-
for i, line in enumerate(content.splitlines()[schema_start + 1 :], schema_start + 1)
|
|
1609
|
-
if not line.strip()
|
|
1610
|
-
)
|
|
1611
|
-
schema = "\n".join(content.splitlines()[schema_start:schema_end])
|
|
1612
|
-
llm_model = llm.get_model(model)
|
|
1613
|
-
click.echo(f"Using model: {model}")
|
|
1614
|
-
prompt = sample_data_prompt.format(current_datetime=datetime.now().isoformat(), row_count=count)
|
|
1615
|
-
# prompt = sample_data_with_errors_prompt.format(current_datetime=datetime.now().isoformat()) # This prompt will generate data with errors
|
|
1616
|
-
full_prompt = prompt + "\n\n" + schema
|
|
1617
|
-
sent_events = 0
|
|
1618
|
-
while sent_events < count:
|
|
1619
|
-
click.echo(f"Generating data for '{datasource_name}'")
|
|
1620
|
-
data = llm_model.prompt(full_prompt)
|
|
1621
|
-
|
|
1622
|
-
click.echo(f"Sending data to '{datasource_name}'")
|
|
1623
|
-
headers = {"Authorization": f"Bearer {token}"}
|
|
1624
|
-
if print_data:
|
|
1625
|
-
click.echo(f"Data: {data}")
|
|
1626
|
-
response = requests.post(
|
|
1627
|
-
f"http://localhost:80/v0/events?name={datasource_name}",
|
|
1628
|
-
data=data,
|
|
1629
|
-
headers=headers,
|
|
1630
|
-
)
|
|
1631
|
-
if response.status_code not in (200, 202):
|
|
1632
|
-
raise CLIException(f"Failed to send data: {response.text}")
|
|
1633
|
-
click.echo(f"Response: {response.text}")
|
|
1634
|
-
sent_events += 10
|
|
1635
|
-
click.echo(f"Sent 10 events to datasource '{datasource_name}'")
|
|
1636
|
-
|
|
1637
|
-
except Exception as e:
|
|
1638
|
-
raise CLIException(FeedbackManager.error_exception(error=str(e)))
|