truefoundry 0.2.0rc8__py3-none-any.whl → 0.2.0rc10__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 truefoundry might be problematic. Click here for more details.
- truefoundry/autodeploy/cli.py +63 -41
- truefoundry/autodeploy/constants.py +6 -0
- truefoundry/autodeploy/exception.py +4 -2
- truefoundry/autodeploy/tools/commit.py +6 -2
- truefoundry/autodeploy/tools/docker_run.py +5 -7
- truefoundry/autodeploy/tools/read_file.py +13 -5
- truefoundry/autodeploy/utils/client.py +12 -0
- truefoundry/deploy/cli/cli.py +4 -0
- truefoundry/deploy/cli/deploy.py +45 -57
- {truefoundry-0.2.0rc8.dist-info → truefoundry-0.2.0rc10.dist-info}/METADATA +4 -4
- {truefoundry-0.2.0rc8.dist-info → truefoundry-0.2.0rc10.dist-info}/RECORD +13 -12
- {truefoundry-0.2.0rc8.dist-info → truefoundry-0.2.0rc10.dist-info}/WHEEL +0 -0
- {truefoundry-0.2.0rc8.dist-info → truefoundry-0.2.0rc10.dist-info}/entry_points.txt +0 -0
truefoundry/autodeploy/cli.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import logging
|
|
2
1
|
import os
|
|
3
2
|
import re
|
|
4
3
|
import sys
|
|
@@ -6,19 +5,10 @@ from typing import Dict, Optional
|
|
|
6
5
|
|
|
7
6
|
import click
|
|
8
7
|
import docker
|
|
9
|
-
import
|
|
10
|
-
from dotenv import dotenv_values
|
|
11
|
-
|
|
12
|
-
from truefoundry.autodeploy.exception import GitBinaryNotFoundException
|
|
13
|
-
|
|
14
|
-
try:
|
|
15
|
-
from git import GitCommandError, Repo
|
|
16
|
-
from git.exc import InvalidGitRepositoryError
|
|
17
|
-
except ImportError as ex:
|
|
18
|
-
raise GitBinaryNotFoundException from ex
|
|
19
|
-
|
|
8
|
+
import questionary
|
|
20
9
|
import requests
|
|
21
|
-
|
|
10
|
+
import yaml
|
|
11
|
+
from dotenv import dotenv_values
|
|
22
12
|
from openai import OpenAI
|
|
23
13
|
from rich.console import Console
|
|
24
14
|
from rich.prompt import Prompt
|
|
@@ -26,6 +16,9 @@ from rich.status import Status
|
|
|
26
16
|
from servicefoundry import Build, DockerFileBuild, Job, LocalSource, Port, Service
|
|
27
17
|
from servicefoundry.cli.const import COMMAND_CLS
|
|
28
18
|
from servicefoundry.lib.auth.servicefoundry_session import ServiceFoundrySession
|
|
19
|
+
from servicefoundry.lib.clients.service_foundry_client import (
|
|
20
|
+
ServiceFoundryServiceClient,
|
|
21
|
+
)
|
|
29
22
|
|
|
30
23
|
from truefoundry.autodeploy.agents.developer import Developer
|
|
31
24
|
from truefoundry.autodeploy.agents.project_identifier import (
|
|
@@ -40,9 +33,13 @@ from truefoundry.autodeploy.constants import (
|
|
|
40
33
|
AUTODEPLOY_OPENAI_BASE_URL,
|
|
41
34
|
AUTODEPLOY_TFY_BASE_URL,
|
|
42
35
|
)
|
|
36
|
+
from truefoundry.autodeploy.exception import InvalidRequirementsException
|
|
43
37
|
from truefoundry.autodeploy.tools.ask import AskQuestion
|
|
44
38
|
from truefoundry.autodeploy.tools.commit import CommitConfirmation
|
|
45
39
|
from truefoundry.autodeploy.tools.docker_run import DockerRun, DockerRunLog
|
|
40
|
+
from truefoundry.autodeploy.utils.client import get_git_binary
|
|
41
|
+
|
|
42
|
+
git = get_git_binary()
|
|
46
43
|
|
|
47
44
|
|
|
48
45
|
def _get_openai_client() -> OpenAI:
|
|
@@ -62,11 +59,38 @@ def _get_openai_client() -> OpenAI:
|
|
|
62
59
|
resp = resp.json()
|
|
63
60
|
return OpenAI(api_key=resp["jwtToken"], base_url=resp["inferenceBaseURL"])
|
|
64
61
|
except requests.exceptions.HTTPError as http_error:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
if http_error.response.status_code in [401, 403]:
|
|
63
|
+
raise InvalidRequirementsException(
|
|
64
|
+
message='Unauthorized access to Truefoundry server. Please verify your credentials and ensure you have the necessary access rights.\nIf you wish to proceed without Truefoundry AI, you need to either have a truefoundry.yaml file in your project root or pass the path to a yaml file using the "--file file_name" option.'
|
|
65
|
+
) from http_error
|
|
66
|
+
|
|
67
|
+
raise http_error
|
|
68
|
+
|
|
68
69
|
except Exception as e:
|
|
69
|
-
raise
|
|
70
|
+
raise InvalidRequirementsException(message=str(e)) from e
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _get_service_port(name: str, workspace_fqn: str, port: int) -> Port:
|
|
74
|
+
client = ServiceFoundryServiceClient()
|
|
75
|
+
workspaces = client.get_workspace_by_fqn(workspace_fqn=workspace_fqn)
|
|
76
|
+
if len(workspaces) == 0:
|
|
77
|
+
raise click.UsageError("Invalid workspace")
|
|
78
|
+
workspace = workspaces[0]
|
|
79
|
+
cluster = client.get_cluster(cluster_id=workspace.clusterId)
|
|
80
|
+
|
|
81
|
+
generated_name = name + "-" + workspace.name
|
|
82
|
+
base_domain_urls = cluster["metadata"].get("baseDomainURLs")
|
|
83
|
+
if not base_domain_urls:
|
|
84
|
+
return Port(port=port, expose=False)
|
|
85
|
+
|
|
86
|
+
base_domain_url = base_domain_urls[0]
|
|
87
|
+
|
|
88
|
+
if "*" in base_domain_url:
|
|
89
|
+
return Port(
|
|
90
|
+
port=port, host=base_domain_url.replace("*", generated_name).strip("/")
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return Port(port=port, host=base_domain_url, path=f"/{generated_name}/")
|
|
70
94
|
|
|
71
95
|
|
|
72
96
|
def deploy_component(
|
|
@@ -79,8 +103,6 @@ def deploy_component(
|
|
|
79
103
|
command: Optional[str] = None,
|
|
80
104
|
port: Optional[int] = None,
|
|
81
105
|
):
|
|
82
|
-
logging.basicConfig(level=logging.INFO)
|
|
83
|
-
|
|
84
106
|
if not os.path.exists(os.path.join(project_root_path, dockerfile_path)):
|
|
85
107
|
raise FileNotFoundError("Dockerfile not found in the project.")
|
|
86
108
|
|
|
@@ -94,14 +116,20 @@ def deploy_component(
|
|
|
94
116
|
if component_type == ComponentType.SERVICE:
|
|
95
117
|
if port is None:
|
|
96
118
|
raise ValueError("Port is required for deploying service")
|
|
119
|
+
service_port = _get_service_port(
|
|
120
|
+
name=name, workspace_fqn=workspace_fqn, port=port
|
|
121
|
+
)
|
|
122
|
+
|
|
97
123
|
app = Service(
|
|
98
124
|
name=name,
|
|
99
125
|
image=image,
|
|
100
|
-
ports=[
|
|
126
|
+
ports=[service_port],
|
|
101
127
|
env=env,
|
|
102
128
|
)
|
|
103
129
|
else:
|
|
104
130
|
app = Job(name=name, image=image, env=env)
|
|
131
|
+
with open("truefoundry.yaml", "w") as application_spec:
|
|
132
|
+
yaml.dump(app.dict(), application_spec, indent=2)
|
|
105
133
|
app.deploy(workspace_fqn=workspace_fqn)
|
|
106
134
|
|
|
107
135
|
|
|
@@ -117,7 +145,7 @@ def _parse_env(project_root_path: str, env_path: str) -> Dict:
|
|
|
117
145
|
|
|
118
146
|
def _check_repo(project_root_path: str, console: Console):
|
|
119
147
|
try:
|
|
120
|
-
repo = Repo(project_root_path)
|
|
148
|
+
repo = git.Repo(path=project_root_path, search_parent_directories=True)
|
|
121
149
|
if repo.is_dirty():
|
|
122
150
|
console.print(
|
|
123
151
|
"[bold red]Error:[/] The repository has uncommitted changes. Please commit or stash them before proceeding."
|
|
@@ -142,14 +170,14 @@ def _check_repo(project_root_path: str, console: Console):
|
|
|
142
170
|
f"[bold magenta]TrueFoundry:[/] Continuing on [green]{current_active_branch!r}[/]"
|
|
143
171
|
)
|
|
144
172
|
|
|
145
|
-
except InvalidGitRepositoryError:
|
|
173
|
+
except git.exc.InvalidGitRepositoryError:
|
|
146
174
|
console.print(
|
|
147
175
|
"[red]Error:[/] This operation can only be performed inside a Git repository.\n"
|
|
148
176
|
"Execute 'git init' to create a new repository."
|
|
149
177
|
)
|
|
150
178
|
sys.exit(1)
|
|
151
179
|
|
|
152
|
-
except GitCommandError as gce:
|
|
180
|
+
except git.GitCommandError as gce:
|
|
153
181
|
console.print(
|
|
154
182
|
f"Command execution failed due to the following error:[red]{gce.stderr}[/]".replace(
|
|
155
183
|
"\n stderr:", ""
|
|
@@ -184,7 +212,7 @@ def _update_status(event, status: Status):
|
|
|
184
212
|
|
|
185
213
|
if isinstance(event, DockerRunLog):
|
|
186
214
|
status.update(
|
|
187
|
-
"[bold cyan]Running:[/] [bold magenta]TrueFoundry[/] is executing the Docker container. Press [yellow]control
|
|
215
|
+
"[bold cyan]Running:[/] [bold magenta]TrueFoundry[/] is executing the Docker container. Press [yellow]control + c[/] to stop waiting for additional logs..."
|
|
188
216
|
)
|
|
189
217
|
|
|
190
218
|
|
|
@@ -199,12 +227,10 @@ def _get_default_project_name(project_root_path: str):
|
|
|
199
227
|
def _get_docker(console: Console) -> docker.DockerClient:
|
|
200
228
|
try:
|
|
201
229
|
return docker.from_env()
|
|
202
|
-
except Exception:
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
)
|
|
207
|
-
sys.exit(1)
|
|
230
|
+
except Exception as e:
|
|
231
|
+
raise InvalidRequirementsException(
|
|
232
|
+
message="Could not connect to Docker, please check whether the Docker daemon is running."
|
|
233
|
+
) from e
|
|
208
234
|
|
|
209
235
|
|
|
210
236
|
def cli(project_root_path: str, deploy: bool, workspace_fqn: str = None):
|
|
@@ -239,21 +265,17 @@ def cli(project_root_path: str, deploy: bool, workspace_fqn: str = None):
|
|
|
239
265
|
"Service: An application that runs continuously. Example: web servers, workers polling a job queue, etc.": "SERVICE",
|
|
240
266
|
"Job: An application that runs once and then stops. Example: Training an ML model, running a script, etc.": "JOB",
|
|
241
267
|
}
|
|
242
|
-
component =
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"component",
|
|
246
|
-
message="TrueFoundry: Is your project a",
|
|
247
|
-
choices=choices.keys(),
|
|
248
|
-
)
|
|
249
|
-
]
|
|
250
|
-
)["component"]
|
|
268
|
+
component = questionary.select(
|
|
269
|
+
"TrueFoundry: Is your project a", choices=choices.keys()
|
|
270
|
+
).ask()
|
|
251
271
|
component_type = ComponentType[choices[component]]
|
|
252
272
|
while True:
|
|
253
273
|
name = Prompt.ask(
|
|
254
|
-
"[bold magenta]TrueFoundry:[/] Name of deployment"
|
|
274
|
+
"[bold magenta]TrueFoundry:[/] Name of deployment, or press [green]Enter[/] to select default. "
|
|
275
|
+
f"default: [green]{_get_default_project_name(project_root_path)}",
|
|
255
276
|
console=console,
|
|
256
277
|
default=_get_default_project_name(project_root_path),
|
|
278
|
+
show_default=False,
|
|
257
279
|
)
|
|
258
280
|
if not re.match(r"^[a-z][a-z0-9\-]{1,30}[a-z0-9]$", name):
|
|
259
281
|
console.print(
|
|
@@ -263,7 +285,7 @@ def cli(project_root_path: str, deploy: bool, workspace_fqn: str = None):
|
|
|
263
285
|
else:
|
|
264
286
|
break
|
|
265
287
|
command = Prompt.ask(
|
|
266
|
-
"[bold magenta]TrueFoundry:[/] Command to run the application",
|
|
288
|
+
"[bold magenta]TrueFoundry:[/] Command to run the application or press [green]Enter[/] to skip",
|
|
267
289
|
console=console,
|
|
268
290
|
show_default=False,
|
|
269
291
|
default=None,
|
|
@@ -20,3 +20,9 @@ ABOUT_AUTODEPLOY = """To deploy your project, we will generate the deployment co
|
|
|
20
20
|
We will analyze your codebase using our AI agent and make the required changes so that we can build and deploy the code.
|
|
21
21
|
We will confirm all the changes with you.
|
|
22
22
|
"""
|
|
23
|
+
# The maximum file size to read is set to 10KB.
|
|
24
|
+
# This limit is determined by the token limit of the LLM used, which is 128,000 tokens.
|
|
25
|
+
# Given that one token is approximately equivalent to 4 English characters,
|
|
26
|
+
# a 10KB file size limit (or ~10,000 characters | ~2500 tokens) ensures that the file content,
|
|
27
|
+
# along with any additional context and instructions for the LLM, fits within the model's token limit.
|
|
28
|
+
MAX_FILE_SIZE_READ = 10 * 1024
|
|
@@ -4,7 +4,6 @@ import os
|
|
|
4
4
|
import tempfile
|
|
5
5
|
from typing import Any, Generator, Optional
|
|
6
6
|
|
|
7
|
-
from git import Repo
|
|
8
7
|
from pydantic import Field
|
|
9
8
|
from rich.console import Console
|
|
10
9
|
from rich.padding import Padding
|
|
@@ -18,9 +17,12 @@ from truefoundry.autodeploy.tools.base import (
|
|
|
18
17
|
ResponseEvent,
|
|
19
18
|
Tool,
|
|
20
19
|
)
|
|
20
|
+
from truefoundry.autodeploy.utils.client import get_git_binary
|
|
21
21
|
from truefoundry.autodeploy.utils.diff import LLMDiff
|
|
22
22
|
from truefoundry.autodeploy.utils.pydantic_compat import model_dump
|
|
23
23
|
|
|
24
|
+
git = get_git_binary()
|
|
25
|
+
|
|
24
26
|
|
|
25
27
|
class CommitConfirmation(Event):
|
|
26
28
|
patch: str
|
|
@@ -109,7 +111,9 @@ The patch should have any changes that is not described in the commit message.
|
|
|
109
111
|
|
|
110
112
|
def __init__(self, project_root_path: str):
|
|
111
113
|
self.project_root_path = project_root_path
|
|
112
|
-
self.repo = Repo(
|
|
114
|
+
self.repo = git.Repo(
|
|
115
|
+
path=self.project_root_path, search_parent_directories=True
|
|
116
|
+
)
|
|
113
117
|
|
|
114
118
|
def run(
|
|
115
119
|
self,
|
|
@@ -20,14 +20,10 @@ from truefoundry.autodeploy.tools.base import (
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
class DockerRunLog(Event):
|
|
23
|
-
index: int
|
|
24
23
|
log: str
|
|
25
24
|
|
|
26
25
|
def render(self, console: Console):
|
|
27
|
-
# if self.index > 1:
|
|
28
|
-
# print("\r", end="")
|
|
29
26
|
console.print(Padding.indent(renderable=Text.from_ansi(self.log), level=2))
|
|
30
|
-
# console.print("Press control-c to stop waiting for more logs", end="")
|
|
31
27
|
|
|
32
28
|
|
|
33
29
|
class DockerRun(Tool):
|
|
@@ -128,13 +124,15 @@ This will not be passed if the container is still running.
|
|
|
128
124
|
exit_code = None
|
|
129
125
|
|
|
130
126
|
all_logs = []
|
|
131
|
-
logs = container.logs(stream=True)
|
|
132
127
|
|
|
133
128
|
try:
|
|
134
|
-
|
|
129
|
+
# This acts as a signal to update status.
|
|
130
|
+
yield DockerRunLog(log="")
|
|
131
|
+
logs = container.logs(stream=True)
|
|
132
|
+
for log in logs:
|
|
135
133
|
log = log.decode()
|
|
136
134
|
all_logs.append(log)
|
|
137
|
-
yield DockerRunLog(
|
|
135
|
+
yield DockerRunLog(log=log)
|
|
138
136
|
except KeyboardInterrupt:
|
|
139
137
|
pass
|
|
140
138
|
else:
|
|
@@ -5,6 +5,7 @@ from typing import Any, Generator, List, Optional
|
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
|
+
from truefoundry.autodeploy.constants import MAX_FILE_SIZE_READ
|
|
8
9
|
from truefoundry.autodeploy.tools.base import (
|
|
9
10
|
Event,
|
|
10
11
|
Message,
|
|
@@ -52,15 +53,22 @@ Avoid reading *.lock type files as they tend to be large
|
|
|
52
53
|
yield Message(
|
|
53
54
|
message=f"[bold cyan]Processing:[/] Reading file at [magenta]{request.path}[/] and extracting details..."
|
|
54
55
|
)
|
|
56
|
+
|
|
55
57
|
try:
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
file_path = os.path.join(self.project_root_path, request.path)
|
|
59
|
+
file_size = os.path.getsize(file_path)
|
|
60
|
+
|
|
61
|
+
if file_size > MAX_FILE_SIZE_READ:
|
|
62
|
+
return ReadFile.Response(error=f"File size exceeds {MAX_FILE_SIZE_READ} bytes limit")
|
|
63
|
+
|
|
64
|
+
with open(file_path, "r", encoding="utf8") as f:
|
|
61
65
|
response = ReadFile.Response(data=[])
|
|
62
66
|
for i, line in enumerate(f):
|
|
63
67
|
response.data.append(Line(line_number=i + 1, content=line))
|
|
64
68
|
return response
|
|
65
69
|
except FileNotFoundError as ex:
|
|
66
70
|
return ReadFile.Response(error=str(ex))
|
|
71
|
+
except UnicodeDecodeError as ex:
|
|
72
|
+
return ReadFile.Response(
|
|
73
|
+
error="This is a binary file, reading it is prohibited."
|
|
74
|
+
)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from truefoundry.autodeploy.exception import InvalidRequirementsException
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_git_binary():
|
|
5
|
+
try:
|
|
6
|
+
import git
|
|
7
|
+
|
|
8
|
+
return git
|
|
9
|
+
except Exception as ex:
|
|
10
|
+
raise InvalidRequirementsException(
|
|
11
|
+
message="We cannot find the 'git' command. We use Git to track changes made while automatically building your project. Please install Git to use this feature or manually create a 'truefoundry.yaml' file."
|
|
12
|
+
) from ex
|
truefoundry/deploy/cli/cli.py
CHANGED
|
@@ -13,10 +13,14 @@ from servicefoundry.cli.config import CliConfig
|
|
|
13
13
|
from servicefoundry.cli.const import GROUP_CLS
|
|
14
14
|
from servicefoundry.cli.util import setup_rich_click
|
|
15
15
|
from servicefoundry.lib.util import is_debug_env_set, is_experimental_env_set
|
|
16
|
+
from servicefoundry.logger import logger as servicefoundry_logger
|
|
16
17
|
from servicefoundry.version import __version__
|
|
17
18
|
|
|
18
19
|
from truefoundry.deploy.cli.deploy import deploy_v2_command
|
|
19
20
|
|
|
21
|
+
servicefoundry_logger.setLevel(level=logging.INFO)
|
|
22
|
+
|
|
23
|
+
|
|
20
24
|
click.rich_click.USE_RICH_MARKUP = True
|
|
21
25
|
|
|
22
26
|
|
truefoundry/deploy/cli/deploy.py
CHANGED
|
@@ -9,24 +9,20 @@ from click.exceptions import ClickException
|
|
|
9
9
|
from servicefoundry.cli.const import GROUP_CLS
|
|
10
10
|
from servicefoundry.lib.dao import application as application_lib
|
|
11
11
|
|
|
12
|
-
from truefoundry.autodeploy.
|
|
12
|
+
from truefoundry.autodeploy.cli import cli as autodeploy_cli
|
|
13
|
+
from truefoundry.autodeploy.exception import InvalidRequirementsException
|
|
13
14
|
|
|
14
|
-
GIT_BINARY = True
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for file in files:
|
|
27
|
-
if os.path.exists(file):
|
|
28
|
-
return file
|
|
29
|
-
return None
|
|
16
|
+
def _get_default_spec_file():
|
|
17
|
+
paths = [
|
|
18
|
+
"./truefoundry.yaml",
|
|
19
|
+
"./truefoundry.yml",
|
|
20
|
+
"./servicefoundry.yaml",
|
|
21
|
+
"./servicefoundry.yml",
|
|
22
|
+
]
|
|
23
|
+
for path in paths:
|
|
24
|
+
if os.path.exists(path):
|
|
25
|
+
return path
|
|
30
26
|
|
|
31
27
|
|
|
32
28
|
@click.group(
|
|
@@ -38,10 +34,10 @@ def _get_yaml_file():
|
|
|
38
34
|
@click.option(
|
|
39
35
|
"-f",
|
|
40
36
|
"--file",
|
|
41
|
-
type=click.
|
|
42
|
-
default=
|
|
37
|
+
type=click.Path(exists=True, dir_okay=False, resolve_path=True),
|
|
38
|
+
default=_get_default_spec_file(),
|
|
43
39
|
help="Path to truefoundry.yaml file",
|
|
44
|
-
show_default=
|
|
40
|
+
show_default=True,
|
|
45
41
|
)
|
|
46
42
|
@click.option(
|
|
47
43
|
"-w",
|
|
@@ -67,53 +63,45 @@ def deploy_v2_command(file: str, workspace_fqn: str, wait: bool):
|
|
|
67
63
|
except Exception as e:
|
|
68
64
|
raise ClickException(message=str(e)) from e
|
|
69
65
|
|
|
70
|
-
if file
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
file = _get_yaml_file()
|
|
76
|
-
|
|
77
|
-
if file is None:
|
|
78
|
-
click.echo(
|
|
79
|
-
click.style(
|
|
80
|
-
"We did not find any truefoundry.yaml or servicefoundry.yaml at the root path.",
|
|
81
|
-
fg="red",
|
|
82
|
-
),
|
|
83
|
-
color=True,
|
|
84
|
-
)
|
|
66
|
+
if file:
|
|
67
|
+
with open(file, "r") as f:
|
|
68
|
+
application_definition = yaml.safe_load(f)
|
|
85
69
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
70
|
+
application = Application.parse_obj(application_definition)
|
|
71
|
+
application.deploy(workspace_fqn=workspace_fqn, wait=wait)
|
|
72
|
+
sys.exit(0)
|
|
73
|
+
|
|
74
|
+
click.echo(
|
|
75
|
+
click.style(
|
|
76
|
+
"We did not find any truefoundry.yaml or servicefoundry.yaml at the root path.",
|
|
77
|
+
fg="red",
|
|
78
|
+
),
|
|
79
|
+
color=True,
|
|
80
|
+
)
|
|
95
81
|
|
|
82
|
+
if not sys.stdout.isatty():
|
|
96
83
|
click.echo(
|
|
97
84
|
click.style(
|
|
98
|
-
'
|
|
85
|
+
'Please create a truefoundry.yaml or pass the file name with "--file file_name"',
|
|
99
86
|
fg="yellow",
|
|
100
87
|
),
|
|
88
|
+
color=True,
|
|
101
89
|
)
|
|
90
|
+
sys.exit(1)
|
|
102
91
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
"We cannot find the 'git' command. We use Git to track changes made while automatically building your project. Please install Git to use this feature or manually create a 'truefoundry.yaml' file."
|
|
110
|
-
)
|
|
111
|
-
else:
|
|
112
|
-
with open(file, "r") as f:
|
|
113
|
-
application_definition = yaml.safe_load(f)
|
|
92
|
+
click.echo(
|
|
93
|
+
click.style(
|
|
94
|
+
'We will be using TrueFoundry AI to build your project.\nIf you wish to proceed without TrueFoundry AI,\nyou need to either have a truefoundry.yaml file in your project root or\npass the path to a yaml file using the "--file file_name" option.',
|
|
95
|
+
fg="yellow",
|
|
96
|
+
),
|
|
97
|
+
)
|
|
114
98
|
|
|
115
|
-
|
|
116
|
-
|
|
99
|
+
try:
|
|
100
|
+
autodeploy_cli(project_root_path=".", deploy=True, workspace_fqn=workspace_fqn)
|
|
101
|
+
except InvalidRequirementsException as e:
|
|
102
|
+
raise UsageError(message=e.message) from e
|
|
103
|
+
except Exception as e:
|
|
104
|
+
raise UsageError(message=str(e)) from e
|
|
117
105
|
|
|
118
106
|
|
|
119
107
|
@click.group(
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: truefoundry
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0rc10
|
|
4
4
|
Summary: Truefoundry CLI
|
|
5
5
|
Author: Abhishek Choudhary
|
|
6
6
|
Author-email: abhichoudhary06@gmail.com
|
|
7
|
-
Requires-Python: >=3.8
|
|
7
|
+
Requires-Python: >=3.8,<3.13
|
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
9
10
|
Classifier: Programming Language :: Python :: 3.9
|
|
10
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
11
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -14,14 +15,13 @@ Provides-Extra: ml
|
|
|
14
15
|
Requires-Dist: docker (>=7.0.0,<8.0.0)
|
|
15
16
|
Requires-Dist: gitignorefile (>=1.1.2,<2.0.0)
|
|
16
17
|
Requires-Dist: gitpython (>=3.1.43,<4.0.0)
|
|
17
|
-
Requires-Dist: inquirer (>=3.2.4,<4.0.0)
|
|
18
18
|
Requires-Dist: mlfoundry (==0.10.9) ; extra == "ml"
|
|
19
19
|
Requires-Dist: openai (>=1.16.2,<2.0.0)
|
|
20
20
|
Requires-Dist: pydantic (>=1.10.0,<3)
|
|
21
21
|
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
|
|
22
22
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
23
23
|
Requires-Dist: rich (>=13.7.1,<14.0.0)
|
|
24
|
-
Requires-Dist: servicefoundry (==0.10.
|
|
24
|
+
Requires-Dist: servicefoundry (==0.10.11)
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
27
27
|
# Truefoundry
|
|
@@ -5,32 +5,33 @@ truefoundry/autodeploy/agents/base.py,sha256=woCry229x7WX0IZmBopW_e_NB76aCLQRLXZ
|
|
|
5
5
|
truefoundry/autodeploy/agents/developer.py,sha256=u1BfjaMDX6Ad32vWYOEFZPWFK33ux0Ro8JztrRAFviY,4126
|
|
6
6
|
truefoundry/autodeploy/agents/project_identifier.py,sha256=wOFCUIbN-3mVQEToJ2svKm8XvxZ_IxIvUF2P3VqQu94,4438
|
|
7
7
|
truefoundry/autodeploy/agents/tester.py,sha256=Ci-382r3R8M1NCpbnmcBBHZa4UBCVjyrrt5bwufHDm4,2352
|
|
8
|
-
truefoundry/autodeploy/cli.py,sha256
|
|
9
|
-
truefoundry/autodeploy/constants.py,sha256=
|
|
10
|
-
truefoundry/autodeploy/exception.py,sha256=
|
|
8
|
+
truefoundry/autodeploy/cli.py,sha256=-wCCaokrSeXw8vKbYVVvnKoHMmtsHcXTaZJiKANtWXc,13648
|
|
9
|
+
truefoundry/autodeploy/constants.py,sha256=m3qQh2gsrqRLqiTbxmddS8CwWX9v7s7oEBHOEvHbFec,1553
|
|
10
|
+
truefoundry/autodeploy/exception.py,sha256=fa_ZyTDUKiMKG2Uayynk1yWcEMsuVluqk2GtV4tfTPU,158
|
|
11
11
|
truefoundry/autodeploy/logger.py,sha256=tkV2UKcOTFl5nz0cn4eRbzxF-2CZd8b7MK9vnhaflYw,325
|
|
12
12
|
truefoundry/autodeploy/tools/__init__.py,sha256=9zJiC1d4bv9EL-p5XTCa9fAQ6ZKV--AbgeLz9bBBkyQ,875
|
|
13
13
|
truefoundry/autodeploy/tools/ask.py,sha256=MxUFLP7rjpdJ85gCc3El0wUqTZDjpjAw7WOTdV4LLWE,856
|
|
14
14
|
truefoundry/autodeploy/tools/base.py,sha256=X7bBhJ2-mkc1_uo9dLtIoZOgKsvoCsmvCzdh_j0rdys,665
|
|
15
|
-
truefoundry/autodeploy/tools/commit.py,sha256=
|
|
15
|
+
truefoundry/autodeploy/tools/commit.py,sha256=ozQFzG3OL1SR9lBaiV70ECNXunqMERCpdVauzVMTTPs,5983
|
|
16
16
|
truefoundry/autodeploy/tools/docker_build.py,sha256=6LfWLJYh3Y3kCIVOC8lFcZjWHIk3iWEuw_qoAxx642k,3931
|
|
17
|
-
truefoundry/autodeploy/tools/docker_run.py,sha256=
|
|
17
|
+
truefoundry/autodeploy/tools/docker_run.py,sha256=6sAyguh_slSLBLIHV2e5QFpAs7XC-0UOjUU1BGqMxJU,4993
|
|
18
18
|
truefoundry/autodeploy/tools/file_type_counts.py,sha256=4p6IHp-j1vBzELpepFhNwfmB88cUUAFdVDQdzv4lGtM,2288
|
|
19
19
|
truefoundry/autodeploy/tools/list_files.py,sha256=9z_Nih_N8v7qe14znl7_-3MKZjw5RylVyy7L8qvU1es,2577
|
|
20
|
-
truefoundry/autodeploy/tools/read_file.py,sha256=
|
|
20
|
+
truefoundry/autodeploy/tools/read_file.py,sha256=LVvpFaFtSnBFVnH8TnmVJlylU46Wkc8wC5GotNirc0E,2155
|
|
21
21
|
truefoundry/autodeploy/tools/send_request.py,sha256=5q_fAo0tXRiHg9M3XpdwhCzUtDUWVh17239oU4LkZfI,1614
|
|
22
22
|
truefoundry/autodeploy/tools/write_file.py,sha256=EcYetnJ4X-NWsd_CdYUKfOnAdz2XXiRukTzJfb_GzFs,3130
|
|
23
|
+
truefoundry/autodeploy/utils/client.py,sha256=PvbSkfgAjAogGjisinqmh4mP4svowxAC0IwzEQz3Ai0,453
|
|
23
24
|
truefoundry/autodeploy/utils/diff.py,sha256=Ef8Y-VffDKel_-q-GxRam6gqiv8qTLMcqVg6iifXfcA,5358
|
|
24
25
|
truefoundry/autodeploy/utils/pydantic_compat.py,sha256=hEAUy5kLjhPdzw7yGZ2iXGMXbbMVXVlGzIofmyHafXQ,412
|
|
25
26
|
truefoundry/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
27
|
truefoundry/cli/__main__.py,sha256=Jap_IddZ9zNyMIyIkCw75xHQCN0WtV2dPZJ_pzdLsVc,916
|
|
27
28
|
truefoundry/deploy/__init__.py,sha256=wDQq3y-t9zOEOVA61t15fRpAVQSpBtiWTyW5hVn1iz4,43
|
|
28
29
|
truefoundry/deploy/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
-
truefoundry/deploy/cli/cli.py,sha256=
|
|
30
|
-
truefoundry/deploy/cli/deploy.py,sha256=
|
|
30
|
+
truefoundry/deploy/cli/cli.py,sha256=gaOareV2M6DhiTXHuyVJy5RrcvJTmGaCF5A1vrVeYeI,3113
|
|
31
|
+
truefoundry/deploy/cli/deploy.py,sha256=hOb0GY1tiPzKy5P85iYAML0WyGSmKBXJgwxD5k5VoME,5105
|
|
31
32
|
truefoundry/langchain/__init__.py,sha256=kQrM0qr2EoB-EFaPkVVVcmSBSJ8KsQzv0nx-LGzmCRo,53
|
|
32
33
|
truefoundry/ml/__init__.py,sha256=yFjvF-e1RW488vLHgn5M7TXoajqww6grkKHb3mhqDEw,179
|
|
33
|
-
truefoundry-0.2.
|
|
34
|
-
truefoundry-0.2.
|
|
35
|
-
truefoundry-0.2.
|
|
36
|
-
truefoundry-0.2.
|
|
34
|
+
truefoundry-0.2.0rc10.dist-info/METADATA,sha256=PrMY6TuPf6d26cIpsmQe1Im-_fOKzhw8k7iQ-hqniq8,1840
|
|
35
|
+
truefoundry-0.2.0rc10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
36
|
+
truefoundry-0.2.0rc10.dist-info/entry_points.txt,sha256=TXvUxQkI6zmqJuycPsyxEIMr3oqfDjgrWj0m_9X12x4,95
|
|
37
|
+
truefoundry-0.2.0rc10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|