Adds one-click remote dev on Kapsule with Claude Code, persistent
storage, and autoscale-to-zero. GP1-L (16 vCPU, 64GB) dev pool,
50Gi PVC for home directory, devcontainer image on SCW registry.
- .devcontainer/ (Dockerfile, devcontainer.json, pod-template, init-home)
- Terraform gpu-dev pool (GP1-L, 0→1 autoscaling)
- CI job to build devcontainer image (Kaniko → SCW registry)
- scripts/devpod-setup.sh for one-time provider config
- "Open in DevPod" link: https://devpod.sh/open#ssh://git@100.90.76.85:2222/root/foxhunt.git
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The replace_all for --insecure-registry left blank lines in the YAML
multi-line scalars, splitting each kaniko command in two. GitLab only
executed the first half (--context + --dockerfile), missing --destination.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Builds .devcontainer/Dockerfile with Kaniko, pushes to internal
GitLab registry. Triggers on .devcontainer/ changes or manual run.
Authenticates to both internal registry and Scaleway CR (for base image pull).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update COPY paths in all 3 Dockerfiles for crates/bin/services/testing layout
- Migrate service image builds from internal GitLab registry to SCW CR
- Update Kaniko auth to use SCW credentials (nologin + SCW_SECRET_KEY)
- Remove --insecure-registry flags (SCW CR is HTTPS)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redis image WORKDIR is /data and entrypoint runs chown recursively.
PVC mounted at /data/training was read-only, causing chown to fail
with exit code 1, crashing the Redis sidecar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
K8s executor doesn't wait for service containers to be healthy.
Use bash built-in /dev/tcp for readiness check (no netcat needed).
Remove --skip for redis_integration_test since sidecar provides Redis.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redis sidecar doesn't work under nvidia RuntimeClass. Skip these tests
in CI — they pass locally with Redis running. TODO: fix sidecar or
connect tests to cluster Redis service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redis sidecar runs as additional container in the build pod.
Kubernetes executor shares network namespace, so tests can
reach Redis at localhost:6379.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Mount training-data-pvc at /data/training in build pods via runner config
- Update real_data_loader to search per-symbol subdirectories (Databento layout)
- Support .dbn.zst (zstd-compressed) files alongside raw .dbn
- Add FOXHUNT_DATA_DIR env var override for CI PVC path
- Extract decode_ohlcv_bars helper (generic over reader type)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CI builder image prepends /usr/local/cuda/lib64/stubs to
LD_LIBRARY_PATH (for GPU-less compilation). On H100 with nvidia
RuntimeClass, the stub libcuda.so shadows the real driver library,
causing CUDA_ERROR_STUB_LIBRARY at test runtime. Strip stubs dir
before running tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two api_gateway JWT tests both call set_var/remove_var("JWT_SECRET") and
race under parallel execution. Setting JWT_SECRET globally prevents the
race: tests read the stable value, cleanup restores it (not removes it).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- poll_timeout 180s→600s: H100 provisioning takes ~3-5min from scale-to-zero
- build-ci-builder: only auto-run on push with Dockerfile changes (API
pipelines evaluate changes=true, causing unnecessary kaniko builds)
- check: add needs:[] to decouple from prepare stage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
bindgen_cuda calls nvidia-smi to detect compute capability, which fails
without GPU device access. Setting CUDA_COMPUTE_CAP=90 bypasses this for
compilation. Pod spec GPU request ensures NVIDIA device plugin injects
/dev/nvidia* for test-time CUDA execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove orphaned `ci` pool (GP1-XS, 4 vCPU wasted — nothing scheduled to it).
Remove `ci-build` pool (GP1-M) — builds now run on gpu-training (H100-1-80G:
24 vCPU, 240GB, real CUDA). This eliminates the need for CUDA stubs,
separate test-gpu jobs, and ml crate exclusions.
Pool layout after:
always-on DEV1-M (core services, always on)
gitlab GP1-XS (GitLab CE + runner manager, always on)
gpu-training H100-1-80G (CI builds + ML training, scale-to-zero)
gpu-inference L4-1-24G (trading inference, scale-to-zero)
Build pod limits bumped to 16 vCPU / 64GB (from 6/12GB) to use H100 capacity.
Runner now has `gpu` tag — all tests including ml crate run in single job.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GP1-XL (48 vCPU) exceeds account quota. GP1-M (16 vCPU, 64GB) fits
within current limits while providing sufficient build resources.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
52 ml tests require real CUDA (DQN, TFT, ensemble, flash_attention,
QAT, trainers). Exclude ml from workspace tests on CPU CI nodes.
Add test-gpu job (manual) for running ml tests on GPU hardware.
Also upgraded ci-build pool from GP1-XS to GP1-S (8 vCPUs, 32GB).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The backtesting crate links libcuda.so.1 at runtime (via candle CUDA).
GPU-less CI nodes need the stub library so binaries can load, but
model_loader tests that actually use CUDA must be skipped. These will
run on gpu-training nodes separately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The backtesting crate dynamically links to libcuda.so.1 via candle.
NVIDIA CUDA dev images include stubs at /usr/local/cuda/lib64/stubs/
but only as libcuda.so (not .so.1). Create the symlink both in the
Dockerfile (for future builds) and inline in the test script (for
the current image).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deploy now runs kubectl apply on manifests first (picking up
config changes), then updates images to the commit SHA.
Adds GitLab environment tracking for production.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fixed 48 lines where unquoted colons caused YAML parser to interpret
script commands as key-value maps instead of literal strings
- All echo commands containing ':' characters now fully quoted
- Affects: build:docker, test:*, deploy:* jobs
- Root cause: GitLab CI/CD YAML parser requires quotes around any script
command containing colons to prevent mapping interpretation
Fixes: 'script config should be a string or a nested array of strings
up to 10 levels deep' error in all test and deploy jobs
GitLab CI/CD parser doesn't support inline comments within script arrays.
Removed all inline '# Test N:' comments from:
- test:glibc-validation
- test:cuda-validation
- test:entrypoint-validation
Comments are now embedded in echo statements for visibility.
Remove escaped backslashes from grep regex pattern that were causing
GitLab CI/CD parser to fail with 'script config should be a string'
error.
Changed: libstdc\+\+ → libstdc (still matches libstdc++.so.6)
- Wrapped echo commands with colons in single quotes (lines 84-86)
- YAML was interpreting 'echo " Commit: $VAR"' as nested key-value pairs
- Single quotes force YAML to treat these as literal strings
- Fixes error: 'before_script config should be a string or nested array'
Issue: Colons followed by spaces in double-quoted strings cause YAML
parser to create nested dictionaries instead of flat string arrays
Root cause: Lines 84-86 contained unquoted colons that violated GitLab's
requirement that before_script must be 'a string or array of strings
up to 10 levels deep'
Validation: YAML syntax validated with PyYAML
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>