chore: Clean up all archived and unused workflow files - keep only ci.yml and deploy-prod.yml
Deploy to Production / Deploy (push) Failing after 25s

This commit is contained in:
2026-07-11 22:10:36 +09:00
parent ce2c4e42a3
commit 571d299d8a
8 changed files with 0 additions and 989 deletions
-15
View File
@@ -1,15 +0,0 @@
name: backup
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch: {}
jobs:
backup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run backup
run: python tools/backup_data_feed_and_databases_v1.py
@@ -1,161 +0,0 @@
name: ARCHIVED - Build & Package (replaced by merge-to-main.yml)
# This workflow has been replaced by .gitea/workflows/merge-to-main.yml
# Triggers are disabled. Kept for reference only.
on:
# DISABLED - use merge-to-main.yml instead
workflow_dispatch: ~
env:
DOTNET_VERSION: '10.0.x'
REGISTRY: ghcr.io
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: write
packages: write
outputs:
build-tag: ${{ steps.metadata.outputs.tag }}
commit-hash: ${{ steps.metadata.outputs.commit }}
build-time: ${{ steps.metadata.outputs.build-time }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install Python Dependencies
run: pip install pyyaml openpyxl requests
- name: "[GATE] Run Critical Validations"
run: |
echo "🔐 Running critical CI validations..."
python3 tools/validate_no_direct_api_trading_v1.py || exit 1
python3 tools/validate_specs.py || exit 1
echo "✅ All critical validations passed"
- name: Prepare Temp Directory
run: |
mkdir -p Temp
if [ ! -f Temp/final_decision_packet_active.json ]; then
echo '{"active_decision": "PASS", "details": "CI dummy packet"}' > Temp/final_decision_packet_active.json
fi
- name: Restore .NET Dependencies
run: dotnet restore src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj
- name: Build Release
run: |
dotnet build src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
-c Release \
--no-restore
- name: Run Unit Tests
run: |
dotnet test src/dotnet/QuantEngine.Core.Tests/QuantEngine.Core.Tests.csproj \
-c Release \
--no-build
- name: Publish Release Package
run: |
dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
-c Release \
--no-build \
-o ./publish
- name: Generate Build Metadata
id: metadata
run: |
COMMIT=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
BUILD_TAG="build-${COMMIT}"
mkdir -p ./publish/wwwroot
cat > ./publish/wwwroot/version.json <<VERSIONEOF
{
"version": "1.0.${{ github.run_number }}-${COMMIT}",
"commit": "${COMMIT}",
"built": "${BUILD_TIME}",
"buildNumber": ${{ github.run_number }}
}
VERSIONEOF
echo "tag=${BUILD_TAG}" >> $GITHUB_OUTPUT
echo "commit=${COMMIT}" >> $GITHUB_OUTPUT
echo "build-time=${BUILD_TIME}" >> $GITHUB_OUTPUT
echo "✓ Build metadata: ${BUILD_TAG} @ ${BUILD_TIME}"
- name: Create Deployment Package
run: |
echo "📦 Creating deployment package..."
tar -czf quantengine-${{ steps.metadata.outputs.commit }}.tar.gz \
-C ./publish .
PACKAGE_SIZE=$(du -sh quantengine-${{ steps.metadata.outputs.commit }}.tar.gz | cut -f1)
echo "✓ Package created: ${PACKAGE_SIZE}"
# Verify package integrity
tar -tzf quantengine-${{ steps.metadata.outputs.commit }}.tar.gz > /dev/null || exit 1
echo "✓ Package integrity verified"
- name: Create GitHub Release
uses: ncipollo/release-action@v1
with:
tag: ${{ steps.metadata.outputs.tag }}
name: Build ${{ steps.metadata.outputs.tag }}
body: |
**Build Information**
- **Commit**: `${{ steps.metadata.outputs.commit }}`
- **Built At**: ${{ steps.metadata.outputs.build-time }}
- **Build Number**: ${{ github.run_number }}
**Quality Gates**
- ✅ No direct API trading validation
- ✅ Specification validation
- ✅ Unit tests passed
**Release Package**
- Release artifact: `quantengine-${{ steps.metadata.outputs.commit }}.tar.gz`
- Size: $(du -sh quantengine-${{ steps.metadata.outputs.commit }}.tar.gz | cut -f1)
**Deployment Instructions**
```bash
# Trigger production deployment with this build
curl -X POST https://gitea.taxbaik.com/api/v1/repos/kjh2064/QuantEngineByItz/actions/workflows/deploy-prod.yml/dispatches \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"ref":"main", "inputs":{"release_tag":"${{ steps.metadata.outputs.tag }}"}}'
```
draft: false
prerelease: false
artifacts: quantengine-${{ steps.metadata.outputs.commit }}.tar.gz
artifactErrorsFailBuild: true
updateLatestRelease: true
- name: Notify Build Success
if: success()
run: |
echo "✅ Build ${{ steps.metadata.outputs.tag }} completed successfully"
echo "📦 Package available at release: ${{ steps.metadata.outputs.tag }}"
- name: Notify Build Failure
if: failure()
run: |
echo "❌ Build ${{ steps.metadata.outputs.tag }} failed"
exit 1
@@ -1,80 +0,0 @@
name: Calibration Backlog (Registry Drift Watch)
on:
schedule:
- cron: "15 2 * * 1-5" # UTC 02:15 = KST 11:15, weekday backlog update
workflow_dispatch:
jobs:
build-calibration-backlog:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
run: |
if [ -d .git ]; then
git remote set-url origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
else
git init
git remote add origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
fi
git fetch origin main --depth=1
git reset --hard FETCH_HEAD
- name: Configure Runtime Paths
run: |
export PATH=/usr/local/bin:$PATH
echo "/usr/local/bin" >> $GITHUB_PATH
/usr/bin/python3 --version
- name: Setup Python Environment
run: |
VENV_BASE=/volume1/gitea/python_venv
REQ_HASH=$(md5sum tools/build_calibration_priority_v1.py 2>/dev/null | cut -d' ' -f1 || echo "calib-default")
VENV="$VENV_BASE/$REQ_HASH"
if [ ! -f "$VENV/bin/python" ]; then
mkdir -p "$VENV_BASE"
/usr/bin/python3 -m venv "$VENV"
if [ ! -f "$VENV/bin/pip" ]; then
curl -sS https://bootstrap.pypa.io/pip/3.8/get-pip.py -o get-pip.py
"$VENV/bin/python" get-pip.py --quiet
rm get-pip.py
fi
"$VENV/bin/pip" install --upgrade pip --quiet
"$VENV/bin/pip" install pyyaml --quiet
fi
echo "$VENV/bin" >> $GITHUB_PATH
- name: Validate Calibration Registry
run: python3 tools/validate_calibration_registry_v1.py
- name: Build Calibration Priority Backlog
run: python3 tools/build_calibration_priority_v1.py
- name: Build Calibration Change Ledger
run: python3 tools/build_calibration_change_ledger_v4.py
- name: Build Calibration Review Report
run: python3 tools/build_calibration_review_report_v1.py
- name: Build Calibration Approval List
run: python3 tools/build_calibration_approval_list_v1.py
- name: Build Calibration Decision Draft
run: python3 tools/build_calibration_decision_draft_v1.py
- name: Validate Calibration Change Ledger
run: python3 tools/validate_calibration_change_ledger_v1.py
- name: Summarize Backlog
if: always()
run: |
STATUS="${{ job.status }}"
echo "=== Calibration Backlog Result ==="
echo "status: $STATUS"
echo "priority: Temp/calibration_priority_v1.json"
echo "ledger: Temp/calibration_change_ledger_v4.json"
echo "review: Temp/calibration_review_report_v1.md"
echo "approval: Temp/calibration_approval_list_v1.md"
echo "decision: Temp/calibration_decision_draft_v1.md"
@@ -1,244 +0,0 @@
name: KIS Data Collection (SQLite Canonical Feed)
# ─────────────────────────────────────────────────────────────────
# [중요] 이 워크플로우는 KIS Open API를 코어로 하는 read-only 데이터 수집만 수행한다.
# GatherTradingData.json + live read-only APIs를 통해 SQLite canonical store를 갱신한다.
# xlsx는 이 워크플로우의 직접 입력이 아니며, KIS 실패 시에만 별도 보조 경로에서 사용한다.
#
# 스케줄: 영업일(월~금) 08:00~17:00 KST, 2시간 간격(08/10/12/14/16시).
# Gitea Actions의 schedule cron은 UTC 기준으로 평가된다(서버 타임존이 별도
# 설정되어 있지 않은 경우의 기본값). 아래 cron은 UTC로 작성했다:
# KST 08:00 = UTC 전날 23:00 → 요일은 "한국 기준 평일"에 맞춰 UTC 0-4(일~목)로 이동
# KST 10/12/14/16:00 = UTC 01/03/05/07:00, 같은 날(UTC 월~금, 1-5)
#
# [실제 Gitea 서버 타임존이 Asia/Seoul로 설정되어 있다면] 아래 cron을 그대로
# "0 8,10,12,14,16 * * 1-5" 한 줄로 교체하면 된다 — 첫 실행 후 Actions 실행
# 기록의 타임스탬프를 확인해 KST 08시 전후로 도는지 검증할 것(추정하지 말고 확인).
#
# 스케줄 주기 변경: 아래 schedule 목록의 cron 줄을 추가/삭제/수정하면 된다.
# 예) 1시간 간격으로 바꾸려면 09,11,13,15시 슬롯을 추가.
# ─────────────────────────────────────────────────────────────────
on:
schedule:
- cron: "0 23 * * 0-4" # KST 월~금 08:00 (UTC 일~목 23:00)
- cron: "0 1 * * 1-5" # KST 월~금 10:00 (UTC 01:00)
- cron: "0 3 * * 1-5" # KST 월~금 12:00 (UTC 03:00)
- cron: "0 5 * * 1-5" # KST 월~금 14:00 (UTC 05:00)
- cron: "0 7 * * 1-5" # KST 월~금 16:00 (UTC 07:00)
workflow_dispatch: # 수동 실행 — 스케줄 검증/즉시 재시도용
jobs:
validate-kis-config-smoke:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
run: |
if [ -d .git ]; then
git remote set-url origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
else
git init
git remote add origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
fi
TARGET_REF="${GITHUB_REF_NAME:-main}"
git fetch origin "$TARGET_REF" --depth=1
git reset --hard FETCH_HEAD
- name: Setup Python Environment
run: |
VENV_BASE=/volume1/gitea/python_venv
REQ_HASH=$(md5sum tools/run_kis_data_collection_v1.py 2>/dev/null | cut -d' ' -f1 || echo "kis-default")
VENV="$VENV_BASE/$REQ_HASH"
if [ ! -f "$VENV/bin/python" ]; then
mkdir -p "$VENV_BASE"
/usr/bin/python3 -m venv "$VENV"
if [ ! -f "$VENV/bin/pip" ]; then
curl -sS https://bootstrap.pypa.io/pip/3.8/get-pip.py -o get-pip.py
"$VENV/bin/python" get-pip.py --quiet
rm get-pip.py
fi
"$VENV/bin/pip" install --upgrade pip --quiet
"$VENV/bin/pip" install requests beautifulsoup4 pyyaml --quiet
ls -dt "$VENV_BASE"/*/ 2>/dev/null | tail -n +3 | xargs rm -rf 2>/dev/null || true
fi
"$VENV/bin/pip" install requests beautifulsoup4 pyyaml --quiet
echo "$VENV/bin" >> $GITHUB_PATH
- name: "[CRITICAL] No Direct API Trading Gate"
run: python3 tools/validate_no_direct_api_trading_v1.py
- name: "[CRITICAL] Validate KIS API Credentials (mock)"
env:
# Gitea repository variables are injected here; the Python loader reads these env names.
KIS_APP_Key_TEST: ${{ vars.KIS_APP_KEY_TEST }}
KIS_APP_Secret_TEST: ${{ vars.KIS_APP_SECRET_TEST }}
run: |
if [ -z "${KIS_APP_Key_TEST:-}" ]; then
echo "::error::Gitea variable KIS_APP_KEY_TEST is missing or empty"
exit 1
fi
if [ -z "${KIS_APP_Secret_TEST:-}" ]; then
echo "::error::Gitea variable KIS_APP_SECRET_TEST is missing or empty"
exit 1
fi
python3 tools/validate_kis_api_credentials_v1.py \
--account mock \
--ticker 005930 \
--dry-run
collect-kis-data-live:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
run: |
if [ -d .git ]; then
git remote set-url origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
else
git init
git remote add origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
fi
TARGET_REF="${GITHUB_REF_NAME:-main}"
git fetch origin "$TARGET_REF" --depth=1
git reset --hard FETCH_HEAD
- name: Prepare Raw Seed Snapshot
run: |
if [ -f GatherTradingData.json ]; then
echo "GatherTradingData.json present"
exit 0
fi
if [ -f .clasprc.json ]; then
echo "GatherTradingData.json missing; seed regeneration is not performed in this workflow."
echo "::error::Commit or pre-stage GatherTradingData.json before running this workflow."
echo "::error::If workbook conversion is required, run tools/convert_xlsx_to_json.py in a separate seed-prep step."
exit 1
fi
echo "::error::GatherTradingData.json is missing."
echo "::error::This workflow is JSON-first and does not consume GatherTradingData.xlsx directly."
echo "::error::Fix options:"
echo "::error:: 1) Commit GatherTradingData.json to the repository tree."
echo "::error:: 2) Run a separate seed-prep job to generate GatherTradingData.json from workbook sources."
exit 1
- name: Configure Runtime Paths
run: |
export PATH=/usr/local/bin:$PATH
echo "/usr/local/bin" >> $GITHUB_PATH
/usr/bin/python3 --version
- name: Setup Python Environment
run: |
VENV_BASE=/volume1/gitea/python_venv
REQ_HASH=$(md5sum tools/run_kis_data_collection_v1.py 2>/dev/null | cut -d' ' -f1 || echo "kis-default")
VENV="$VENV_BASE/$REQ_HASH"
if [ ! -f "$VENV/bin/python" ]; then
mkdir -p "$VENV_BASE"
/usr/bin/python3 -m venv "$VENV"
if [ ! -f "$VENV/bin/pip" ]; then
curl -sS https://bootstrap.pypa.io/pip/3.8/get-pip.py -o get-pip.py
"$VENV/bin/python" get-pip.py --quiet
rm get-pip.py
fi
"$VENV/bin/pip" install --upgrade pip --quiet
"$VENV/bin/pip" install requests beautifulsoup4 pyyaml --quiet
ls -dt "$VENV_BASE"/*/ 2>/dev/null | tail -n +3 | xargs rm -rf 2>/dev/null || true
fi
"$VENV/bin/pip" install requests beautifulsoup4 pyyaml --quiet
echo "$VENV/bin" >> $GITHUB_PATH
- name: "[CRITICAL] No Direct API Trading Gate"
run: python3 tools/validate_no_direct_api_trading_v1.py
- name: Collect KIS Market Data to SQLite (read-only)
env:
# Real collection uses repository variables, not Windows shell env syntax.
KIS_APP_Key: ${{ vars.KIS_APP_KEY }}
KIS_APP_Secret: ${{ vars.KIS_APP_SECRET }}
run: |
if [ -z "${KIS_APP_Key:-}" ]; then
echo "::error::Gitea variable KIS_APP_KEY is missing or empty"
exit 1
fi
if [ -z "${KIS_APP_Secret:-}" ]; then
echo "::error::Gitea variable KIS_APP_SECRET is missing or empty"
exit 1
fi
python3 tools/run_kis_data_collection_v1.py \
--input-json GatherTradingData.json \
--sqlite-db outputs/kis_data_collection/kis_data_collection.db \
--output-json Temp/kis_data_collection_v1.json \
--kis-account real
- name: Validate SQLite Artifact
run: |
python3 - <<'PY'
import json, sqlite3
from pathlib import Path
db = Path("outputs/kis_data_collection/kis_data_collection.db")
report = Path("Temp/kis_data_collection_v1.json")
assert db.exists(), f"missing db: {db}"
assert report.exists(), f"missing report: {report}"
conn = sqlite3.connect(db)
try:
run_count = conn.execute("SELECT COUNT(*) FROM collection_runs").fetchone()[0]
snap_count = conn.execute("SELECT COUNT(*) FROM collection_snapshots").fetchone()[0]
print(json.dumps({"run_count": run_count, "snapshot_count": snap_count}, ensure_ascii=False))
assert run_count >= 1
assert snap_count >= 1
finally:
conn.close()
PY
- name: Backup SQLite Database (WBS-9.7)
if: always()
run: |
BACKUP_BASE="/volume1/gitea/backups/kis_data_collection"
mkdir -p "$BACKUP_BASE"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
SOURCE_DB="outputs/kis_data_collection/kis_data_collection.db"
BACKUP_DIR="$BACKUP_BASE/$TIMESTAMP"
BACKUP_DB="$BACKUP_DIR/kis_data_collection.db"
if [ -f "$SOURCE_DB" ]; then
mkdir -p "$BACKUP_DIR"
cp "$SOURCE_DB" "$BACKUP_DB"
echo "Backup created: $BACKUP_DB"
# 메타데이터 저장 (backup manifest)
cat > "$BACKUP_DIR/manifest.json" <<EOF
{
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"source_db": "$SOURCE_DB",
"backup_db": "$BACKUP_DB",
"job_id": "${{ github.run_id }}",
"branch": "${{ github.ref }}",
"status": "${{ job.status }}"
}
EOF
# 오래된 백업 정리 (7일 이상 된 것 삭제)
find "$BACKUP_BASE" -mindepth 1 -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \; 2>/dev/null || true
else
echo "::warning::Source DB not found: $SOURCE_DB"
fi
- name: Notify Run Result
if: always()
run: |
STATUS="${{ job.status }}"
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
SUMMARY_FILE="Temp/kis_data_collection_v1.json"
SUMMARY_TEXT="(요약 파일 없음)"
[ -f "$SUMMARY_FILE" ] && SUMMARY_TEXT=$(cat "$SUMMARY_FILE")
echo "=== KIS Data Collection Result ==="
echo "status: $STATUS"
echo "summary: $SUMMARY_TEXT"
echo "run log: $RUN_URL"
@@ -1,156 +0,0 @@
name: Qualitative Sell Strategy (Read-Only, SQLite Canonical)
on:
schedule:
- cron: "0 10 * * 1-5" # KST 19:00-ish daily post-close batch window (UTC 10:00)
workflow_dispatch:
jobs:
evaluate-qualitative-sell:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
run: |
if [ -d .git ]; then
git remote set-url origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
else
git init
git remote add origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
fi
TARGET_REF="${GITHUB_REF_NAME:-main}"
git fetch origin "$TARGET_REF" --depth=1
git reset --hard FETCH_HEAD
- name: Prepare Raw Seed Snapshot
run: |
if [ -f GatherTradingData.json ]; then
echo "GatherTradingData.json present"
exit 0
fi
if [ -f GatherTradingData.xlsx ]; then
echo "GatherTradingData.json missing; regenerating from GatherTradingData.xlsx"
python3 tools/convert_xlsx_to_json.py \
--xlsx GatherTradingData.xlsx \
--out GatherTradingData.json
if [ -f GatherTradingData.json ]; then
echo "GatherTradingData.json regenerated successfully"
exit 0
fi
echo "::error::GatherTradingData.xlsx is present but JSON regeneration failed."
echo "::error::Check tools/convert_xlsx_to_json.py and workbook sheet integrity."
exit 1
fi
if [ -f .clasprc.json ]; then
echo "GatherTradingData seed files missing; downloading GatherTradingData.xlsx from Google Drive via .clasprc.json"
python3 tools/download_trading_data.py
if [ -f GatherTradingData.xlsx ]; then
echo "GatherTradingData.xlsx downloaded successfully; regenerating GatherTradingData.json"
python3 tools/convert_xlsx_to_json.py \
--xlsx GatherTradingData.xlsx \
--out GatherTradingData.json
if [ -f GatherTradingData.json ]; then
echo "GatherTradingData.json regenerated successfully from downloaded workbook"
exit 0
fi
echo "::error::Downloaded GatherTradingData.xlsx but JSON regeneration failed."
echo "::error::Check workbook integrity and tools/convert_xlsx_to_json.py."
exit 1
fi
echo "::error::.clasprc.json exists but GatherTradingData.xlsx was not downloaded."
echo "::error::Check Google Drive access and tools/download_trading_data.py."
exit 1
fi
echo "::error::Neither GatherTradingData.json nor GatherTradingData.xlsx exists in the checked-out tree."
echo "::error::This workflow requires a canonical seed snapshot before batch build can start."
echo "::error::Fix options:"
echo "::error:: 1) Commit GatherTradingData.json to the repository tree."
echo "::error:: 2) Commit GatherTradingData.xlsx so the workflow can regenerate the JSON."
echo "::error:: 3) Provide .clasprc.json so the workflow can download GatherTradingData.xlsx from Google Drive and regenerate the JSON."
echo "::error:: 4) If neither file should be tracked, add a prior step that downloads the seed before collection."
exit 1
- name: Configure Runtime Paths
run: |
export PATH=/usr/local/bin:$PATH
echo "/usr/local/bin" >> $GITHUB_PATH
/usr/bin/python3 --version
- name: Setup Python Environment
run: |
VENV_BASE=/volume1/gitea/python_venv
REQ_HASH=$(md5sum tools/build_qualitative_sell_inputs_v1.py 2>/dev/null | cut -d' ' -f1 || echo "qual-default")
VENV="$VENV_BASE/$REQ_HASH"
if [ ! -f "$VENV/bin/python" ]; then
mkdir -p "$VENV_BASE"
/usr/bin/python3 -m venv "$VENV"
"$VENV/bin/pip" install --upgrade pip --quiet
"$VENV/bin/pip" install requests beautifulsoup4 pyyaml openpyxl --quiet
fi
"$VENV/bin/pip" install requests beautifulsoup4 pyyaml openpyxl --quiet
echo "$VENV/bin" >> $GITHUB_PATH
- name: "[CRITICAL] No Direct API Trading Gate"
run: python3 tools/validate_no_direct_api_trading_v1.py
- name: "[CRITICAL] Validate KIS API Credentials (mock)"
env:
# Mock validation is wired from Gitea repository variables.
KIS_APP_Key_TEST: ${{ vars.KIS_APP_KEY_TEST }}
KIS_APP_Secret_TEST: ${{ vars.KIS_APP_SECRET_TEST }}
run: |
if [ -z "${KIS_APP_Key_TEST:-}" ]; then
echo "::error::Gitea variable KIS_APP_KEY_TEST is missing or empty"
exit 1
fi
if [ -z "${KIS_APP_Secret_TEST:-}" ]; then
echo "::error::Gitea variable KIS_APP_SECRET_TEST is missing or empty"
exit 1
fi
python3 tools/validate_kis_api_credentials_v1.py --account mock --ticker 005930 --dry-run
- name: Build Qualitative Sell Inputs (batch)
env:
# Real batch build reads the same repository variables as KIS collection.
KIS_APP_Key: ${{ vars.KIS_APP_KEY }}
KIS_APP_Secret: ${{ vars.KIS_APP_SECRET }}
run: |
if [ -z "${KIS_APP_Key:-}" ]; then
echo "::error::Gitea variable KIS_APP_KEY is missing or empty"
exit 1
fi
if [ -z "${KIS_APP_Secret:-}" ]; then
echo "::error::Gitea variable KIS_APP_SECRET is missing or empty"
exit 1
fi
if [ -f GatherTradingData.xlsx ]; then
python3 tools/build_qualitative_sell_inputs_v1.py \
--batch \
--workbook GatherTradingData.xlsx \
--kis-account real \
--apply
else
echo "GatherTradingData.xlsx missing -> skip batch build"
fi
- name: Build Satellite Recommendations
run: |
if [ -f GatherTradingData.xlsx ]; then
python3 tools/build_satellite_candidate_recommendations_v1.py \
--workbook GatherTradingData.xlsx \
--apply
else
echo "GatherTradingData.xlsx missing -> skip satellite build"
fi
- name: Evaluate Qualitative Sell Accuracy
run: |
if [ -f outputs/qualitative_sell_strategy/qualitative_sell_strategy.db ]; then
python3 tools/evaluate_qualitative_sell_strategy_accuracy_v1.py \
--sqlite-db outputs/qualitative_sell_strategy/qualitative_sell_strategy.db
else
echo "qualitative_sell_strategy.db missing -> skip accuracy evaluation"
fi
@@ -1,111 +0,0 @@
name: Snapshot Admin Web Validation
on:
workflow_dispatch:
push:
paths:
- "src/quant_engine/snapshot_admin_server_v1.py"
- "src/quant_engine/snapshot_admin_store_v1.py"
- "tools/run_snapshot_admin_server_v1.py"
- "tools/validate_snapshot_admin_workflow_v1.py"
- "tools/validate_snapshot_admin_web_v1.py"
- "spec/15_account_snapshot_contract.yaml"
- "spec/18_settings_contract.yaml"
- "GatherTradingData.json"
jobs:
# Push-only smoke gate: no deployment, no web UI smoke, no long-running side effects.
validate-snapshot-admin-smoke:
if: github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
run: |
echo "[smoke] push-only snapshot admin workflow validation"
if [ -d .git ]; then
git remote set-url origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
else
git init
git remote add origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
fi
git fetch origin main --depth=1
git reset --hard FETCH_HEAD
- name: Setup Python Environment
run: |
echo "[smoke] prepare python venv"
VENV_BASE=/volume1/gitea/python_venv
REQ_HASH=$(md5sum tools/validate_snapshot_admin_workflow_v1.py 2>/dev/null | cut -d' ' -f1 || echo "snapshot-admin-default")
VENV="$VENV_BASE/$REQ_HASH"
if [ ! -f "$VENV/bin/python" ]; then
mkdir -p "$VENV_BASE"
/usr/bin/python3 -m venv "$VENV"
"$VENV/bin/pip" install --upgrade pip --quiet
fi
"$VENV/bin/pip" install pyyaml --quiet
echo "$VENV/bin" >> $GITHUB_PATH
- name: Validate Snapshot Admin Workflow
run: |
echo "[smoke] validate workflow only (no web UI, no deploy)"
python3 tools/validate_snapshot_admin_workflow_v1.py
- name: Validate DB First Pipeline
run: |
echo "[smoke] validate DB-first pipeline contract"
python3 tools/validate_db_first_pipeline_v1.py
# Manual dispatch gate: full workflow + web UI validation only.
validate-snapshot-admin-full:
if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Checkout Code
run: |
echo "[full] workflow_dispatch snapshot admin validation"
if [ -d .git ]; then
git remote set-url origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
else
git init
git remote add origin http://x-access-token:${{ secrets.GITHUB_TOKEN }}@192.168.123.100:8418/KimJaeHyun/myfinance.git
fi
git fetch origin main --depth=1
git reset --hard FETCH_HEAD
- name: Setup Python Environment
run: |
echo "[full] prepare python venv"
VENV_BASE=/volume1/gitea/python_venv
REQ_HASH=$(md5sum tools/validate_snapshot_admin_workflow_v1.py 2>/dev/null | cut -d' ' -f1 || echo "snapshot-admin-default")
VENV="$VENV_BASE/$REQ_HASH"
if [ ! -f "$VENV/bin/python" ]; then
mkdir -p "$VENV_BASE"
/usr/bin/python3 -m venv "$VENV"
"$VENV/bin/pip" install --upgrade pip --quiet
fi
"$VENV/bin/pip" install pyyaml --quiet
echo "$VENV/bin" >> $GITHUB_PATH
- name: Validate Snapshot Admin Workflow
run: |
echo "[full] validate workflow"
python3 tools/validate_snapshot_admin_workflow_v1.py
- name: Validate DB First Pipeline
run: |
echo "[full] validate DB-first pipeline contract"
python3 tools/validate_db_first_pipeline_v1.py
- name: Validate Snapshot Admin Web UI
run: |
echo "[full] validate web ui"
python3 tools/validate_snapshot_admin_web_v1.py
- name: Notify Run Result
if: always()
run: |
STATUS="${{ job.status }}"
echo "=== Snapshot Admin Full Validation ==="
echo "status: $STATUS"
echo "workflow validation: Temp/snapshot_admin_workflow_v1.json"
echo "web validation: Temp/snapshot_admin_web_validation_v1.json"
@@ -1,133 +0,0 @@
name: WBS-9.3 - NULL Policy CI Gate
on:
push:
branches:
- main
- 'feature/**'
paths:
- 'src/**'
- 'spec/12_field_dictionary.yaml'
pull_request:
branches:
- main
jobs:
null-policy-validation:
runs-on: ubuntu-latest
name: NULL Policy Validation
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Python
run: python --version
- name: Run NULL Policy Validation
run: |
python -c "
import sqlite3
from pathlib import Path
import yaml
# Load NULL policy from field dictionary
with open('spec/12_field_dictionary.yaml') as f:
spec = yaml.safe_load(f)
null_policy = spec.get('field_dictionary', {}).get('policy', {})
print(f'[*] NULL Policy loaded: {null_policy}')
# Check both databases
databases = [
'src/quant_engine/kis_data_collection.db',
'src/quant_engine/snapshot_admin.db'
]
all_passed = True
for db_path in databases:
if not Path(db_path).exists():
print(f'[SKIP] {db_path} not found')
continue
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
# Get all tables
cursor.execute(\"SELECT name FROM sqlite_master WHERE type='table'\")
tables = [row[0] for row in cursor.fetchall()]
print(f'\n[CHECK] {db_path}')
for table in tables:
if table == 'sqlite_sequence':
continue
cursor.execute(f'SELECT * FROM {table} LIMIT 1')
if cursor.fetchone() is None:
print(f' [{table}] Empty (OK)')
else:
print(f' [{table}] Has data')
conn.close()
print('\n[RESULT] NULL Policy validation PASS')
"
- name: Validate Field Dictionary Schema
run: |
python -c "
import yaml
from pathlib import Path
with open('spec/12_field_dictionary.yaml') as f:
spec = yaml.safe_load(f)
# Check required sections
required_sections = ['meta', 'field_dictionary']
for section in required_sections:
if section not in spec:
print(f'ERROR: Missing section: {section}')
exit(1)
# Check field_dictionary structure
fd = spec['field_dictionary']
if 'fields' not in fd:
print('ERROR: Missing fields in field_dictionary')
exit(1)
print('[OK] Field dictionary schema valid')
print(f'[OK] Total fields defined: {len(fd[\"fields\"])}')
"
- name: Check FILLABLE vs NOT_FILLABLE
run: |
python -c "
import yaml
with open('spec/12_field_dictionary.yaml') as f:
spec = yaml.safe_load(f)
fields = spec['field_dictionary']['fields']
fillable = 0
not_fillable = 0
for fname, fspec in fields.items():
if 'data_quality_policy' in fspec:
chargeability = fspec['data_quality_policy'].get('chargeability')
if chargeability == 'FILLABLE':
fillable += 1
elif chargeability == 'NOT_FILLABLE':
not_fillable += 1
print(f'[OK] FILLABLE fields: {fillable}')
print(f'[OK] NOT_FILLABLE fields: {not_fillable}')
print('[OK] Data quality policy check complete')
"
- name: Log Results
if: always()
run: |
echo "WBS-9.3 NULL Policy CI Gate completed"
echo "Fields validated: total definitions vs NULL distribution"
@@ -1,89 +0,0 @@
name: Build and Test (Reusable)
on:
workflow_call:
outputs:
artifact-path:
description: "Artifact path"
value: ${{ jobs.build.outputs.artifact-path }}
build-tag:
description: "Build tag"
value: ${{ jobs.build.outputs.build-tag }}
commit-hash:
description: "Commit hash"
value: ${{ jobs.build.outputs.commit-hash }}
env:
DOTNET_VERSION: '10.0.x'
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
artifact-path: quantengine-${{ steps.metadata.outputs.commit }}.tar.gz
build-tag: build-${{ steps.metadata.outputs.commit }}-${{ github.run_number }}
commit-hash: ${{ steps.metadata.outputs.commit }}
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Generate Build Metadata
id: metadata
run: |
COMMIT=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
echo "commit=${COMMIT}" >> $GITHUB_OUTPUT
echo "build-time=${BUILD_TIME}" >> $GITHUB_OUTPUT
- name: Restore Dependencies
run: dotnet restore src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj
- name: Build Release
run: |
dotnet build src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
-c Release --no-restore
- name: Run Unit Tests
run: |
dotnet test src/dotnet/QuantEngine.Core.Tests/QuantEngine.Core.Tests.csproj \
-c Release --no-build || true
- name: Publish Release Package
run: |
dotnet publish src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj \
-c Release --no-build -o ./publish
- name: Create Version Metadata
run: |
mkdir -p ./publish/wwwroot
cat > ./publish/wwwroot/version.json <<EOF
{
"version": "1.0.${{ github.run_number }}-${{ steps.metadata.outputs.commit }}",
"commit": "${{ steps.metadata.outputs.commit }}",
"built": "${{ steps.metadata.outputs.build-time }}",
"buildNumber": ${{ github.run_number }}
}
EOF
- name: Package Artifact
run: |
tar -czf quantengine-${{ steps.metadata.outputs.commit }}.tar.gz \
-C ./publish .
tar -tzf quantengine-${{ steps.metadata.outputs.commit }}.tar.gz > /dev/null || exit 1
- name: Upload Build Artifact
uses: actions/upload-artifact@v3
with:
name: quantengine-build-${{ github.run_number }}
path: quantengine-${{ steps.metadata.outputs.commit }}.tar.gz
retention-days: 5