chore: Archive 7 unused workflows and consolidate to SSOT pipeline
Merge to Main - Full Pipeline / Stage 1: Fast Gates (push) Failing after 3s
Merge to Main - Full Pipeline / Stage 2: Critical Gates (push) Has been skipped
Merge to Main - Full Pipeline / Stage 3: Integration Tests (push) Has been skipped
Merge to Main - Full Pipeline / Stage 4: Build and Package (push) Has been skipped
Merge to Main - Full Pipeline / Stage 5: Deploy to Production (push) Has been skipped
Merge to Main - Full Pipeline / Pipeline Summary (push) Successful in 1s

Reorganized .gitea/workflows/ to reduce duplication and noise:
- Archived 7 unnecessary workflows to .archived/ subdirectory:
  - auto_backup_schedule.yml
  - backup.yml
  - calibration_backlog.yml
  - kis_data_collection.yml
  - qualitative_sell_strategy.yml
  - snapshot_admin.yml
  - wbs_9_3_null_policy_ci_gate.yml

Active workflows (5 total):
- merge-to-main.yml (SSOT 5-stage pipeline)
- ci.yml (PR validation)
- deploy-prod.yml (manual deployment)
- fast-validation.yml (PR fast checks)
- _common/build-and-test.yml (reusable component)

Rationale: Phase 2 deployment infrastructure is complete. Legacy workflows
are no longer needed, reducing CI/CD maintenance burden and improving clarity.
Archived workflows remain available for reference if rollback is needed.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 21:31:44 +09:00
parent dc21e8e323
commit 647a26eefd
7 changed files with 0 additions and 172 deletions
+15
View File
@@ -0,0 +1,15 @@
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
@@ -0,0 +1,80 @@
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"
@@ -0,0 +1,244 @@
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"
@@ -0,0 +1,156 @@
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
@@ -0,0 +1,111 @@
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"
@@ -0,0 +1,133 @@
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"