File size: 3,373 Bytes
5d36f24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/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 <username/space-name>

Optional:
  python scripts/sync_hf_secrets.py --space-id <username/space-name> --env-file .env
  python scripts/sync_hf_secrets.py --space-id <username/space-name> --token <hf_token>
  python scripts/sync_hf_secrets.py --space-id <username/space-name> --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())