Skip to content

Commit 682dd1c

Browse files
authored
Merge pull request #698 from code0-tech/694-setup-builds-for-velorum
Setup builds for velorum
2 parents 7954e88 + 7e40f8a commit 682dd1c

12 files changed

Lines changed: 164 additions & 0 deletions

File tree

.gitlab/ci/container-boot.gitlab-ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,38 @@ container:boot:sculptor:
158158
- docker ps --all
159159
- docker compose logs sculptor -f &
160160
- docker compose run curl-sculptor
161+
162+
container:boot:velorum:
163+
extends:
164+
- .container:boot
165+
needs:
166+
- generate-environment
167+
- manifest:velorum
168+
script:
169+
- bundle install
170+
- docker compose up velorum -d
171+
- docker compose logs velorum -f &
172+
- support/grpc_check_health --host docker:50052 --service liveness --retries 20
173+
- support/grpc_check_health --host docker:50052 --service readiness --retries 20
174+
175+
container:boot:velorum:offline:
176+
extends:
177+
- .container:boot
178+
needs:
179+
- generate-environment
180+
- manifest:velorum
181+
script:
182+
- docker compose up velorum-offline -d
183+
- docker compose logs velorum-offline -f &
184+
- |
185+
for i in $(seq 1 30); do
186+
STATUS=$(docker inspect --format='{{.State.Health.Status}}' $(docker compose ps -q velorum-offline) 2>/dev/null || echo "starting")
187+
echo "Attempt $i/30: $STATUS"
188+
if [ "$STATUS" = "healthy" ]; then
189+
echo "Velorum booted successfully without network access"
190+
exit 0
191+
fi
192+
sleep 1
193+
done
194+
echo "Timed out waiting for healthy status"
195+
exit 1

.gitlab/ci/container-build.gitlab-ci.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,18 @@ manifest:sculptor:
326326
PLATFORM:
327327
- amd64
328328
- arm64
329+
330+
container:velorum:
331+
extends:
332+
- .single-image-build-base
333+
needs:
334+
- generate-environment
335+
variables:
336+
NEED_PROJECT_DOWNLOAD: 'true'
337+
338+
manifest:velorum:
339+
extends:
340+
- .manifest-create-base
341+
needs:
342+
- generate-environment
343+
- container:velorum

