1+ #!/usr/bin/python3
2+ """
3+ Creates Github Releases Notes with content hashes
4+ """
5+
6+ import argparse
7+ import logging
8+ import os
9+ import hashlib
10+ import glob
11+
12+ from github import Github , GithubException , UnknownObjectException
13+
14+ FORMAT = "%(levelname)s - %(asctime)s: %(message)s"
15+ logging .basicConfig (format = FORMAT )
16+
17+ CLOUDFLARED_REPO = os .environ .get ("GITHUB_REPO" , "cloudflare/cloudflared" )
18+ 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 ()
27+
28+
29+ def update_or_add_message (msg , name , sha ):
30+ """
31+ updates or builds the github version message for each new asset's sha256.
32+ Searches the existing message string to update or create.
33+ """
34+ new_text = '{0}: {1}\n ' .format (name , sha )
35+ start = msg .find (name )
36+ if (start != - 1 ):
37+ end = msg .find ("\n " , start )
38+ if (end != - 1 ):
39+ return msg .replace (msg [start :end + 1 ], new_text )
40+ back = msg .rfind ("```" )
41+ if (back != - 1 ):
42+ return '{0}{1}```' .format (msg [:back ], new_text )
43+ return '{0} \n ### SHA256 Checksums:\n ```\n {1}```' .format (msg , new_text )
44+
45+ def get_release (repo , version ):
46+ """ Get a Github Release matching the version tag. """
47+ try :
48+ release = repo .get_release (version )
49+ logging .info ("Release %s found" , version )
50+ return release
51+ except UnknownObjectException :
52+ logging .info ("Release %s not found" , version )
53+
54+
55+ def parse_args ():
56+ """ Parse and validate args """
57+ parser = argparse .ArgumentParser (
58+ description = "Creates Github Releases and uploads assets."
59+ )
60+ parser .add_argument (
61+ "--api-key" , default = os .environ .get ("API_KEY" ), help = "Github API key"
62+ )
63+ parser .add_argument (
64+ "--release-version" ,
65+ metavar = "version" ,
66+ default = os .environ .get ("VERSION" ),
67+ help = "Release version" ,
68+ )
69+ parser .add_argument (
70+ "--dry-run" , action = "store_true" , help = "Do not modify the release message"
71+ )
72+
73+ args = parser .parse_args ()
74+ is_valid = True
75+ if not args .release_version :
76+ logging .error ("Missing release version" )
77+ is_valid = False
78+
79+ if not args .api_key :
80+ logging .error ("Missing API key" )
81+ is_valid = False
82+
83+ if is_valid :
84+ return args
85+
86+ parser .print_usage ()
87+ exit (1 )
88+
89+
90+ def main ():
91+ """ Attempts to update the Github Release message with the github asset's checksums """
92+ try :
93+ args = parse_args ()
94+ client = Github (args .api_key )
95+ repo = client .get_repo (CLOUDFLARED_REPO )
96+ release = get_release (repo , args .release_version )
97+
98+ msg = release .body
99+
100+ for filename in glob .glob (".artifacts/*.*" ):
101+ pkg_hash = get_sha256 (filename )
102+ # add the sha256 of the new artifact to the release message body
103+ msg = update_or_add_message (msg , filename , pkg_hash )
104+
105+ if args .dry_run :
106+ logging .info ("Skipping asset upload because of dry-run" )
107+ return
108+
109+ # update the release body text
110+ release .update_release (version , version , msg )
111+
112+ except Exception as e :
113+ logging .exception (e )
114+ exit (1 )
115+
116+
117+ main ()
0 commit comments