Files
foxhunt/docs/plans/2026-03-07-gitlab-releases-design.md
jgrusewski 7a9683d5fb feat(infra): GitLab releases with CalVer auto-versioning
Replace MinIO binary distribution with GitLab Generic Package Registry.
Every code push to main auto-creates a CalVer tag (vYYYY.MM.N),
compiles, uploads binaries to GitLab packages, creates a Release
with auto-generated notes, and deploys via deployment patching.

- New CI templates: create-tag, upload-release
- Modified: compile-services/training upload to GitLab packages
- Modified: deploy-services patches FOXHUNT_RELEASE on deployments
- All 7 service initContainers fetch from GitLab (curl, deploy token)
- Training job-template binary fetch from GitLab (data stays MinIO)
- MinIO retains: sccache, training data, model checkpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 20:38:41 +01:00

183 lines
6.0 KiB
Markdown

# GitLab Releases with CalVer Auto-Versioning
**Date**: 2026-03-07
**Status**: Approved
## Summary
Replace MinIO binary distribution with GitLab Generic Package Registry + Releases.
Every push to `main` that touches code auto-creates a CalVer tag, compiles, uploads
binaries as GitLab generic packages, creates a GitLab Release, and deploys.
MinIO retains sccache, training data, and model checkpoints (not release artifacts).
## Versioning
**Scheme**: CalVer `vYYYY.MM.N` where N auto-increments per month.
Examples: `v2026.03.1`, `v2026.03.2`, `v2026.04.1`
**Increment logic**: Query GitLab tags API for latest `vYYYY.MM.*`, parse N, increment.
If no tag exists for current month, start at 1.
**Cargo.toml**: Workspace `version` stays at `1.0.0` (Cargo version != release version).
Runtime version comes from `FOXHUNT_BUILD_VERSION` env var baked at compile time
via `option_env!()` in `common/src/build_info.rs` (existing design from 2026-03-04).
## Branching Model
Trunk-based. No develop/release branches.
```
feature/* --merge--> main --auto--> tag vYYYY.MM.N -> compile -> release -> deploy
```
## Pipeline Changes (ci-pipeline-template.yaml)
### Current DAG
```
detect-changes -> [compile-services | compile-training | build-web-dashboard] -> deploy-services
```
### New DAG
```
detect-changes -> create-tag (if code changed)
|
+---------+---------+
| |
compile-services compile-training
| |
+---------+---------+
|
upload-release -> deploy-services
```
Non-code changes (docker images, dashboard) remain unchanged and don't create tags.
### New template: create-tag
- Runs on `platform` node (lightweight)
- Uses GitLab API via deploy token with `api` scope
- Computes version: `YYYY.MM` from date, queries `GET /api/v4/projects/:id/repository/tags?search=vYYYY.MM`
- Increments N, creates tag via `POST /api/v4/projects/:id/repository/tags`
- Outputs the tag name for downstream steps
### Modified: compile-services / compile-training
- `FOXHUNT_BUILD_VERSION` = tag from create-tag step (was `YYYY.MM.argo`)
- Upload destination changes from MinIO to GitLab Generic Package Registry:
```
PUT /api/v4/projects/:id/packages/generic/foxhunt-services/<tag>/<binary-name>
PUT /api/v4/projects/:id/packages/generic/foxhunt-training/<tag>/<binary-name>
```
- Removes rclone + MinIO credentials for binary upload
- Adds `GITLAB_API_TOKEN` from secret
### New template: upload-release
- Creates GitLab Release via `POST /api/v4/projects/:id/releases`
- Attaches package links as release assets
- Auto-generates release notes from commits since last tag:
`GET /api/v4/projects/:id/repository/changelog?version=<tag>`
- Runs after both compile steps complete
### Modified: deploy-services
- Sets `FOXHUNT_RELEASE` annotation on deployments to trigger rollout
- initContainers now know which version to fetch
## Service Deployment Changes (infra/k8s/services/*.yaml)
### initContainer: fetch-binary
Before (MinIO):
```yaml
- name: fetch-binary
args:
- |
rclone copyto ":s3:foxhunt-binaries/services/trading-service" "/binaries/trading-service" \
--s3-provider=Minio --s3-endpoint=http://minio.foxhunt.svc.cluster.local:9000 ...
env:
- name: MINIO_ACCESS_KEY ...
- name: MINIO_SECRET_KEY ...
```
After (GitLab Generic Packages):
```yaml
- name: fetch-binary
args:
- |
set -e
curl -fSL -o /binaries/trading-service \
--header "DEPLOY-TOKEN: ${GITLAB_DEPLOY_TOKEN}" \
"${GITLAB_API}/projects/1/packages/generic/foxhunt-services/${FOXHUNT_RELEASE}/trading-service"
chmod +x /binaries/trading-service
env:
- name: GITLAB_DEPLOY_TOKEN
valueFrom:
secretKeyRef:
name: gitlab-deploy-token
key: token
- name: GITLAB_API
value: "http://gitlab-webservice-default.foxhunt.svc.cluster.local:8181/api/v4"
- name: FOXHUNT_RELEASE
value: "v2026.03.1" # Updated by deploy-services step
```
### Training job-template.yaml
Same pattern: replace rclone/MinIO with curl/GitLab for binary fetch.
Training data sync stays on MinIO (not a release artifact).
## Secrets
### New
- `gitlab-deploy-token`: GitLab deploy token with `read_package_registry` scope (for service pods)
- `gitlab-api-token`: GitLab PAT or deploy token with `api` scope (for CI tag/release creation)
### Removed from binary path
- `minio-credentials` no longer needed in service deployments or compile upload steps
- MinIO credentials remain for: sccache, training data sync, model checkpoints
## Rollback
```bash
# Roll back to previous release
kubectl -n foxhunt set env deployment/trading-service FOXHUNT_RELEASE=v2026.03.1
kubectl -n foxhunt rollout restart deployment/trading-service
```
All previous binaries remain available in GitLab's package registry indefinitely.
## What stays on MinIO
| Bucket | Purpose | Change |
|--------|---------|--------|
| foxhunt-sccache | Rust build cache | No change |
| foxhunt-training-data | DBN market data | No change |
| foxhunt-training-results | Training outputs | No change |
| foxhunt-models | Model checkpoints | No change |
| foxhunt-binaries | **Service/training binaries** | **Decommission after migration** |
## Migration
1. Deploy new CI pipeline with dual-write (MinIO + GitLab) for one release
2. Switch service initContainers to GitLab fetch
3. Verify all services boot correctly
4. Remove MinIO binary upload from CI
5. Delete `foxhunt-binaries` bucket contents (keep bucket for sccache)
## Files Changed
### New files
- `crates/common/src/build_info.rs` — version function (from 2026-03-04 design)
### Modified files
- `infra/k8s/argo/ci-pipeline-template.yaml` — new create-tag + upload-release templates, modified compile steps
- `infra/k8s/services/*.yaml` (8 files) — initContainer fetch from GitLab
- `infra/k8s/training/job-template.yaml` — binary fetch from GitLab
- `infra/k8s/secrets/` — new gitlab-deploy-token, gitlab-api-token
- `crates/common/src/lib.rs` — re-export build_info