fix(n8n-webhook): auto-load local gog automation env

This commit is contained in:
zap
2026-03-12 19:16:24 +00:00
parent afa48a3aa6
commit 044e36f385
4 changed files with 39 additions and 3 deletions

View File

@@ -129,7 +129,8 @@ python3 scripts/resolve-approval-with-gog.py --id <approval-id> --decision appro
```
Practical note:
- unattended execution needs `GOG_KEYRING_PASSWORD` in the environment because `gog`'s file keyring cannot prompt in non-TTY automation
- unattended execution needs `GOG_KEYRING_PASSWORD` available to the executor because `gog`'s file keyring cannot prompt in non-TTY automation
- the included bridge auto-loads `/home/openclaw/.openclaw/credentials/gog.env` when present, so you can keep `GOG_ACCOUNT` and `GOG_KEYRING_PASSWORD` there with mode `600`
- for safe plumbing tests without touching Google state, add `--dry-run`
### Add a new webhook-backed capability

View File

@@ -260,8 +260,10 @@ Behavior:
- writes execution metadata back via `approval_history_attach_execution`
Important automation note:
- real unattended execution needs `GOG_KEYRING_PASSWORD` in the environment
- without it, non-TTY `gog` calls will fail when the file keyring tries to prompt
- real unattended execution needs `GOG_KEYRING_PASSWORD` available to the executor
- the included bridge auto-loads `/home/openclaw/.openclaw/credentials/gog.env` when present
- keep that file mode `600` if you use it for `GOG_ACCOUNT` / `GOG_KEYRING_PASSWORD`
- without the password, non-TTY `gog` calls will fail when the file keyring tries to prompt
- `--dry-run` works without touching Google state and is useful for plumbing verification
## Validation

View File

@@ -12,6 +12,7 @@ from pathlib import Path
DEFAULT_BASE_URL = os.environ.get('N8N_BASE_URL', 'http://192.168.153.113:18808').rstrip('/')
DEFAULT_ACTION_PATH = os.environ.get('N8N_ACTION_PATH', 'openclaw-action').strip('/')
DEFAULT_SECRET_HEADER = os.environ.get('N8N_SECRET_HEADER', 'x-openclaw-secret')
DEFAULT_GOG_ENV_FILE = Path(os.environ.get('GOG_ENV_FILE', '/home/openclaw/.openclaw/credentials/gog.env'))
def fail(msg: str, code: int = 1):
@@ -24,6 +25,30 @@ def run(cmd, *, env=None):
return proc.returncode, proc.stdout, proc.stderr
def load_env_file(path: Path) -> dict:
if not path.exists():
return {}
try:
st = path.stat()
if (st.st_mode & 0o077) != 0:
fail(f'insecure permissions on {path}; expected mode 600-ish')
except FileNotFoundError:
return {}
loaded = {}
for raw_line in path.read_text(encoding='utf-8').splitlines():
line = raw_line.strip()
if not line or line.startswith('#') or '=' not in line:
continue
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in {'"', "'"}:
value = value[1:-1]
loaded[key] = value
return loaded
def gog_account(args_account: str | None) -> str:
account = args_account or os.environ.get('GOG_ACCOUNT', '').strip()
if not account:
@@ -155,6 +180,9 @@ def main():
ap.add_argument('--secret-header', default=DEFAULT_SECRET_HEADER)
args = ap.parse_args()
file_env = load_env_file(DEFAULT_GOG_ENV_FILE)
os.environ.update({k: v for k, v in file_env.items() if k not in os.environ or not os.environ.get(k)})
secret = webhook_secret()
resolved = call_action(
{