11"""Wait for hash on server to match with deployed code"""
22import asyncio
3+ import json
4+ import logging
35import time
46
57from async_subprocess import check_output
68from client_wrapper import ClientWrapper
7- from release import init_working_dir
9+ from lib import init_working_dir # Import from lib.py
10+ from version import get_version_tag
811
12+ log = logging .getLogger (__name__ )
913
10- async def fetch_release_hash (hash_url ):
11- """Fetch the hash from the release"""
14+
15+ async def fetch_release_hash (hash_url , * , expected_version = None ):
16+ """
17+ Fetch the hash from the release URL.
18+
19+ Handles both plain text hash responses and JSON responses containing a 'hash' key.
20+ """
1221 client = ClientWrapper ()
1322 response = await client .get (hash_url )
1423 response .raise_for_status ()
15- release_hash = response .content .decode ().strip ()
24+ content = response .content .decode ().strip ()
25+ release_hash = None
26+
27+ try :
28+ data = json .loads (content )
29+ if isinstance (data , dict ):
30+ # If we expect a specific version, check it first
31+ if expected_version and "version" in data :
32+ deployed_version = str (data ["version" ]).strip ()
33+ if deployed_version != expected_version :
34+ raise Exception (
35+ f"Version mismatch at { hash_url } : Expected '{ expected_version } ', but found '{ deployed_version } '"
36+ )
37+ # If version matches (or wasn't checked), get the hash
38+ if "hash" in data :
39+ release_hash = str (data ["hash" ]).strip ()
40+ except json .JSONDecodeError :
41+ # Content is not JSON, treat it as a plain hash
42+ pass
43+
44+ if release_hash is None :
45+ # Fallback: Treat the entire content as the hash if JSON parsing failed
46+ # or the 'hash' key wasn't found.
47+ release_hash = content
48+
1649 if len (release_hash ) != 40 :
50+ # Validate the final hash string
1751 raise Exception (
18- f"Expected release hash from { hash_url } but got: { release_hash } "
52+ f"Expected a 40-character release hash from { hash_url } but got: ' { release_hash } ' "
1953 )
2054 return release_hash
2155
2256
2357async def wait_for_deploy (
24- * , github_access_token , repo_url , hash_url , watch_branch , timeout_seconds = 60 * 60
58+ * ,
59+ github_access_token ,
60+ repo_url ,
61+ hash_url ,
62+ watch_branch ,
63+ expected_version ,
64+ timeout_seconds = 60 * 60 ,
2565):
2666 """
2767 Wait until server is finished with the deploy
@@ -31,6 +71,7 @@ async def wait_for_deploy(
3171 repo_url (str): The repository URL which has the latest commit hash to check
3272 hash_url (str): The deployment URL which has the commit of the deployed app
3373 watch_branch (str): The branch in the repository which has the latest commit
74+ expected_version (str or None): The version string expected to be found at the hash_url, or None to skip version check.
3475 timeout_seconds (int): The number of seconds to wait before timing out the deploy
3576
3677 Returns:
@@ -44,9 +85,27 @@ async def wait_for_deploy(
4485 ["git" , "rev-parse" , f"origin/{ watch_branch } " ], cwd = working_dir
4586 )
4687 latest_hash = output .decode ().strip ()
47- while await fetch_release_hash (hash_url ) != latest_hash :
88+
89+ if expected_version :
90+ log .info (f"Expecting version '{ expected_version } ' for hash { latest_hash [:7 ]} " )
91+ else :
92+ log .info (f"No specific version expected for hash { latest_hash [:7 ]} . Proceeding without version check." )
93+
94+ while True :
95+ try :
96+ current_hash = await fetch_release_hash (hash_url , expected_version = expected_version )
97+ if current_hash == latest_hash :
98+ log .info (f"Hash { latest_hash [:7 ]} confirmed at { hash_url } " )
99+ break # Hashes match, deploy successful
100+ else :
101+ log .info (f"Waiting for hash { latest_hash [:7 ]} at { hash_url } , currently { current_hash [:7 ]} " )
102+ except Exception as e : # pylint: disable=broad-except
103+ log .error (f"Error checking deploy status at { hash_url } : { e } " )
104+ # Optionally, decide if specific errors should stop the wait
105+
48106 if (time .time () - start_time ) > timeout_seconds :
49- return False
107+ log .error (f"Timeout waiting for hash { latest_hash [:7 ]} at { hash_url } " )
108+ return False # Timeout reached
50109 await asyncio .sleep (30 )
51110
52111 return True
0 commit comments