4c00229442
이전 커밋들에서 추가한 기능을 실제로 동작시키는 배선 작업. - .gitea/workflows/ci.yml: No Direct API Trading 게이트, KIS 자격증명 검증(mock), 캘리브레이션 백로그 빌드, 정성매도 파이프라인 검증, Gitea secrets 계약 검증, snapshot admin 워크플로/웹 검증 단계 추가 - package.json: ops:data-collect, ops:sell-*, ops:snapshot-*, ops:calibration-* npm 스크립트 추가 - src/gas/core/gas_lib.gs doPost(): "trigger_run_all" action 추가 — Gitea CI가 공유 비밀키로 run_all()을 원격 트리거(주문 실행 없음, governance/rules/06·07과 동일 원칙) - tools/trigger_gas_run_all_v1.py: 위 GAS 엔드포인트를 호출하는 CLI - AGENTS.md/README.md: 신규 파일 인덱스 및 사용 가이드 갱신
52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
"""GAS run_all()을 Gitea CI 스케줄러에서 원격 트리거.
|
|
|
|
언어 선택: Python — 이미 이 저장소의 모든 CI/도구가 Python이고(requests만으로 HTTP POST
|
|
한 번이면 충분), 새 언어를 도입할 이유가 없다(불필요한 복잡성 증가 경계).
|
|
|
|
대상 엔드포인트: src/gas/core/gas_lib.gs:doPost action="trigger_run_all" — 공유 비밀키로
|
|
보호된 GAS 웹앱. run_all()은 데이터 갱신/분석만 수행하며 매수/매도 주문을 실행하지
|
|
않는다(governance/rules/06,07과 동일 원칙).
|
|
|
|
필요한 자격정보(Windows 환경변수, KIS와 동일한 레지스트리 폴백 사용):
|
|
GAS_WEBAPP_URL — Apps Script 배포 웹앱 URL
|
|
RUN_ALL_TRIGGER_SECRET — gas_lib.gs Script Properties에 설정한 것과 동일한 값
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import requests
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
if str(ROOT) not in sys.path:
|
|
sys.path.insert(0, str(ROOT))
|
|
|
|
from src.quant_engine.kis_api_client_v1 import _read_env_var # 동일한 env+registry 폴백 재사용
|
|
|
|
|
|
def trigger_run_all(timeout_sec: int = 280) -> dict:
|
|
webapp_url = _read_env_var("GAS_WEBAPP_URL")
|
|
secret = _read_env_var("RUN_ALL_TRIGGER_SECRET")
|
|
if not webapp_url or not secret:
|
|
return {"status": "ERROR", "message": "GAS_WEBAPP_URL/RUN_ALL_TRIGGER_SECRET 환경변수 없음"}
|
|
|
|
resp = requests.post(
|
|
webapp_url,
|
|
json={"action": "trigger_run_all", "secret": secret},
|
|
timeout=timeout_sec,
|
|
)
|
|
resp.raise_for_status()
|
|
return resp.json()
|
|
|
|
|
|
def main() -> int:
|
|
result = trigger_run_all()
|
|
print(json.dumps(result, ensure_ascii=False, indent=2))
|
|
return 0 if result.get("status") == "OK" else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|