1
1
#!/usr/bin/python3
2
2
"""
3
- Creates Github Releases Notes with content hashes
3
+ Create Github Releases Notes with binary checksums from Workers KV
4
4
"""
5
5
6
6
import argparse
7
7
import logging
8
8
import os
9
- import hashlib
10
- import glob
9
+ import requests
11
10
12
- from github import Github , GithubException , UnknownObjectException
11
+ from github import Github , UnknownObjectException
13
12
14
13
FORMAT = "%(levelname)s - %(asctime)s: %(message)s"
15
- logging .basicConfig (format = FORMAT )
14
+ logging .basicConfig (format = FORMAT , level = logging . INFO )
16
15
17
16
CLOUDFLARED_REPO = os .environ .get ("GITHUB_REPO" , "cloudflare/cloudflared" )
18
17
GITHUB_CONFLICT_CODE = "already_exists"
19
-
20
- def get_sha256 (filename ):
21
- """ get the sha256 of a file """
22
- sha256_hash = hashlib .sha256 ()
23
- with open (filename ,"rb" ) as f :
24
- for byte_block in iter (lambda : f .read (4096 ),b"" ):
25
- sha256_hash .update (byte_block )
26
- return sha256_hash .hexdigest ()
18
+ BASE_KV_URL = 'https://api.cloudflare.com/client/v4/accounts/'
19
+
20
+
21
+ def kv_get_keys (prefix , account , namespace , api_token ):
22
+ """ get the KV keys for a given prefix """
23
+ response = requests .get (
24
+ BASE_KV_URL + account + "/storage/kv/namespaces/" +
25
+ namespace + "/keys" + "?prefix=" + prefix ,
26
+ headers = {
27
+ "Content-Type" : "application/json" ,
28
+ "Authorization" : "Bearer " + api_token ,
29
+ },
30
+ )
31
+ if response .status_code != 200 :
32
+ jsonResponse = response .json ()
33
+ errors = jsonResponse ["errors" ]
34
+ if len (errors ) > 0 :
35
+ raise Exception ("failed to get checksums: {0}" , errors [0 ])
36
+ return response .json ()["result" ]
37
+
38
+
39
+ def kv_get_value (key , account , namespace , api_token ):
40
+ """ get the KV value for a provided key """
41
+ response = requests .get (
42
+ BASE_KV_URL + account + "/storage/kv/namespaces/" + namespace + "/values/" + key ,
43
+ headers = {
44
+ "Content-Type" : "application/json" ,
45
+ "Authorization" : "Bearer " + api_token ,
46
+ },
47
+ )
48
+ if response .status_code != 200 :
49
+ jsonResponse = response .json ()
50
+ errors = jsonResponse ["errors" ]
51
+ if len (errors ) > 0 :
52
+ raise Exception ("failed to get checksums: {0}" , errors [0 ])
53
+ return response .text
27
54
28
55
29
56
def update_or_add_message (msg , name , sha ):
@@ -42,6 +69,7 @@ def update_or_add_message(msg, name, sha):
42
69
return '{0}{1}```' .format (msg [:back ], new_text )
43
70
return '{0} \n ### SHA256 Checksums:\n ```\n {1}```' .format (msg , new_text )
44
71
72
+
45
73
def get_release (repo , version ):
46
74
""" Get a Github Release matching the version tag. """
47
75
try :
@@ -55,11 +83,20 @@ def get_release(repo, version):
55
83
def parse_args ():
56
84
""" Parse and validate args """
57
85
parser = argparse .ArgumentParser (
58
- description = "Creates Github Releases and uploads assets. "
86
+ description = "Updates a Github Release with checksums from KV "
59
87
)
60
88
parser .add_argument (
61
89
"--api-key" , default = os .environ .get ("API_KEY" ), help = "Github API key"
62
90
)
91
+ parser .add_argument (
92
+ "--kv-namespace-id" , default = os .environ .get ("KV_NAMESPACE" ), help = "workers KV namespace id"
93
+ )
94
+ parser .add_argument (
95
+ "--kv-account-id" , default = os .environ .get ("KV_ACCOUNT" ), help = "workers KV account id"
96
+ )
97
+ parser .add_argument (
98
+ "--kv-api-token" , default = os .environ .get ("KV_API_TOKEN" ), help = "workers KV API Token"
99
+ )
63
100
parser .add_argument (
64
101
"--release-version" ,
65
102
metavar = "version" ,
@@ -80,6 +117,18 @@ def parse_args():
80
117
logging .error ("Missing API key" )
81
118
is_valid = False
82
119
120
+ if not args .kv_namespace_id :
121
+ logging .error ("Missing KV namespace id" )
122
+ is_valid = False
123
+
124
+ if not args .kv_account_id :
125
+ logging .error ("Missing KV account id" )
126
+ is_valid = False
127
+
128
+ if not args .kv_api_token :
129
+ logging .error ("Missing KV API token" )
130
+ is_valid = False
131
+
83
132
if is_valid :
84
133
return args
85
134
@@ -95,16 +144,20 @@ def main():
95
144
repo = client .get_repo (CLOUDFLARED_REPO )
96
145
release = get_release (repo , args .release_version )
97
146
98
- msg = release . body
147
+ msg = ""
99
148
100
- for filepath in glob .glob ("artifacts/*" ):
101
- pkg_hash = get_sha256 (filepath )
102
- # add the sha256 of the new artifact to the release message body
103
- name = os .path .basename (filepath )
104
- msg = update_or_add_message (msg , name , pkg_hash )
149
+ prefix = f"update_{ args .release_version } _"
150
+ keys = kv_get_keys (prefix , args .kv_account_id ,
151
+ args .kv_namespace_id , args .kv_api_token )
152
+ for key in [k ["name" ] for k in keys ]:
153
+ checksum = kv_get_value (
154
+ key , args .kv_account_id , args .kv_namespace_id , args .kv_api_token )
155
+ binary_name = key [len (prefix ):]
156
+ msg = update_or_add_message (msg , binary_name , checksum )
105
157
106
158
if args .dry_run :
107
- logging .info ("Skipping asset upload because of dry-run" )
159
+ logging .info ("Skipping release message update because of dry-run" )
160
+ logging .info (f"Github message:\n { msg } " )
108
161
return
109
162
110
163
# update the release body text
@@ -115,4 +168,4 @@ def main():
115
168
exit (1 )
116
169
117
170
118
- main ()
171
+ main ()
0 commit comments