From 1180d860912152c8ef59e1ad5ef29eb17300395d Mon Sep 17 00:00:00 2001 From: Windmill Bot Date: Sat, 21 Feb 2026 04:00:01 +0000 Subject: [PATCH] Auto-sync: 2026-02-21 04:00:01 --- .../system_heartbeat__flow/flow.yaml | 57 +++++++++++++++++++ .../step1:_診断データ生成.lock | 1 + .../step1:_診断データ生成.py | 20 +++++++ .../step2:_データ検証.lock | 1 + .../step2:_データ検証.py | 32 +++++++++++ .../step3:_httpヘルスチェック.lock | 1 + .../step3:_httpヘルスチェック.py | 31 ++++++++++ .../step4:_年度判定_&_最終レポート.lock | 1 + .../step4:_年度判定_&_最終レポート.py | 41 +++++++++++++ workflows/wmill-lock.yaml | 5 ++ 10 files changed, 190 insertions(+) create mode 100644 workflows/f/app_custom/system_heartbeat__flow/flow.yaml create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.lock create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.py create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.lock create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.py create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.lock create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.py create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.lock create mode 100644 workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.py diff --git a/workflows/f/app_custom/system_heartbeat__flow/flow.yaml b/workflows/f/app_custom/system_heartbeat__flow/flow.yaml new file mode 100644 index 0000000..5edd0ca --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/flow.yaml @@ -0,0 +1,57 @@ +summary: Windmill Heartbeat - システム自己診断 +description: Windmillの動作確認用ワークフロー。UUID生成、時刻取得、計算チェック、HTTPヘルスチェック、年度判定を行い、全ステップの正常性を検証する。 +value: + modules: + - id: a + summary: 'Step1: 診断データ生成' + value: + type: rawscript + content: '!inline step1:_診断データ生成.py' + input_transforms: {} + lock: '!inline step1:_診断データ生成.lock' + language: python3 + - id: b + summary: 'Step2: データ検証' + value: + type: rawscript + content: '!inline step2:_データ検証.py' + input_transforms: + step1_result: + type: javascript + expr: results.a + lock: '!inline step2:_データ検証.lock' + language: python3 + - id: c + summary: 'Step3: HTTPヘルスチェック' + value: + type: rawscript + content: '!inline step3:_httpヘルスチェック.py' + input_transforms: + verification_result: + type: javascript + expr: results.b + lock: '!inline step3:_httpヘルスチェック.lock' + language: python3 + - id: d + summary: 'Step4: 年度判定 & 最終レポート' + value: + type: rawscript + content: '!inline step4:_年度判定_&_最終レポート.py' + input_transforms: + http_check: + type: javascript + expr: results.c + step1_data: + type: javascript + expr: results.a + verification: + type: javascript + expr: results.b + lock: '!inline step4:_年度判定_&_最終レポート.lock' + language: python3 +schema: + $schema: 'https://json-schema.org/draft/2020-12/schema' + type: object + order: [] + properties: {} + required: [] diff --git a/workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.lock b/workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.lock new file mode 100644 index 0000000..3aacf1d --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.lock @@ -0,0 +1 @@ +# py: 3.12 diff --git a/workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.py b/workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.py new file mode 100644 index 0000000..759abc5 --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step1:_診断データ生成.py @@ -0,0 +1,20 @@ +import uuid +from datetime import datetime, timezone + +def main(): + """診断データを生成する""" + now = datetime.now(timezone.utc) + run_id = str(uuid.uuid4()) + check_value = 2 + 2 + + result = { + "timestamp": now.isoformat(), + "run_id": run_id, + "check": check_value, + "python_version": __import__('sys').version + } + print(f"[Step1] 診断データ生成完了") + print(f" run_id: {run_id}") + print(f" timestamp: {now.isoformat()}") + print(f" check: {check_value}") + return result diff --git a/workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.lock b/workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.lock new file mode 100644 index 0000000..3aacf1d --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.lock @@ -0,0 +1 @@ +# py: 3.12 diff --git a/workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.py b/workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.py new file mode 100644 index 0000000..8693572 --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step2:_データ検証.py @@ -0,0 +1,32 @@ +from datetime import datetime, timezone + +def main(step1_result: dict): + """Step1の結果を検証する""" + errors = [] + + # 計算チェック + if step1_result.get("check") != 4: + errors.append(f"計算エラー: expected 4, got {step1_result.get('check')}") + + # run_idの存在チェック + if not step1_result.get("run_id"): + errors.append("run_idが存在しない") + + # timestampの存在チェック + if not step1_result.get("timestamp"): + errors.append("timestampが存在しない") + + if errors: + error_msg = "; ".join(errors) + print(f"[Step2] 検証失敗: {error_msg}") + raise Exception(f"検証失敗: {error_msg}") + + print(f"[Step2] データ検証OK") + print(f" 計算チェック: 2+2={step1_result['check']} ✓") + print(f" run_id: {step1_result['run_id']} ✓") + print(f" timestamp: {step1_result['timestamp']} ✓") + + return { + "verification": "PASS", + "step1_data": step1_result + } diff --git a/workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.lock b/workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.lock new file mode 100644 index 0000000..3aacf1d --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.lock @@ -0,0 +1 @@ +# py: 3.12 diff --git a/workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.py b/workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.py new file mode 100644 index 0000000..90e0fc6 --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step3:_httpヘルスチェック.py @@ -0,0 +1,31 @@ +import urllib.request +import ssl + +def main(verification_result: dict): + """Windmillサーバー自身へのHTTPチェック""" + url = "https://windmill.keinafarm.net/api/version" + + # SSL検証をスキップ(自己署名証明書対応) + ctx = ssl.create_default_context() + ctx.check_hostname = False + ctx.verify_mode = ssl.CERT_NONE + + try: + req = urllib.request.Request(url) + with urllib.request.urlopen(req, context=ctx, timeout=10) as response: + status_code = response.status + body = response.read().decode('utf-8') + except Exception as e: + print(f"[Step3] HTTPチェック失敗: {e}") + raise Exception(f"HTTPヘルスチェック失敗: {e}") + + print(f"[Step3] HTTPヘルスチェックOK") + print(f" URL: {url}") + print(f" Status: {status_code}") + print(f" Version: {body}") + + return { + "http_check": "PASS", + "status_code": status_code, + "server_version": body + } diff --git a/workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.lock b/workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.lock new file mode 100644 index 0000000..3aacf1d --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.lock @@ -0,0 +1 @@ +# py: 3.12 diff --git a/workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.py b/workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.py new file mode 100644 index 0000000..9717da0 --- /dev/null +++ b/workflows/f/app_custom/system_heartbeat__flow/step4:_年度判定_&_最終レポート.py @@ -0,0 +1,41 @@ +from datetime import datetime, timezone + +def main(step1_data: dict, verification: dict, http_check: dict): + """年度判定と最終診断レポートを生成""" + now = datetime.now(timezone.utc) + + # 日本の年度判定(4月始まり) + fiscal_year = now.year if now.month >= 4 else now.year - 1 + + report = { + "status": "ALL OK", + "fiscal_year": fiscal_year, + "diagnostics": { + "data_generation": "PASS", + "data_verification": verification.get("verification", "UNKNOWN"), + "http_health": http_check.get("http_check", "UNKNOWN"), + "server_version": http_check.get("server_version", "UNKNOWN") + }, + "run_id": step1_data.get("run_id"), + "started_at": step1_data.get("timestamp"), + "completed_at": now.isoformat() + } + + print("") + print("========================================") + print(" Windmill Heartbeat - 診断レポート") + print("========================================") + print(f" Status: {report['status']}") + print(f" 年度: {fiscal_year}年度") + print(f" Run ID: {report['run_id']}") + print(f" Server: {report['diagnostics']['server_version']}") + print(f" 開始: {report['started_at']}") + print(f" 完了: {report['completed_at']}") + print(" ────────────────────────────────────") + print(f" データ生成: PASS ✓") + print(f" データ検証: {report['diagnostics']['data_verification']} ✓") + print(f" HTTP確認: {report['diagnostics']['http_health']} ✓") + print("========================================") + print("") + + return report diff --git a/workflows/wmill-lock.yaml b/workflows/wmill-lock.yaml index f801d70..b06152d 100644 --- a/workflows/wmill-lock.yaml +++ b/workflows/wmill-lock.yaml @@ -1,5 +1,10 @@ version: v2 locks: + f/app_custom/system_heartbeat__flow+__flow_hash: 658d12c41ff4fed8cc458803c725da51f0ef477ea605ac1617a8cbc27a94f1fe + 'f/app_custom/system_heartbeat__flow+step1:_診断データ生成.py': 5dac5515801ac73afa433b242e8af9989ecdc18b9798522d627aa8d88bc07bc8 + 'f/app_custom/system_heartbeat__flow+step2:_データ検証.py': d7f4e6e04ed116ba3836cb32793a0187a69359a3f2a807b533030b01d42bed39 + 'f/app_custom/system_heartbeat__flow+step3:_httpヘルスチェック.py': 5d3bce0ddb4f521444bf01bc80670e7321933ad09f935044f4d6123c658ca7a8 + 'f/app_custom/system_heartbeat__flow+step4:_年度判定_&_最終レポート.py': 6889bfac9a629fa42cf0505cbc945ba3782c59e1697b8493ce6101ef5ffa8b32 g/all/setup_app__app+__app_hash: d71add32e14e552d1a4c861c972a50d9598b07c0af201bbadec5b59bbd99d7e3 g/all/setup_app__app+change_account.deno.ts: 3c592cac27e9cdab0de6ae19270bcb08c7fa54355ad05253a12de2351894346b u/admin/hub_sync: aaf9fd803fa229f3029d1bb02bbe3cc422fce680cad39c4eec8dd1da115de102