From 472853826c14961f84b9814a2abe7312fa217339 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Sat, 13 Jun 2026 14:19:18 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20GAS=20=EC=9E=90=EB=8F=99=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20=EC=BB=A4=EB=B0=8B/PR=20=EC=8B=9C=20?= =?UTF-8?q?=EC=9B=90=EA=B2=A9=20=EB=B0=B0=ED=8F=AC=20=ED=95=98=EB=93=9C=20?= =?UTF-8?q?=EB=A3=B0=20=EC=B6=94=EA=B0=80=20(2026-06-13)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주요 변경 사항: - tools/deploy_gas.py 추가: * clasp를 사용하여 로컬의 8개 .gs 스크립트 파일과 appsscript.json을 원격 Apps Script 프로젝트에 강제 푸시(clasp push -f)하는 자동화 스크립트 작성 - AGENTS.md 수정: * 3. 하드 룰 섹션에 커밋, 푸쉬, PR 작업 시 반드시 로컬 .gs 파일을 원격 프로젝트에 업로드하고 사용자가 스프레드시트 상의 스크립트(runDataFeed 등)를 직접 실행해 검증하도록 가이드하는 하드 룰 명시 - 검증 결과: python tools/deploy_gas.py 원격 배포(9개 파일 push) 정상 검증 완료 Co-Authored-By: Antigravity AI --- AGENTS.md | 1 + tools/deploy_gas.py | 91 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 tools/deploy_gas.py diff --git a/AGENTS.md b/AGENTS.md index 7606bb4..1bd942c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -55,6 +55,7 @@ - 데이터 흐름은 단방향(Data -> Feature -> Decision -> Execution -> Report) 아키텍처 경계를 유지하며, renderer가 core 계산을 호출하는 역참조를 금지한다. - D+2 영업일 기준 현금을 즉시방어 자산으로 간주하고, 목표 예산 5억 원을 기준으로 포지션 사이징 및 리스크 버킷을 제어한다. - 매주 주말 리밸런싱(rebalance_required=true) 및 매월 1일/11일/21일 중간점검(mid_check_required=true) 운영 cadence를 준수한다. +- 커밋, 푸쉬, PR 작업 시 반드시 로컬의 .gs 파일을 Google Apps Script 원격 프로젝트에 업로드(python tools/deploy_gas.py 실행)하고, 사용자에게 스프레드시트 상의 스크립트 실행(예: runDataFeed)을 통한 검증을 유도 및 가이드해야 한다. ## 4. 보고 규칙 - 모든 숫자에는 반드시 provenance(출처)를 남기며, 출처가 유효하지 않거나 없는 숫자는 보고서 표기를 전면 배제(DATA_MISSING 처리)한다. diff --git a/tools/deploy_gas.py b/tools/deploy_gas.py new file mode 100644 index 0000000..ba30f04 --- /dev/null +++ b/tools/deploy_gas.py @@ -0,0 +1,91 @@ +import os +import shutil +import json +import subprocess +from pathlib import Path + +# Resolve project root dynamically relative to this script's directory (tools/) +ROOT = Path(__file__).resolve().parent.parent +DEPLOY_DIR = ROOT / "Temp" / "gas_deploy" + +GAS_FILES = [ + "gas_data_feed.gs", + "gas_data_collect.gs", + "gas_lib.gs", + "gas_harness_rows.gs", + "gas_report.gs", + "gas_event_calendar.gs", + "gas_apex_alpha_watch.gs", + "gas_apex_runtime_core.gs" +] + +def main(): + print(f"Preparing deployment directory: {DEPLOY_DIR}") + if DEPLOY_DIR.exists(): + shutil.rmtree(DEPLOY_DIR) + DEPLOY_DIR.mkdir(parents=True, exist_ok=True) + + # 1. Copy appsscript.json manifest + manifest_src = ROOT / "src" / "gas_adapter_parts" / "appsscript.json" + if manifest_src.exists(): + shutil.copy(manifest_src, DEPLOY_DIR / "appsscript.json") + print(f"Copied appsscript.json from {manifest_src}") + else: + # Create default manifest + manifest = { + "timeZone": "Asia/Seoul", + "dependencies": {}, + "exceptionLogging": "STACKDRIVER", + "runtimeVersion": "V8" + } + with open(DEPLOY_DIR / "appsscript.json", "w", encoding="utf-8") as f: + json.dump(manifest, f, ensure_ascii=False, indent=2) + print("Created default appsscript.json") + + # 2. Copy GAS files from ROOT to DEPLOY_DIR + copied_count = 0 + for gf in GAS_FILES: + src = ROOT / gf + if src.exists(): + shutil.copy(src, DEPLOY_DIR / gf) + print(f"Copied {gf}") + copied_count += 1 + else: + print(f"WARNING: Source file not found: {gf}") + + # 3. Create/Overwrite .clasp.json with DEPLOY_DIR as rootDir + clasp_cfg = { + "scriptId": "1xfeBAeeknmnBtSvrIqWXO_2hc3ByeriLUOSuOOB4YxLLHhN3zdnL7tVh", + "rootDir": str(DEPLOY_DIR.relative_to(ROOT)) + } + with open(ROOT / ".clasp.json", "w", encoding="utf-8") as f: + json.dump(clasp_cfg, f, ensure_ascii=False, indent=2) + print(f"Updated .clasp.json with rootDir={clasp_cfg['rootDir']}") + + # 4. Run clasp push with shell=True for Windows compatibility + print("Running npx @google/clasp push -f ...") + env = dict(os.environ) + res = subprocess.run( + ["npx", "@google/clasp", "push", "-f"], + cwd=str(ROOT), + env=env, + shell=True, + capture_output=True, + text=True, + encoding="utf-8", + errors="replace" + ) + print(f"Return code: {res.returncode}") + print("STDOUT:") + print(res.stdout) + print("STDERR:") + print(res.stderr) + + if res.returncode == 0: + print("GAS deploy completed successfully!") + else: + print("GAS deploy failed!") + exit(1) + +if __name__ == "__main__": + main()