11#!/usr/bin/python3
22"""
3- Creates Github Releases Notes with content hashes
3+ Create Github Releases Notes with binary checksums from Workers KV
44"""
55
66import argparse
77import logging
88import os
9- import hashlib
10- import glob
9+ import requests
1110
12- from github import Github , GithubException , UnknownObjectException
11+ from github import Github , UnknownObjectException
1312
1413FORMAT = "%(levelname)s - %(asctime)s: %(message)s"
15- logging .basicConfig (format = FORMAT )
14+ logging .basicConfig (format = FORMAT , level = logging . INFO )
1615
1716CLOUDFLARED_REPO = os .environ .get ("GITHUB_REPO" , "cloudflare/cloudflared" )
1817GITHUB_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
2754
2855
2956def update_or_add_message (msg , name , sha ):
@@ -42,6 +69,7 @@ def update_or_add_message(msg, name, sha):
4269 return '{0}{1}```' .format (msg [:back ], new_text )
4370 return '{0} \n ### SHA256 Checksums:\n ```\n {1}```' .format (msg , new_text )
4471
72+
4573def get_release (repo , version ):
4674 """ Get a Github Release matching the version tag. """
4775 try :
@@ -55,11 +83,20 @@ def get_release(repo, version):
5583def parse_args ():
5684 """ Parse and validate args """
5785 parser = argparse .ArgumentParser (
58- description = "Creates Github Releases and uploads assets. "
86+ description = "Updates a Github Release with checksums from KV "
5987 )
6088 parser .add_argument (
6189 "--api-key" , default = os .environ .get ("API_KEY" ), help = "Github API key"
6290 )
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+ )
63100 parser .add_argument (
64101 "--release-version" ,
65102 metavar = "version" ,
@@ -80,6 +117,18 @@ def parse_args():
80117 logging .error ("Missing API key" )
81118 is_valid = False
82119
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+
83132 if is_valid :
84133 return args
85134
@@ -95,16 +144,20 @@ def main():
95144 repo = client .get_repo (CLOUDFLARED_REPO )
96145 release = get_release (repo , args .release_version )
97146
98- msg = release . body
147+ msg = ""
99148
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 )
105157
106158 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 } " )
108161 return
109162
110163 # update the release body text
@@ -115,4 +168,4 @@ def main():
115168 exit (1 )
116169
117170
118- main ()
171+ main ()
0 commit comments