#!/usr/bin/env python3 """ Sync selected keys from a local .env file to Hugging Face Space secrets. Usage: python scripts/sync_hf_secrets.py --space-id Optional: python scripts/sync_hf_secrets.py --space-id --env-file .env python scripts/sync_hf_secrets.py --space-id --token python scripts/sync_hf_secrets.py --space-id --dry-run """ from __future__ import annotations import argparse import os import sys from pathlib import Path from dotenv import dotenv_values ALLOWED_KEYS = [ "AZURE_SEARCH_ENDPOINT", "AZURE_SEARCH_KEY", "AZURE_SEARCH_INDEX_NAME", "AZURE_OPENAI_ENDPOINT", "AZURE_OPENAI_KEY", "AZURE_OPENAI_DEPLOYMENT", "AZURE_OPENAI_API_VERSION", "AZURE_VISION_ENDPOINT", "AZURE_VISION_KEY", "AZURE_VISION_MODEL_VERSION", "EDITING_API_URL", "FIVEK_SUBSET_SIZE", ] def _parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description="Sync selected .env keys to Hugging Face Space secrets." ) parser.add_argument( "--space-id", required=True, help="Hugging Face Space id, e.g. username/my-space", ) parser.add_argument( "--env-file", default=".env", help="Path to .env file (default: .env)", ) parser.add_argument( "--token", default=os.getenv("HF_TOKEN"), help="Hugging Face token (defaults to HF_TOKEN env var)", ) parser.add_argument( "--dry-run", action="store_true", help="Print what would be synced without updating the Space", ) return parser.parse_args() def _load_pairs(env_file: Path) -> dict[str, str]: if not env_file.exists(): raise FileNotFoundError(f".env file not found: {env_file}") raw = dotenv_values(env_file) pairs: dict[str, str] = {} for key in ALLOWED_KEYS: value = raw.get(key) if value is None: continue value = str(value).strip() if not value: continue pairs[key] = value return pairs def main() -> int: args = _parse_args() env_file = Path(args.env_file).resolve() try: pairs = _load_pairs(env_file) except Exception as exc: # pragma: no cover print(f"ERROR: {exc}") return 1 if not pairs: print("No allowed keys with non-empty values found in .env.") return 1 if args.dry_run: print(f"[dry-run] Would sync {len(pairs)} secret(s) to {args.space_id}:") for k in sorted(pairs): print(f" - {k}") return 0 if not args.token: print("ERROR: Missing token. Set HF_TOKEN or pass --token.") return 1 try: from huggingface_hub import HfApi except Exception: print("ERROR: huggingface_hub is not installed.") print("Install it with: pip install huggingface_hub") return 1 api = HfApi(token=args.token) print(f"Syncing {len(pairs)} secret(s) to {args.space_id}...") for key, value in pairs.items(): api.add_space_secret(repo_id=args.space_id, key=key, value=value) print(f" - synced {key}") print("Done. Your Space will restart to apply updated secrets.") return 0 if __name__ == "__main__": raise SystemExit(main())