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