arkitekt-next 0.8.60__py3-none-any.whl → 0.8.62__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 arkitekt-next might be problematic. Click here for more details.
- arkitekt_next/__blok__.py +3 -0
- arkitekt_next/__init__.py +5 -1
- arkitekt_next/base_models.py +2 -4
- arkitekt_next/bloks/arkitekt.py +15 -13
- arkitekt_next/bloks/base.py +6 -4
- arkitekt_next/bloks/gateway.py +10 -6
- arkitekt_next/bloks/kraph.py +4 -1
- arkitekt_next/bloks/local_sign.py +261 -0
- arkitekt_next/bloks/lok.py +5 -3
- arkitekt_next/bloks/ollama.py +1 -4
- arkitekt_next/bloks/orkestrator.py +4 -6
- arkitekt_next/bloks/self_signed.py +1 -8
- arkitekt_next/bloks/services/certer.py +2 -2
- arkitekt_next/cli/commands/gen/init.py +2 -2
- arkitekt_next/cli/commands/inspect/templates.py +0 -2
- arkitekt_next/cli/commands/kabinet/build.py +28 -9
- arkitekt_next/cli/commands/kabinet/init.py +1 -1
- arkitekt_next/cli/commands/kabinet/io.py +206 -0
- arkitekt_next/cli/commands/kabinet/main.py +27 -15
- arkitekt_next/cli/commands/kabinet/publish.py +2 -2
- arkitekt_next/cli/commands/kabinet/stage.py +1 -1
- arkitekt_next/cli/commands/kabinet/types.py +139 -0
- arkitekt_next/cli/commands/kabinet/utils.py +1 -1
- arkitekt_next/cli/commands/kabinet/validate.py +1 -1
- arkitekt_next/cli/commands/manifest/inspect.py +2 -7
- arkitekt_next/cli/commands/manifest/main.py +0 -2
- arkitekt_next/cli/io.py +0 -192
- arkitekt_next/cli/types.py +2 -147
- arkitekt_next/cli/ui.py +1 -1
- arkitekt_next/init_registry.py +2 -11
- arkitekt_next/qt/builders.py +2 -3
- arkitekt_next/service_registry.py +5 -87
- arkitekt_next/utils.py +3 -2
- {arkitekt_next-0.8.60.dist-info → arkitekt_next-0.8.62.dist-info}/METADATA +19 -9
- {arkitekt_next-0.8.60.dist-info → arkitekt_next-0.8.62.dist-info}/RECORD +38 -37
- arkitekt_next/cli/commands/kabinet/wizard.py +0 -329
- arkitekt_next/cli/commands/manifest/wizard.py +0 -94
- {arkitekt_next-0.8.60.dist-info → arkitekt_next-0.8.62.dist-info}/LICENSE +0 -0
- {arkitekt_next-0.8.60.dist-info → arkitekt_next-0.8.62.dist-info}/WHEEL +0 -0
- {arkitekt_next-0.8.60.dist-info → arkitekt_next-0.8.62.dist-info}/entry_points.txt +0 -0
|
@@ -5,9 +5,9 @@ import os
|
|
|
5
5
|
from rich.panel import Panel
|
|
6
6
|
import subprocess
|
|
7
7
|
import uuid
|
|
8
|
-
from
|
|
8
|
+
from .io import generate_build
|
|
9
9
|
from click import Context
|
|
10
|
-
from
|
|
10
|
+
from .types import Flavour, InspectionInput
|
|
11
11
|
import yaml
|
|
12
12
|
from typing import Dict, Optional
|
|
13
13
|
import json
|
|
@@ -93,24 +93,38 @@ def inspect_docker_container(build_id: str) -> InspectionInput:
|
|
|
93
93
|
raise InspectionError(f"An error occurred: {e.stdout + e.stderr}") from e
|
|
94
94
|
|
|
95
95
|
|
|
96
|
-
def inspect_templates(build_id: str, url:str) -> list[TemplateInput]:
|
|
96
|
+
def inspect_templates(build_id: str, url: str) -> list[TemplateInput]:
|
|
97
97
|
try:
|
|
98
98
|
# Run 'docker inspect' with the container ID or name
|
|
99
99
|
process = subprocess.Popen(
|
|
100
|
-
" ".join(
|
|
100
|
+
" ".join(
|
|
101
|
+
[
|
|
102
|
+
"docker",
|
|
103
|
+
"run",
|
|
104
|
+
"-it",
|
|
105
|
+
"--network",
|
|
106
|
+
"host",
|
|
107
|
+
build_id,
|
|
108
|
+
"arkitekt-next",
|
|
109
|
+
"inspect",
|
|
110
|
+
"templates",
|
|
111
|
+
"-mr",
|
|
112
|
+
"--url",
|
|
113
|
+
url,
|
|
114
|
+
]
|
|
115
|
+
),
|
|
101
116
|
shell=True,
|
|
102
117
|
stdout=subprocess.PIPE,
|
|
103
118
|
stderr=subprocess.PIPE,
|
|
104
119
|
)
|
|
105
120
|
|
|
106
|
-
|
|
107
121
|
lines = []
|
|
108
|
-
|
|
122
|
+
# Poll process for new output until finished
|
|
109
123
|
while True:
|
|
110
124
|
if process.poll() is not None:
|
|
111
125
|
break
|
|
112
126
|
nextline = process.stdout.readline()
|
|
113
|
-
|
|
127
|
+
|
|
114
128
|
lines.append(nextline.decode("utf-8"))
|
|
115
129
|
sys.stdout.buffer.write(nextline)
|
|
116
130
|
sys.stdout.flush()
|
|
@@ -267,7 +281,13 @@ def get_flavours(ctx: Context, select: Optional[str] = None) -> Dict[str, Flavou
|
|
|
267
281
|
default=DEFAULT_ARKITEKT_URL,
|
|
268
282
|
)
|
|
269
283
|
@click.pass_context
|
|
270
|
-
def build(
|
|
284
|
+
def build(
|
|
285
|
+
ctx: Context,
|
|
286
|
+
flavour: str,
|
|
287
|
+
no_inspect: bool,
|
|
288
|
+
tag: str = None,
|
|
289
|
+
url: str = DEFAULT_ARKITEKT_URL,
|
|
290
|
+
) -> None:
|
|
271
291
|
"""Builds the arkitekt_next app to docker"""
|
|
272
292
|
|
|
273
293
|
manifest = get_manifest(ctx)
|
|
@@ -298,7 +318,6 @@ def build(ctx: Context, flavour: str, no_inspect: bool, tag: str = None, url: st
|
|
|
298
318
|
if tag:
|
|
299
319
|
subprocess.run(["docker", "tag", build_tag, tag], check=True)
|
|
300
320
|
|
|
301
|
-
|
|
302
321
|
inspection = None
|
|
303
322
|
if not no_inspect:
|
|
304
323
|
inspection = inspect_build(build_tag, url)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from importlib.metadata import version
|
|
2
2
|
from arkitekt_next.cli.constants import compile_dockerfiles
|
|
3
|
-
from
|
|
3
|
+
from .types import Flavour
|
|
4
4
|
from arkitekt_next.cli.utils import build_relative_dir
|
|
5
5
|
import rich_click as click
|
|
6
6
|
from click import Context
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import uuid
|
|
3
|
+
from arkitekt_next.utils import create_arkitekt_next_folder
|
|
4
|
+
import os
|
|
5
|
+
from typing import Optional, List, Dict
|
|
6
|
+
from arkitekt_next.cli.types import (
|
|
7
|
+
Manifest,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from .types import (
|
|
11
|
+
Build,
|
|
12
|
+
BuildsConfigFile,
|
|
13
|
+
Flavour,
|
|
14
|
+
DeploymentsConfigFile,
|
|
15
|
+
)
|
|
16
|
+
from kabinet.api.schema import (
|
|
17
|
+
InspectionInput,
|
|
18
|
+
AppImageInput,
|
|
19
|
+
DockerImageInput,
|
|
20
|
+
ManifestInput,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
import yaml
|
|
24
|
+
import json
|
|
25
|
+
import rich_click as click
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_builds(selected_run: Optional[str] = None) -> Dict[str, Build]:
|
|
29
|
+
"""Will load the builds.yaml file and return a dictionary of builds
|
|
30
|
+
|
|
31
|
+
Will load the builds.yaml file and return a dictionary of builds
|
|
32
|
+
where the key is the build_id and the value is the build object.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
Dict[str, Build]
|
|
38
|
+
The loaded builds
|
|
39
|
+
"""
|
|
40
|
+
path = create_arkitekt_next_folder()
|
|
41
|
+
config_file = os.path.join(path, "builds.yaml")
|
|
42
|
+
|
|
43
|
+
builds = {}
|
|
44
|
+
|
|
45
|
+
if os.path.exists(config_file):
|
|
46
|
+
with open(config_file, "r") as file:
|
|
47
|
+
config = BuildsConfigFile(**yaml.safe_load(file))
|
|
48
|
+
|
|
49
|
+
# We will only return the builds from the selected run
|
|
50
|
+
selected_run = selected_run or config.latest_build_run
|
|
51
|
+
|
|
52
|
+
builds = {
|
|
53
|
+
build.build_id: build
|
|
54
|
+
for build in config.builds
|
|
55
|
+
if build.build_run == selected_run
|
|
56
|
+
}
|
|
57
|
+
return builds
|
|
58
|
+
else:
|
|
59
|
+
raise click.ClickException(
|
|
60
|
+
"Could not find any builds. Please run `arkitekt_next port build` first"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def manifest_to_input(manifest: Manifest) -> ManifestInput:
|
|
65
|
+
|
|
66
|
+
return ManifestInput(**manifest.model_dump(by_alias=True))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def generate_build(
|
|
70
|
+
build_run: str,
|
|
71
|
+
build_id: str,
|
|
72
|
+
flavour_name: str,
|
|
73
|
+
flavour: Flavour,
|
|
74
|
+
manifest: Manifest,
|
|
75
|
+
inspection: Optional[InspectionInput],
|
|
76
|
+
) -> Build:
|
|
77
|
+
"""Generates a build from a builder, build_id and manifest
|
|
78
|
+
|
|
79
|
+
Will generate a build from a builder, build_id and manifest,
|
|
80
|
+
and write it to the builds.yaml file in the arkitekt_next folder.
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
builder : str
|
|
86
|
+
The builder that was used to build the build
|
|
87
|
+
build_id : str
|
|
88
|
+
The build_id of the build
|
|
89
|
+
manifest : Manifest
|
|
90
|
+
The manifest of the build
|
|
91
|
+
|
|
92
|
+
Returns
|
|
93
|
+
-------
|
|
94
|
+
Build
|
|
95
|
+
The generated build
|
|
96
|
+
"""
|
|
97
|
+
path = create_arkitekt_next_folder()
|
|
98
|
+
|
|
99
|
+
config_file = os.path.join(path, "builds.yaml")
|
|
100
|
+
|
|
101
|
+
build = Build(
|
|
102
|
+
manifest=manifest_to_input(manifest),
|
|
103
|
+
flavour=flavour_name,
|
|
104
|
+
selectors=flavour.selectors,
|
|
105
|
+
build_id=build_id,
|
|
106
|
+
build_run=build_run,
|
|
107
|
+
description=flavour.description,
|
|
108
|
+
inspection=inspection,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
if os.path.exists(config_file):
|
|
112
|
+
with open(config_file, "r") as file:
|
|
113
|
+
config = BuildsConfigFile(**yaml.safe_load(file))
|
|
114
|
+
config.builds.append(build)
|
|
115
|
+
config.latest_build_run = build_run
|
|
116
|
+
else:
|
|
117
|
+
config = BuildsConfigFile(builds=[build], latest_build_run=build_run)
|
|
118
|
+
|
|
119
|
+
with open(config_file, "w") as file:
|
|
120
|
+
yaml.safe_dump(
|
|
121
|
+
json.loads(
|
|
122
|
+
config.json(exclude_none=True, exclude_unset=True, by_alias=True)
|
|
123
|
+
),
|
|
124
|
+
file,
|
|
125
|
+
sort_keys=True,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
return build
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def get_deployments() -> DeploymentsConfigFile:
|
|
132
|
+
"""Loads the deployments.yaml file and returns the deployments
|
|
133
|
+
|
|
134
|
+
Will load the deployments.yaml file and return the deployments
|
|
135
|
+
as a DeploymentsConfigFile object. If no deployments.yaml file
|
|
136
|
+
exists, it will return an empty DeploymentsConfigFile object.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
DeploymentsConfigFile
|
|
141
|
+
The deployments as a DeploymentsConfigFile object
|
|
142
|
+
"""
|
|
143
|
+
path = create_arkitekt_next_folder()
|
|
144
|
+
config_file = os.path.join(path, "deployments.yaml")
|
|
145
|
+
if os.path.exists(config_file):
|
|
146
|
+
with open(config_file, "r") as file:
|
|
147
|
+
return DeploymentsConfigFile(**yaml.safe_load(file))
|
|
148
|
+
else:
|
|
149
|
+
return DeploymentsConfigFile()
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def generate_deployment(
|
|
153
|
+
deployment_run: str,
|
|
154
|
+
build: Build,
|
|
155
|
+
image: str,
|
|
156
|
+
) -> AppImageInput:
|
|
157
|
+
"""Generates a deployment from a build and an image
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
|
|
162
|
+
build : Build
|
|
163
|
+
The build that should be deployed
|
|
164
|
+
image: str
|
|
165
|
+
The image that is the actuall deployment of the build
|
|
166
|
+
with_definitions: bool:
|
|
167
|
+
Should we generated and inspect definitions to bundle with
|
|
168
|
+
the deployment?
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
------
|
|
172
|
+
Deployment: The created deployment
|
|
173
|
+
|
|
174
|
+
"""
|
|
175
|
+
|
|
176
|
+
path = create_arkitekt_next_folder()
|
|
177
|
+
|
|
178
|
+
config_file = os.path.join(path, "deployments.yaml")
|
|
179
|
+
|
|
180
|
+
app_image = AppImageInput(
|
|
181
|
+
appImageId=uuid.uuid4().hex,
|
|
182
|
+
manifest=build.manifest,
|
|
183
|
+
flavourName=build.flavour,
|
|
184
|
+
selectors=build.selectors,
|
|
185
|
+
inspection=build.inspection,
|
|
186
|
+
image=DockerImageInput(imageString=image, buildAt=datetime.datetime.now()),
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
if os.path.exists(config_file):
|
|
190
|
+
with open(config_file, "r") as file:
|
|
191
|
+
config = DeploymentsConfigFile(**yaml.safe_load(file))
|
|
192
|
+
config.app_images.append(app_image)
|
|
193
|
+
config.latest_app_image = app_image.app_image_id
|
|
194
|
+
else:
|
|
195
|
+
config = DeploymentsConfigFile(
|
|
196
|
+
app_images=[app_image], latest_app_image=app_image.app_image_id
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
with open(config_file, "w") as file:
|
|
200
|
+
yaml.safe_dump(
|
|
201
|
+
json.loads(config.model_dump_json(exclude_none=True, by_alias=True)),
|
|
202
|
+
file,
|
|
203
|
+
sort_keys=True,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
return app_image
|
|
@@ -1,14 +1,34 @@
|
|
|
1
1
|
import rich_click as click
|
|
2
|
-
|
|
3
|
-
from .publish import publish
|
|
4
|
-
from .stage import stage
|
|
5
|
-
from .init import init
|
|
6
|
-
from .wizard import wizard
|
|
7
|
-
from .validate import validate
|
|
2
|
+
|
|
8
3
|
from click import Context
|
|
9
4
|
|
|
10
5
|
|
|
11
|
-
|
|
6
|
+
class LazyGroup(click.Group):
|
|
7
|
+
|
|
8
|
+
def list_commands(self, ctx):
|
|
9
|
+
return ["build", "init", "validate", "publish", "stage", "wizard"]
|
|
10
|
+
|
|
11
|
+
def get_command(self, ctx, cmd_name):
|
|
12
|
+
from .build import build
|
|
13
|
+
from .publish import publish
|
|
14
|
+
from .stage import stage
|
|
15
|
+
from .init import init
|
|
16
|
+
from .validate import validate
|
|
17
|
+
|
|
18
|
+
if cmd_name == "build":
|
|
19
|
+
return build
|
|
20
|
+
elif cmd_name == "init":
|
|
21
|
+
return init
|
|
22
|
+
elif cmd_name == "validate":
|
|
23
|
+
return validate
|
|
24
|
+
elif cmd_name == "publish":
|
|
25
|
+
return publish
|
|
26
|
+
elif cmd_name == "stage":
|
|
27
|
+
return stage
|
|
28
|
+
return None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@click.group(cls=LazyGroup)
|
|
12
32
|
@click.pass_context
|
|
13
33
|
def kabinet(ctx: Context) -> None:
|
|
14
34
|
"""Deploy the arkitekt_next app with Port
|
|
@@ -21,11 +41,3 @@ def kabinet(ctx: Context) -> None:
|
|
|
21
41
|
"""
|
|
22
42
|
|
|
23
43
|
pass
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
kabinet.add_command(build, "build")
|
|
27
|
-
kabinet.add_command(init, "init")
|
|
28
|
-
kabinet.add_command(validate, "validate")
|
|
29
|
-
kabinet.add_command(publish, "publish")
|
|
30
|
-
kabinet.add_command(stage, "stage")
|
|
31
|
-
kabinet.add_command(wizard, "wizard")
|
|
@@ -2,9 +2,9 @@ import rich_click as click
|
|
|
2
2
|
import subprocess
|
|
3
3
|
from .utils import search_username_in_docker_info
|
|
4
4
|
from arkitekt_next.cli.vars import get_console
|
|
5
|
-
from
|
|
5
|
+
from .types import Build
|
|
6
6
|
from rich.panel import Panel
|
|
7
|
-
from
|
|
7
|
+
from .io import get_builds, get_deployments, generate_deployment
|
|
8
8
|
from click import Context
|
|
9
9
|
import uuid
|
|
10
10
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
from pydantic import BaseModel, Field, field_validator
|
|
3
|
+
import datetime
|
|
4
|
+
from typing import List, Optional, Union, Literal, Dict
|
|
5
|
+
from enum import Enum
|
|
6
|
+
import semver
|
|
7
|
+
import uuid
|
|
8
|
+
from arkitekt_next.base_models import Requirement
|
|
9
|
+
from string import Formatter
|
|
10
|
+
import os
|
|
11
|
+
|
|
12
|
+
from kabinet.api.schema import (
|
|
13
|
+
AppImageInput,
|
|
14
|
+
InspectionInput,
|
|
15
|
+
SelectorInput,
|
|
16
|
+
ManifestInput,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
ALLOWED_BUILDER_KEYS = [
|
|
20
|
+
"tag",
|
|
21
|
+
"dockerfile",
|
|
22
|
+
"package_version",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SelectorType(str, Enum):
|
|
27
|
+
RAM = "ram"
|
|
28
|
+
CPU = "cpu"
|
|
29
|
+
GPU = "gpu"
|
|
30
|
+
LABEL = "label"
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Flavour(BaseModel):
|
|
34
|
+
selectors: List[SelectorInput]
|
|
35
|
+
description: str = Field(default="")
|
|
36
|
+
dockerfile: str = Field(default="Dockerfile")
|
|
37
|
+
build_command: List[str] = Field(
|
|
38
|
+
default_factory=lambda: [
|
|
39
|
+
"docker",
|
|
40
|
+
"build",
|
|
41
|
+
"-t",
|
|
42
|
+
"{tag}",
|
|
43
|
+
"-f",
|
|
44
|
+
"{dockerfile}",
|
|
45
|
+
".",
|
|
46
|
+
]
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
@field_validator("build_command", mode="before")
|
|
50
|
+
def check_valid_template_name(cls, value):
|
|
51
|
+
"""Checks that the build_command templates are valid"""
|
|
52
|
+
|
|
53
|
+
for v in value:
|
|
54
|
+
for literal_text, field_name, format_spec, conversion in Formatter().parse(
|
|
55
|
+
v
|
|
56
|
+
):
|
|
57
|
+
if field_name is not None:
|
|
58
|
+
assert (
|
|
59
|
+
field_name in ALLOWED_BUILDER_KEYS
|
|
60
|
+
), f"Invalid template key {field_name}. Allowed keys are {ALLOWED_BUILDER_KEYS}"
|
|
61
|
+
|
|
62
|
+
return value
|
|
63
|
+
|
|
64
|
+
def generate_build_command(self, tag: str, relative_dir: str):
|
|
65
|
+
"""Generates the build command for this flavour"""
|
|
66
|
+
|
|
67
|
+
dockerfile = os.path.join(relative_dir, self.dockerfile)
|
|
68
|
+
|
|
69
|
+
return [v.format(tag=tag, dockerfile=dockerfile) for v in self.build_command]
|
|
70
|
+
|
|
71
|
+
def check_relative_paths(self, flavour_folder: str):
|
|
72
|
+
"""Checks that the paths are relative to the flavour folder"""
|
|
73
|
+
|
|
74
|
+
dockerfile_path = os.path.join(flavour_folder, self.dockerfile)
|
|
75
|
+
|
|
76
|
+
if not os.path.exists(dockerfile_path):
|
|
77
|
+
raise Exception(
|
|
78
|
+
f"Could not find Dockerfile {self.dockerfile} in flavour {flavour_folder}"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class DeploymentsConfigFile(BaseModel):
|
|
83
|
+
"""The ConfigFile is a pydantic model that represents the deployments.yaml file
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
Parameters
|
|
87
|
+
----------
|
|
88
|
+
BaseModel : _type_
|
|
89
|
+
_description_
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
app_images: List[AppImageInput] = []
|
|
93
|
+
latest_app_image: Optional[str] = None
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Build(BaseModel):
|
|
97
|
+
build_run: str
|
|
98
|
+
build_id: str
|
|
99
|
+
inspection: Optional[InspectionInput] = None
|
|
100
|
+
description: str = Field(default="")
|
|
101
|
+
selectors: List[SelectorInput] = Field(default_factory=list)
|
|
102
|
+
flavour: str = Field(default="vanilla")
|
|
103
|
+
manifest: ManifestInput
|
|
104
|
+
build_at: datetime.datetime = Field(default_factory=datetime.datetime.now)
|
|
105
|
+
base_docker_command: List[str] = Field(
|
|
106
|
+
default_factory=lambda: ["docker", "run", "-it", "--net", "host"]
|
|
107
|
+
)
|
|
108
|
+
base_arkitekt_next_command: List[str] = Field(
|
|
109
|
+
default_factory=lambda: ["arkitekt-next", "run", "prod", "--headless"]
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def build_docker_command(self) -> List[str]:
|
|
113
|
+
"""Builds the docker command for this build"""
|
|
114
|
+
|
|
115
|
+
base_command = self.base_docker_command
|
|
116
|
+
|
|
117
|
+
for selector in self.selectors:
|
|
118
|
+
base_command = base_command + selector.build_docker_params()
|
|
119
|
+
|
|
120
|
+
base_command = base_command + [self.build_id]
|
|
121
|
+
|
|
122
|
+
return base_command
|
|
123
|
+
|
|
124
|
+
def build_arkitekt_next_command(self, fakts_next_url: str):
|
|
125
|
+
"""Builds the arkitekt_next command for this build"""
|
|
126
|
+
|
|
127
|
+
base_command = self.base_arkitekt_next_command
|
|
128
|
+
|
|
129
|
+
for selector in self.selectors:
|
|
130
|
+
base_command = base_command + selector.build_arkitekt_next_params()
|
|
131
|
+
|
|
132
|
+
base_command = base_command + ["--url", fakts_next_url]
|
|
133
|
+
|
|
134
|
+
return base_command
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class BuildsConfigFile(BaseModel):
|
|
138
|
+
builds: List[Build] = Field(default_factory=list)
|
|
139
|
+
latest_build_run: Optional[str] = None
|
|
@@ -17,20 +17,15 @@ def inspect(ctx) -> None:
|
|
|
17
17
|
"""
|
|
18
18
|
manifest = get_manifest(ctx)
|
|
19
19
|
|
|
20
|
-
table = Table.grid()
|
|
21
|
-
table.add_column()
|
|
20
|
+
table = Table.grid(padding=(0, 3))
|
|
22
21
|
table.add_column()
|
|
22
|
+
table.add_column(justify="right")
|
|
23
23
|
table.add_row("Identifier", manifest.identifier)
|
|
24
24
|
table.add_row("Version", manifest.version)
|
|
25
25
|
table.add_row("Author", manifest.author)
|
|
26
26
|
table.add_row("Logo", manifest.logo or "-")
|
|
27
27
|
table.add_row("Entrypoint", manifest.entrypoint)
|
|
28
28
|
table.add_row("Scopes", ", ".join(manifest.scopes) if manifest.scopes else "-")
|
|
29
|
-
table.add_row(
|
|
30
|
-
"Requirements",
|
|
31
|
-
", ".join(manifest.requirements) if manifest.requirements else "-",
|
|
32
|
-
)
|
|
33
|
-
table.add_row("Created at", str(manifest.created_at.strftime("%Y/%m/%d %H:%M")))
|
|
34
29
|
|
|
35
30
|
panel = Panel(
|
|
36
31
|
Group("[bold green]Manifest[/]", table),
|
|
@@ -2,7 +2,6 @@ import rich_click as click
|
|
|
2
2
|
from .inspect import inspect
|
|
3
3
|
from .scopes import scopes_group
|
|
4
4
|
from .version import version
|
|
5
|
-
from .wizard import wizard
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
@click.group()
|
|
@@ -22,4 +21,3 @@ def manifest(ctx) -> None:
|
|
|
22
21
|
manifest.add_command(inspect, "inspect")
|
|
23
22
|
manifest.add_command(scopes_group, "scopes")
|
|
24
23
|
manifest.add_command(version, "version")
|
|
25
|
-
manifest.add_command(wizard, "wizard")
|