hf-actions commited on
Commit
475fc0c
·
1 Parent(s): b3ab169

chore: add set_github_secrets.py helper and PyNaCl requirement

Browse files
Files changed (2) hide show
  1. requirements.txt +2 -1
  2. set_github_secrets.py +119 -0
requirements.txt CHANGED
@@ -3,4 +3,5 @@ requests>=2.0.0
3
  openai>=0.27.0
4
  gradio
5
  replicate>=0.10.0
6
- huggingface-hub>=0.18.0
 
 
3
  openai>=0.27.0
4
  gradio
5
  replicate>=0.10.0
6
+ huggingface-hub>=0.18.0
7
+ pynacl>=1.5.0
set_github_secrets.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """set_github_secrets.py
2
+
3
+ Reads values from .env and publishes them as GitHub Actions secrets for a given repo.
4
+
5
+ Usage:
6
+ python set_github_secrets.py --owner <owner> --repo <repo> --keys KEY1 KEY2 ...
7
+
8
+ Requires a GitHub token in the environment as `GITHUB_TOKEN` or `GH_TOKEN` with `repo` scope.
9
+ """
10
+ import os
11
+ import sys
12
+ import json
13
+ import argparse
14
+ from pathlib import Path
15
+
16
+ try:
17
+ from dotenv import load_dotenv
18
+ load_dotenv()
19
+ except Exception:
20
+ pass
21
+
22
+ import requests
23
+ import base64
24
+ try:
25
+ from nacl import public, encoding
26
+ except Exception:
27
+ public = None
28
+
29
+
30
+ def load_token():
31
+ for k in ("GITHUB_TOKEN", "GH_TOKEN"):
32
+ v = os.getenv(k)
33
+ if v:
34
+ return v
35
+ return None
36
+
37
+
38
+ def get_public_key(token: str, owner: str, repo: str):
39
+ url = f"https://api.github.com/repos/{owner}/{repo}/actions/secrets/public-key"
40
+ headers = {"Authorization": f"token {token}", "Accept": "application/vnd.github+json"}
41
+ r = requests.get(url, headers=headers, timeout=15)
42
+ if r.status_code != 200:
43
+ raise RuntimeError(f"Failed to fetch public key: {r.status_code} {r.text}")
44
+ return r.json()
45
+
46
+
47
+ def encrypt_secret(public_key: str, value: str) -> str:
48
+ if public is None:
49
+ raise RuntimeError("PyNaCl is required to encrypt secrets. Install with 'pip install pynacl'.")
50
+ pk = base64.b64decode(public_key)
51
+ pk_obj = public.PublicKey(pk)
52
+ sealed_box = public.SealedBox(pk_obj)
53
+ encrypted = sealed_box.encrypt(value.encode('utf-8'))
54
+ return base64.b64encode(encrypted).decode('utf-8')
55
+
56
+
57
+ def put_secret(token: str, owner: str, repo: str, name: str, encrypted_value: str, key_id: str):
58
+ url = f"https://api.github.com/repos/{owner}/{repo}/actions/secrets/{name}"
59
+ headers = {"Authorization": f"token {token}", "Accept": "application/vnd.github+json"}
60
+ payload = {"encrypted_value": encrypted_value, "key_id": key_id}
61
+ r = requests.put(url, headers=headers, data=json.dumps(payload), timeout=15)
62
+ if r.status_code not in (201, 204):
63
+ raise RuntimeError(f"Failed setting secret {name}: {r.status_code} {r.text}")
64
+ return True
65
+
66
+
67
+ DEFAULT_KEYS = [
68
+ 'FB_PAGE_ACCESS_TOKEN',
69
+ 'FB_PAGE_ID',
70
+ 'OPENAI_API_KEY',
71
+ 'REPLICATE_API_TOKEN',
72
+ 'DAILY_PROMPT',
73
+ 'RUN_DAILY_REPLICATE',
74
+ 'SHOW_POST_LOG',
75
+ ]
76
+
77
+
78
+ def main():
79
+ parser = argparse.ArgumentParser()
80
+ parser.add_argument('--owner', required=True)
81
+ parser.add_argument('--repo', required=True)
82
+ parser.add_argument('--keys', nargs='*')
83
+ args = parser.parse_args()
84
+
85
+ token = load_token()
86
+ if not token:
87
+ print('No GitHub token found in env (GITHUB_TOKEN/GH_TOKEN). Aborting.')
88
+ sys.exit(2)
89
+
90
+ keys = args.keys or DEFAULT_KEYS
91
+ to_publish = {}
92
+ for k in keys:
93
+ v = os.getenv(k)
94
+ if v is not None and v != '':
95
+ to_publish[k] = v
96
+
97
+ if not to_publish:
98
+ print('No configured keys found in environment to publish. Exiting.')
99
+ return
100
+
101
+ print(f'Publishing {len(to_publish)} secrets to {args.owner}/{args.repo}...')
102
+ pk_info = get_public_key(token, args.owner, args.repo)
103
+ key_id = pk_info.get('key_id')
104
+ public_key = pk_info.get('key')
105
+ if not key_id or not public_key:
106
+ print('Failed to retrieve public key info from GitHub API.')
107
+ sys.exit(3)
108
+
109
+ for k, v in to_publish.items():
110
+ try:
111
+ enc = encrypt_secret(public_key, v)
112
+ put_secret(token, args.owner, args.repo, k, enc, key_id)
113
+ print('OK', k)
114
+ except Exception as e:
115
+ print('ERROR', k, str(e))
116
+
117
+
118
+ if __name__ == '__main__':
119
+ main()