container/config-generator/generate.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ def env?(key)
8383
def env_set?(key)
8484
@env.fetch(key, nil) != nil
8585
end
86+
87+
def find_envs(pattern, group: false)
88+
if group
89+
@env.each_with_object({}) do |(key, value), groups|
90+
match = key.match(pattern)
91+
next unless match
92+
93+
group_key = match[1]
94+
suffix = key.sub(/.*#{Regexp.escape(group_key)}_?/, '')
95+
(groups[group_key] ||= {})[suffix] = value
96+
end
97+
else
98+
@env.select { |key, _| key =~ pattern }
99+
end
100+
end
86101
end
87102

88103
# Run the generator

container/config-generator/templates/sagittarius.sagittarius.yml.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ rails:
66
db:
77
host: <%= env('POSTGRES_HOST') %>
88
port: <%= env('POSTGRES_PORT') %>
9+
velorum:
10+
enabled: <%= env_set?('VELORUM_ENABLED') ? env('VELORUM_ENABLED') : env('COMPOSE_PROFILES').include?('ide_velorum') %>
11+
host: <%= env('VELORUM_HOST') %>:<%= env('VELORUM_PORT') %>
12+
jwt_secret: <%= env('VELORUM_JWT_SECRET') %>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[
2+
<% find_envs(/VELORUM_MODEL_(\S+?)_.+/, group: true).each_with_index do |(_, envs), i| %>
3+
<%= ',' if i > 0 %>
4+
{
5+
"identifier": "<%= envs.fetch('IDENTIFIER', '') %>",
6+
"name": "<%= envs.fetch('NAME', '') %>",
7+
"capabilities": [
8+
<%= envs.fetch('CAPABILITIES', '').split(',').map { |c| "\"#{c}\"" }.join(',') %>
9+
],
10+
"provider": "<%= envs.fetch('PROVIDER', '') %>",
11+
"api": "<%= envs.fetch('API', '') %>",
12+
"auth": "<%= envs.fetch('AUTH', '') %>",
13+
"token_cost": <%= envs.fetch('TOKEN_COST', '').to_f %>
14+
}
15+
<% end %>
16+
]

container/velorum/Dockerfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
ARG PYTHON_VERSION=3.12
2+
ARG UV_VERSION=0.11.16
3+
4+
FROM ghcr.io/astral-sh/uv:${UV_VERSION} AS uv
5+
FROM python:${PYTHON_VERSION}-slim
6+
7+
COPY --from=uv /uv /uvx /usr/local/bin/
8+
9+
WORKDIR /velorum
10+
11+
COPY projects/velorum/pyproject.toml projects/velorum/uv.lock ./
12+
RUN uv sync --frozen
13+
COPY projects/velorum/src/model.py ./src/model.py
14+
RUN uv run python -c "from src.model import load_vector_model; load_vector_model()"
15+
16+
COPY projects/velorum/cli ./cli
17+
COPY projects/velorum/src ./src
18+
COPY projects/velorum/main.py ./main.py
19+
20+
ENV HF_HUB_OFFLINE=1
21+
ENV PYTHONUNBUFFERED=1
22+
23+
HEALTHCHECK --interval=5s --timeout=3s --retries=3 \
24+
CMD uv run python -c "import grpc; from grpc_health.v1 import health_pb2, health_pb2_grpc; ch = grpc.insecure_channel('localhost:50051'); stub = health_pb2_grpc.HealthStub(ch); stub.Check(health_pb2.HealthCheckRequest(service='liveness'))" || exit 1
25+
26+
EXPOSE 50051
27+
CMD ["uv", "run", "main.py"]

docker-compose/.env

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,28 @@ DRACO_REST_AQUILA_TOKEN=draco-rest
2121
DRACO_CRON_AQUILA_TOKEN=draco-cron
2222

2323
# Active services
24+
# Available services: ide, runtime, ide_velorum (AI orchestrator)
2425
COMPOSE_PROFILES=ide,runtime
2526

2627
# Image config
2728
IMAGE_REGISTRY=registry.gitlab.com/code0-tech/packages
2829
IMAGE_TAG=
2930
IMAGE_EDITION= # ce or ee
3031

32+
# Velorum config
33+
# VELORUM_ENABLED=false (override, default checks if COMPOSE_PROFILES contains ide_velorum)
34+
VELORUM_HOST=velorum
35+
VELORUM_PORT=50051
36+
VELORUM_JWT_SECRET=088cfc7a7fc2b07696d8ee5e1ea9d642 # change to a random value
37+
38+
# example, GPT5 in the variable name can be changed to other values. This set of variables can be repeated multiple times
39+
# VELORUM_MODEL_GPT5_IDENTIFIER=gpt-5
40+
# VELORUM_MODEL_GPT5_NAME=GPT 5
41+
# VELORUM_MODEL_GPT5_CAPABILITIES=explain,generate
42+
# VELORUM_MODEL_GPT5_API= # if using a non-default base-url
43+
# VELORUM_MODEL_GPT5_AUTH= # authentication token
44+
# VELORUM_MODEL_GPT5_TOKEN_COST=1
45+
3146
# Internal config options
3247
SAGITTARIUS_RAILS_HOST=sagittarius-rails-web
3348
SAGITTARIUS_RAILS_PORT=3000

docker-compose/docker-compose.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,24 @@ services:
110110
profiles:
111111
- ide
112112

113+
velorum:
114+
image: ${IMAGE_REGISTRY}/velorum:${IMAGE_TAG}
115+
depends_on:
116+
config-generator:
117+
condition: service_completed_successfully
118+
restart: unless-stopped
119+
environment:
120+
SECURITY_TOKEN: $VELORUM_JWT_SECRET
121+
volumes:
122+
- generated-configs:/tmp/generated-configs:ro
123+
entrypoint: |
124+
sh -c "
125+
cp /tmp/generated-configs/velorum.models.configuration.json models.configuration.json
126+
exec uv run main.py
127+
"
128+
profiles:
129+
- ide_velorum
130+
113131
nginx:
114132
image: nginx:1.31.0-alpine-slim
115133
depends_on:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

support/docker-compose.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,5 +147,20 @@ services:
147147
- --retry-connrefused
148148
- http://sculptor:3000/
149149

150+
velorum:
151+
image: ghcr.io/code0-tech/reticulum/ci-builds/velorum:${RETICULUM_CONTAINER_VERSION}
152+
networks:
153+
- boot
154+
volumes:
155+
- ./config/velorum.models.configuration.json:/velorum/models.configuration.json
156+
ports:
157+
- "50052:50051"
158+
159+
velorum-offline:
160+
image: ghcr.io/code0-tech/reticulum/ci-builds/velorum:${RETICULUM_CONTAINER_VERSION}
161+
network_mode: "none"
162+
volumes:
163+
- ./config/velorum.models.configuration.json:/velorum/models.configuration.json
164+
150165
networks:
151166
boot:

0 commit comments

Comments
 (0)