fix(ci): fail Windows signing on error and retry transient HTTP failures

res/job.py sign_files exited 0 when a file was left unsigned: a sign
task that never reached "done" only broke out of the current directory,
and a failed download of the signed file was ignored, keeping the
unsigned original in place. Both now exit non-zero, so the Windows
signing steps fail the job.

Retry requests.get/post on connection-level errors with the same wrapper
the signing service's client uses, rewinding upload streams before each
retry. Tunable via HTTP_RETRY_MAX_TRIES and HTTP_RETRY_SLEEP_SECS.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rustdeskandClaude Opus 5.5 committed 2026-10-31 23:13:40 +08:00
1 parent 3b7e2cebd9
commit 94c321d05c
1 file changed
+45 -2
+45 -2
View File
@@ -6,8 +6,48 @@ import time
import argparse
import logging
import shutil
import sys
import zipfile
def _file_stream_positions(files):
if not files:
return []
values = files.values() if hasattr(files, "values") else (item[1] for item in files)
positions = []
for value in values:
stream = value[1] if isinstance(value, tuple) and len(value) > 1 else value
if hasattr(stream, "tell") and hasattr(stream, "seek"):
try:
positions.append((stream, stream.tell()))
except (OSError, ValueError):
pass
return positions
def _with_simple_retries(fn, max_attempts=8, sleep_secs=1.0):
def _wrapper(*args, **kwargs):
file_positions = _file_stream_positions(kwargs.get("files"))
for i in range(max_attempts):
try:
if i:
for stream, position in file_positions:
stream.seek(position)
return fn(*args, **kwargs)
except Exception as e:
logging.warning(f"{fn.__name__} attempt {i+1}/{max_attempts} failed: {e}")
if i == max_attempts - 1:
raise
time.sleep(sleep_secs)
return _wrapper
HTTP_RETRY_MAX_TRIES = int(os.getenv("HTTP_RETRY_MAX_TRIES") or "8")
HTTP_RETRY_SLEEP_SECS = float(os.getenv("HTTP_RETRY_SLEEP_SECS") or "1")
requests.get = _with_simple_retries(requests.get, max_attempts=HTTP_RETRY_MAX_TRIES, sleep_secs=HTTP_RETRY_SLEEP_SECS)
requests.post = _with_simple_retries(requests.post, max_attempts=HTTP_RETRY_MAX_TRIES, sleep_secs=HTTP_RETRY_SLEEP_SECS)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s [%(filename)s:%(lineno)d]",
@@ -164,10 +204,13 @@ def sign_one_file(file_path):
n += 1
status = get_status(task_id)
if status and status.get("state") == "done":
download_one_file(
downloaded = download_one_file(
task_id, os.path.basename(file_path), os.path.dirname(file_path)
)
delete_task(task_id)
if not downloaded:
logging.error(f"Failed to download signed {file_path}")
return False
logging.info(f"Signed {file_path}")
return True
return False
@@ -217,7 +260,7 @@ def sign_files(dir_path, only_ext=None):
if ext in SIGN_EXTENSIONS:
if not sign_one_file(file_path):
logging.error(f"Failed to sign {file_path}")
break
sys.exit(1)
def main():