feat: Unraid deploy, dealer-flow heatmap, confluence zones, 13F capture
Ship Node production images, Unraid compose, and Gitea CI/CD (test then push registry images; cron script if no runner). Rebuild dealer flow as a heatmap-first map with integrity gates and chart helpers. Add confluence zone rules, session clock, capture evidence, and tighter 13F/queue/options paths, plus the matching UI and tests.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# Copy to the compose working directory as `.env`.
|
||||
# Generate secrets: openssl rand -hex 32
|
||||
|
||||
# Required
|
||||
IFLOW_SESSION_SECRET=
|
||||
# 64 hex chars. Required if you copy an existing DB that has encrypted X/FRED keys.
|
||||
# If you never set this locally, leave blank only for a fresh Unraid DB.
|
||||
IFLOW_CRYPTO_KEY=
|
||||
|
||||
# SQLite + harvest files. Use a cache (or single-disk) path, not /mnt/user.
|
||||
IFLOW_DATA_DIR=/mnt/cache/appdata/investor-flow/data
|
||||
|
||||
# Host ports
|
||||
IFLOW_WEB_PORT=3000
|
||||
IFLOW_BACKEND_PORT=3001
|
||||
|
||||
# Images: local tags when building on Unraid; Gitea registry after CD is live.
|
||||
IFLOW_IMAGE_BACKEND=investor-flow-backend:local
|
||||
IFLOW_IMAGE_FRONTEND=investor-flow-frontend:local
|
||||
# After the Gitea runner + CD workflow exist:
|
||||
# IFLOW_IMAGE_BACKEND=unraid.local:3003/transnet/investor-flow-backend:latest
|
||||
# IFLOW_IMAGE_FRONTEND=unraid.local:3003/transnet/investor-flow-frontend:latest
|
||||
IFLOW_TAG=latest
|
||||
|
||||
# SEC / Yahoo user-agent identity (required by fair-use)
|
||||
SEC_OPERATOR_EMAIL=you@example.com
|
||||
YF_OPERATOR_EMAIL=you@example.com
|
||||
|
||||
# Optional vendor keys
|
||||
FRED_API_KEY=
|
||||
|
||||
# Ornith on the LAN (not localhost — that is inside the container)
|
||||
LLM_PROVIDER_URL=http://10.37.0.165:30081/v1
|
||||
ORNITH_LLM_URL=http://10.37.0.165:30081/v1
|
||||
@@ -0,0 +1,27 @@
|
||||
# Gitea Actions runner for Unraid. One-time setup so CI/CD actually executes.
|
||||
# Current Gitea (unraid.local:3003) has Actions enabled but zero runners —
|
||||
# every workflow run is cancelled until this container is registered.
|
||||
#
|
||||
# 1. In Gitea: Site Administration → Actions → Runners → Create new runner
|
||||
# Copy the registration token.
|
||||
# 2. Put the token in .env next to this file:
|
||||
# GITEA_INSTANCE_URL=http://10.37.0.86:3003
|
||||
# GITEA_RUNNER_REGISTRATION_TOKEN=...
|
||||
# 3. docker compose -f act-runner-compose.yml up -d
|
||||
# 4. Confirm the runner is Idle on the Gitea runners page.
|
||||
|
||||
name: gitea-act-runner
|
||||
|
||||
services:
|
||||
runner:
|
||||
image: gitea/act_runner:0.2.13
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
CONFIG_FILE: /config.yaml
|
||||
GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL:-http://10.37.0.86:3003}
|
||||
GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:?set registration token}
|
||||
GITEA_RUNNER_NAME: ${GITEA_RUNNER_NAME:-unraid-investor-flow}
|
||||
GITEA_RUNNER_LABELS: ubuntu-latest:docker://gitea/runner-images:ubuntu-22.04
|
||||
volumes:
|
||||
- ${GITEA_RUNNER_DATA:-/mnt/cache/appdata/gitea-runner}:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
@@ -0,0 +1,55 @@
|
||||
# Unraid stack that *pulls* prebuilt images from the Gitea registry.
|
||||
# Use this after CI/CD has pushed at least one tag.
|
||||
#
|
||||
# Place next to a `.env` (see .env.example) and run:
|
||||
# docker compose -f compose.pull.yml pull
|
||||
# docker compose -f compose.pull.yml up -d
|
||||
|
||||
name: investor-flow
|
||||
|
||||
services:
|
||||
backend:
|
||||
image: ${GITEA_REGISTRY:-unraid.local:3003}/transnet/investor-flow-backend:${IFLOW_TAG:-latest}
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${IFLOW_BACKEND_PORT:-3001}:3001"
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
HOST: 0.0.0.0
|
||||
PORT: 3001
|
||||
IFLOW_DB_PATH: /app/data/investor-flow.db
|
||||
IFLOW_SESSION_SECRET: ${IFLOW_SESSION_SECRET:?set IFLOW_SESSION_SECRET}
|
||||
IFLOW_CRYPTO_KEY: ${IFLOW_CRYPTO_KEY:-}
|
||||
SEC_OPERATOR_EMAIL: ${SEC_OPERATOR_EMAIL:-operator@example.com}
|
||||
YF_OPERATOR_EMAIL: ${YF_OPERATOR_EMAIL:-${SEC_OPERATOR_EMAIL:-operator@example.com}}
|
||||
FRED_API_KEY: ${FRED_API_KEY:-}
|
||||
LLM_PROVIDER_URL: ${LLM_PROVIDER_URL:-}
|
||||
ORNITH_LLM_URL: ${ORNITH_LLM_URL:-${LLM_PROVIDER_URL:-}}
|
||||
volumes:
|
||||
- ${IFLOW_DATA_DIR}:/app/data
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3001/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
|
||||
frontend:
|
||||
image: ${GITEA_REGISTRY:-unraid.local:3003}/transnet/investor-flow-frontend:${IFLOW_TAG:-latest}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
backend:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "${IFLOW_WEB_PORT:-3000}:3000"
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
HOSTNAME: 0.0.0.0
|
||||
PORT: 3000
|
||||
IFLOW_BACKEND_URL: http://backend:3001
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
# Unraid User Scripts → "Run in background" on a 5–15 min cron.
|
||||
# Pulls main from Gitea and rebuilds the stack when HEAD moved.
|
||||
#
|
||||
# First-time:
|
||||
# mkdir -p /mnt/cache/appdata/investor-flow
|
||||
# git clone http://unraid.local:3003/transnet/investor-flow.git \
|
||||
# /mnt/cache/appdata/investor-flow/repo
|
||||
# cp /mnt/cache/appdata/investor-flow/repo/deploy/unraid/.env.example \
|
||||
# /mnt/cache/appdata/investor-flow/.env
|
||||
# # edit .env
|
||||
# Then point this script at those paths (or set the env vars below).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO_DIR="${IFLOW_REPO_DIR:-/mnt/cache/appdata/investor-flow/repo}"
|
||||
ENV_FILE="${IFLOW_ENV_FILE:-/mnt/cache/appdata/investor-flow/.env}"
|
||||
COMPOSE="docker compose --project-directory ${REPO_DIR} --env-file ${ENV_FILE}"
|
||||
LOG_TAG="investor-flow-cd"
|
||||
|
||||
log() { echo "[${LOG_TAG}] $*"; }
|
||||
|
||||
if [[ ! -d "${REPO_DIR}/.git" ]]; then
|
||||
log "ERROR: ${REPO_DIR} is not a git checkout"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "${ENV_FILE}" ]]; then
|
||||
log "ERROR: missing ${ENV_FILE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "${REPO_DIR}"
|
||||
git fetch --prune origin main
|
||||
LOCAL=$(git rev-parse HEAD)
|
||||
REMOTE=$(git rev-parse origin/main)
|
||||
|
||||
if [[ "${LOCAL}" == "${REMOTE}" ]]; then
|
||||
log "already at ${LOCAL:0:12} — no deploy"
|
||||
# still ensure the stack is up
|
||||
${COMPOSE} up -d --remove-orphans
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "updating ${LOCAL:0:12} → ${REMOTE:0:12}"
|
||||
git merge --ff-only origin/main
|
||||
${COMPOSE} up -d --build --remove-orphans
|
||||
|
||||
# Wait for health
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if curl -fsS "http://127.0.0.1:${IFLOW_WEB_PORT:-3000}/health" >/dev/null \
|
||||
&& curl -fsS "http://127.0.0.1:${IFLOW_BACKEND_PORT:-3001}/health" >/dev/null; then
|
||||
log "healthy after deploy"
|
||||
exit 0
|
||||
fi
|
||||
sleep 3
|
||||
done
|
||||
|
||||
log "WARNING: containers started but health checks did not pass in 30s"
|
||||
${COMPOSE} ps
|
||||
exit 1
|
||||
Reference in New Issue
Block a user