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

6.0 KiB

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):

- 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):

- 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

# 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