From cb670f605d12ba5cc6346750af9cda362a131a10 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 2 Jan 2026 10:43:45 -0800 Subject: [PATCH 01/15] Add Python CICD fixes and rollback handling to server.py Add a CI/CD check function to server.py --- server.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/server.py b/server.py index b0366d4..e91835f 100644 --- a/server.py +++ b/server.py @@ -1,3 +1,4 @@ +import sys import argparse import dataclasses import json @@ -42,7 +43,14 @@ logger = logging.getLogger(__name__) - +def cicd_check(): + error_condition = False # Set to True to simulate failure + if error_condition: + print("Error detected! Exiting with 1.") + sys.exit(1) + else: + print("All checks passed.") + sys.exit(0) @dataclasses.dataclass class RepoToWatch: From 606c5778c2b07cae33aec24c19e59d00bdca904e Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 2 Jan 2026 11:58:26 -0800 Subject: [PATCH 02/15] Added git rollback if docker-compose fails with python Add git rollback if docker-compose fails with python in server.py --- server.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index e91835f..4ba880d 100644 --- a/server.py +++ b/server.py @@ -173,10 +173,21 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: text=True, ) logger.info(f"Docker compose stdout: {docker_result.stdout}") - logger.info(f"Docker compose stdout: {docker_result.stderr}") + logger.info(f"Docker compose stderr: {docker_result.stderr}") result.docker_stdout = docker_result.stdout result.docker_stderr = docker_result.stderr - result.git_exit_code = git_result.returncode + result.docker_exit_code = docker_result.returncode + + # Rollback if docker-compose fails + if docker_result.returncode != 0: + rollback_result = subprocess.run( + ["git", "reset", "--hard", "HEAD@{1}"], + cwd=repo_config.path, + capture_output=True, + text=True, + ) + logger.warning(f"Rollback performed due to docker-compose failure. Rollback stdout: {rollback_result.stdout}, stderr: {rollback_result.stderr}") + push_update_success_as_discord_embed(repo_config, result) except Exception: logger.exception("update_repo had a bad time") From 78288bb70ec2ff17d422d9e4a11801025fd34531 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 2 Jan 2026 20:28:13 -0800 Subject: [PATCH 03/15] Added a rollback command for terminal Updated rollback handling to log messages without executing git reset in development in the terminal --- server.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server.py b/server.py index 4ba880d..2228e89 100644 --- a/server.py +++ b/server.py @@ -57,6 +57,7 @@ class RepoToWatch: name: str branch: str path: str + force_recreate: bool = False @dataclasses.dataclass @@ -68,6 +69,7 @@ class RepoUpdateResult: git_stderr: str = "" docker_stdout: str = "" docker_stderr: str = "" + development: bool = False def load_config(development: bool): @@ -178,16 +180,17 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: result.docker_stderr = docker_result.stderr result.docker_exit_code = docker_result.returncode - # Rollback if docker-compose fails + # rollback command for terminal if docker_result.returncode != 0: - rollback_result = subprocess.run( - ["git", "reset", "--hard", "HEAD@{1}"], - cwd=repo_config.path, - capture_output=True, - text=True, - ) - logger.warning(f"Rollback performed due to docker-compose failure. Rollback stdout: {rollback_result.stdout}, stderr: {rollback_result.stderr}") - + logger.warning("\nROLLBACK INITIATED\n") + logger.warning(f"docker-compose failed (exit code {docker_result.returncode}), git pull exit code {git_result.returncode}. Rollback would be performed here (mocked in dev).") + # Mock rollback: do not actually reset the repo in local/dev + logger.warning("Rollback skipped for local development. No destructive git reset performed.") + logger.warning("\nROLLBACK COMPLETE\n") + result.git_exit_code = 1 + result.docker_exit_code = 1 + push_update_success_as_discord_embed(repo_config, result) + return result push_update_success_as_discord_embed(repo_config, result) except Exception: logger.exception("update_repo had a bad time") From 214d76391000e2afc31d7e05294f1061b5c6fb18 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 2 Jan 2026 20:36:25 -0800 Subject: [PATCH 04/15] removed "mock rollback" comment --- server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server.py b/server.py index 2228e89..71f8a32 100644 --- a/server.py +++ b/server.py @@ -184,7 +184,6 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: if docker_result.returncode != 0: logger.warning("\nROLLBACK INITIATED\n") logger.warning(f"docker-compose failed (exit code {docker_result.returncode}), git pull exit code {git_result.returncode}. Rollback would be performed here (mocked in dev).") - # Mock rollback: do not actually reset the repo in local/dev logger.warning("Rollback skipped for local development. No destructive git reset performed.") logger.warning("\nROLLBACK COMPLETE\n") result.git_exit_code = 1 From 9589fc9438e6051da2bed1d2974b4ddfd38db8f4 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 3 Jan 2026 09:23:58 -0800 Subject: [PATCH 05/15] Removed rollback warning message in server.py Removed mock rollback message for local development. --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index 71f8a32..38e917e 100644 --- a/server.py +++ b/server.py @@ -183,7 +183,7 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: # rollback command for terminal if docker_result.returncode != 0: logger.warning("\nROLLBACK INITIATED\n") - logger.warning(f"docker-compose failed (exit code {docker_result.returncode}), git pull exit code {git_result.returncode}. Rollback would be performed here (mocked in dev).") + logger.warning(f"docker-compose failed (exit code {docker_result.returncode}), git pull exit code {git_result.returncode}.") logger.warning("Rollback skipped for local development. No destructive git reset performed.") logger.warning("\nROLLBACK COMPLETE\n") result.git_exit_code = 1 From f03565628d465892e8dbd6b0966deabf32d19401 Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 3 Jan 2026 21:15:17 -0800 Subject: [PATCH 06/15] added "rollback feature if docker step fails Added rollback functionality with backup branch creation and deletion. --- server.py | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 38e917e..8c78740 100644 --- a/server.py +++ b/server.py @@ -6,6 +6,7 @@ import os import subprocess import threading +import datetime from dotenv import load_dotenv import uvicorn @@ -58,6 +59,7 @@ class RepoToWatch: branch: str path: str force_recreate: bool = False + enable_rollback: bool = False @dataclasses.dataclass @@ -79,6 +81,8 @@ def load_config(development: bool): with open("config.yml") as f: loaded_yaml = yaml.safe_load(f) for config in loaded_yaml.get("repos", []): + if 'enable_rollback' not in config: + config['enable_rollback'] = False parsed = RepoToWatch(**config) result[(parsed.name, parsed.branch)] = parsed @@ -149,7 +153,24 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: f"updating {repo_config.name} to {repo_config.branch} in {repo_config.path}" ) - result = RepoUpdateResult() + result = RepoUpdateResult(commit=commit_obj, author=author_obj) + backup_branch_name = None + # Backup branch logic + if getattr(repo_config, 'enable_rollback', False): + from datetime import datetime + backup_branch_name = datetime.now().strftime('%Y%m%d-%H%M%S') + f'-{repo_config.branch}' + try: + # double check if on the main branch + subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) + # create backup branch + subprocess.run(["git", "checkout", "-b", backup_branch_name], cwd=repo_config.path, check=True) + # switch back to main + subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) + logger.info(f"Created backup branch {backup_branch_name} for rollback protection.") + except Exception as e: + logger.error(f"Failed to create backup branch {backup_branch_name}: {e}") + result.rollback_message = f"Failed to create backup branch: {e}" + result.backup_branch_name = backup_branch_name if args.development: logging.warning("skipping command to update, we are in development mode") @@ -179,17 +200,56 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: result.docker_stdout = docker_result.stdout result.docker_stderr = docker_result.stderr result.docker_exit_code = docker_result.returncode - # rollback command for terminal if docker_result.returncode != 0: logger.warning("\nROLLBACK INITIATED\n") logger.warning(f"docker-compose failed (exit code {docker_result.returncode}), git pull exit code {git_result.returncode}.") - logger.warning("Rollback skipped for local development. No destructive git reset performed.") + rollback_success = False + rollback_error = None + if getattr(repo_config, 'enable_rollback', False) and hasattr(result, 'backup_branch_name') and result.backup_branch_name: + try: + #reset main to backup branch + subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) + subprocess.run(["git", "reset", "--hard", result.backup_branch_name], cwd=repo_config.path, check=True) + #delete backup branch + subprocess.run(["git", "branch", "-D", result.backup_branch_name], cwd=repo_config.path, check=True) + logger.info(f"Rolled back {repo_config.branch} to {result.backup_branch_name} and deleted backup branch.") + rollback_success = True + except Exception as e: + logger.error(f"Rollback failed: {e}") + rollback_error = str(e) + else: + logger.warning("Rollback skipped: no backup branch available.") logger.warning("\nROLLBACK COMPLETE\n") result.git_exit_code = 1 result.docker_exit_code = 1 + if rollback_success: + result.rollback_message = f"Deployment failed, rollback performed using backup branch {getattr(result, 'backup_branch_name', '')}." + # Retry docker-compose up after rollback + try: + retry_result = subprocess.run( + ["docker-compose", "up", "--build", "-d"], + cwd=repo_config.path, + capture_output=True, + text=True, + ) + logger.info(f"Docker compose retry stdout: {retry_result.stdout}") + logger.info(f"Docker compose retry stderr: {retry_result.stderr}") + result.docker_stdout += f"\n[rollback retry]\n{retry_result.stdout}" + result.docker_stderr += f"\n[rollback retry]\n{retry_result.stderr}" + result.docker_exit_code = retry_result.returncode + except Exception as e: + logger.error(f"Retry after rollback failed: {e}") + else: + result.rollback_message = f"Deployment failed, rollback logic triggered but failed: {rollback_error or 'No backup branch.'}" push_update_success_as_discord_embed(repo_config, result) return result + if getattr(repo_config, 'enable_rollback', False) and hasattr(result, 'backup_branch_name') and result.backup_branch_name: + try: + subprocess.run(["git", "branch", "-D", result.backup_branch_name], cwd=repo_config.path, check=True) + logger.info(f"Deleted backup branch {result.backup_branch_name} after successful deployment.") + except Exception as e: + logger.error(f"Failed to delete backup branch {result.backup_branch_name}: {e}") push_update_success_as_discord_embed(repo_config, result) except Exception: logger.exception("update_repo had a bad time") From 2f46df1b31e9c8e3892b11b103ad29e97ae72c4d Mon Sep 17 00:00:00 2001 From: Brian Date: Sat, 3 Jan 2026 21:48:59 -0800 Subject: [PATCH 07/15] Remove unused datetime import Removed unused import for datetime module. --- server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/server.py b/server.py index 8c78740..d96d0eb 100644 --- a/server.py +++ b/server.py @@ -6,7 +6,6 @@ import os import subprocess import threading -import datetime from dotenv import load_dotenv import uvicorn From d7a267d60b993bee5ccb7261e993b362980a8650 Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 4 Jan 2026 21:17:14 +0000 Subject: [PATCH 08/15] Implement rollback functionality with backup branch Added import datetime to the top, removed force_recreate and enable_rollback, made own functions for create_copy_of_cicd_branch and do rollback --- server.py | 126 +++++++++++++++++++++++++----------------------------- 1 file changed, 59 insertions(+), 67 deletions(-) diff --git a/server.py b/server.py index d96d0eb..524c3dc 100644 --- a/server.py +++ b/server.py @@ -6,6 +6,7 @@ import os import subprocess import threading +import datetime from dotenv import load_dotenv import uvicorn @@ -57,7 +58,6 @@ class RepoToWatch: name: str branch: str path: str - force_recreate: bool = False enable_rollback: bool = False @@ -80,8 +80,6 @@ def load_config(development: bool): with open("config.yml") as f: loaded_yaml = yaml.safe_load(f) for config in loaded_yaml.get("repos", []): - if 'enable_rollback' not in config: - config['enable_rollback'] = False parsed = RepoToWatch(**config) result[(parsed.name, parsed.branch)] = parsed @@ -145,31 +143,66 @@ def push_update_success_as_discord_embed( except Exception: logger.exception("push_update_success_as_discord_embed had a bad time") - +def create_copy_of_cicd_branch(repo_config): + copy_branch_name = datetime.datetime.now().strftime('%Y%m%d-%H%M%S') + f'-{repo_config.branch}' + try: + subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) + subprocess.run(["git", "checkout", "-b", copy_branch_name], cwd=repo_config.path, check=True) + subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) + logger.info(f"Created backup branch {copy_branch_name} for rollback protection.") + return copy_branch_name + except Exception as e: + logger.error(f"Failed to create backup branch {copy_branch_name}: {e}") + return None +def do_rollback(repo_config, copy_branch_name, result): + rollback_success = False + rollback_error = None + try: + # Reset main to backup branch + subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) + subprocess.run(["git", "reset", "--hard", copy_branch_name], cwd=repo_config.path, check=True) + # Delete backup branch + subprocess.run(["git", "branch", "-D", copy_branch_name], cwd=repo_config.path, check=True) + logger.info(f"Rolled back {repo_config.branch} to {copy_branch_name} and deleted backup branch.") + rollback_success = True + except Exception as e: + logger.error(f"Rollback failed: {e}") + rollback_error = str(e) + result.git_exit_code = 1 + result.docker_exit_code = 1 + if rollback_success: + result.rollback_message = f"Deployment failed, rollback performed using backup branch {copy_branch_name}." + # Retry docker-compose up after rollback + try: + retry_result = subprocess.run( + ["docker-compose", "up", "--build", "-d"], + cwd=repo_config.path, + capture_output=True, + text=True, + ) + logger.info(f"Docker compose retry stdout: {retry_result.stdout}") + logger.info(f"Docker compose retry stderr: {retry_result.stderr}") + result.docker_stdout += f"\n[rollback retry]\n{retry_result.stdout}" + result.docker_stderr += f"\n[rollback retry]\n{retry_result.stderr}" + result.docker_exit_code = retry_result.returncode + except Exception as e: + logger.error(f"Retry after rollback failed: {e}") + else: + result.rollback_message = f"Deployment failed, rollback logic triggered but failed: {rollback_error or 'No backup branch.'}" + push_update_success_as_discord_embed(repo_config, result) + return result + def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: MetricsHandler.last_push_timestamp.labels(repo=repo_config.name).set(time.time()) logger.info( f"updating {repo_config.name} to {repo_config.branch} in {repo_config.path}" ) - result = RepoUpdateResult(commit=commit_obj, author=author_obj) - backup_branch_name = None + copy_branch_name = None # Backup branch logic if getattr(repo_config, 'enable_rollback', False): - from datetime import datetime - backup_branch_name = datetime.now().strftime('%Y%m%d-%H%M%S') + f'-{repo_config.branch}' - try: - # double check if on the main branch - subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) - # create backup branch - subprocess.run(["git", "checkout", "-b", backup_branch_name], cwd=repo_config.path, check=True) - # switch back to main - subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) - logger.info(f"Created backup branch {backup_branch_name} for rollback protection.") - except Exception as e: - logger.error(f"Failed to create backup branch {backup_branch_name}: {e}") - result.rollback_message = f"Failed to create backup branch: {e}" - result.backup_branch_name = backup_branch_name + copy_branch_name = create_copy_of_cicd_branch(repo_config) + result.copy_branch_name = copy_branch_name if args.development: logging.warning("skipping command to update, we are in development mode") @@ -200,55 +233,14 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: result.docker_stderr = docker_result.stderr result.docker_exit_code = docker_result.returncode # rollback command for terminal - if docker_result.returncode != 0: - logger.warning("\nROLLBACK INITIATED\n") - logger.warning(f"docker-compose failed (exit code {docker_result.returncode}), git pull exit code {git_result.returncode}.") - rollback_success = False - rollback_error = None - if getattr(repo_config, 'enable_rollback', False) and hasattr(result, 'backup_branch_name') and result.backup_branch_name: - try: - #reset main to backup branch - subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) - subprocess.run(["git", "reset", "--hard", result.backup_branch_name], cwd=repo_config.path, check=True) - #delete backup branch - subprocess.run(["git", "branch", "-D", result.backup_branch_name], cwd=repo_config.path, check=True) - logger.info(f"Rolled back {repo_config.branch} to {result.backup_branch_name} and deleted backup branch.") - rollback_success = True - except Exception as e: - logger.error(f"Rollback failed: {e}") - rollback_error = str(e) - else: - logger.warning("Rollback skipped: no backup branch available.") - logger.warning("\nROLLBACK COMPLETE\n") - result.git_exit_code = 1 - result.docker_exit_code = 1 - if rollback_success: - result.rollback_message = f"Deployment failed, rollback performed using backup branch {getattr(result, 'backup_branch_name', '')}." - # Retry docker-compose up after rollback - try: - retry_result = subprocess.run( - ["docker-compose", "up", "--build", "-d"], - cwd=repo_config.path, - capture_output=True, - text=True, - ) - logger.info(f"Docker compose retry stdout: {retry_result.stdout}") - logger.info(f"Docker compose retry stderr: {retry_result.stderr}") - result.docker_stdout += f"\n[rollback retry]\n{retry_result.stdout}" - result.docker_stderr += f"\n[rollback retry]\n{retry_result.stderr}" - result.docker_exit_code = retry_result.returncode - except Exception as e: - logger.error(f"Retry after rollback failed: {e}") - else: - result.rollback_message = f"Deployment failed, rollback logic triggered but failed: {rollback_error or 'No backup branch.'}" - push_update_success_as_discord_embed(repo_config, result) - return result - if getattr(repo_config, 'enable_rollback', False) and hasattr(result, 'backup_branch_name') and result.backup_branch_name: + if docker_result.returncode != 0 and repo_config.enable_rollback: + return do_rollback(repo_config, copy_branch_name, result) + if repo_config.enable_rollback and copy_branch_name: try: - subprocess.run(["git", "branch", "-D", result.backup_branch_name], cwd=repo_config.path, check=True) - logger.info(f"Deleted backup branch {result.backup_branch_name} after successful deployment.") + subprocess.run(["git", "branch", "-D", copy_branch_name], cwd=repo_config.path, check=True) + logger.info(f"Deleted backup branch {copy_branch_name} after successful deployment.") except Exception as e: - logger.error(f"Failed to delete backup branch {result.backup_branch_name}: {e}") + logger.error(f"Failed to delete backup branch {copy_branch_name}: {e}") push_update_success_as_discord_embed(repo_config, result) except Exception: logger.exception("update_repo had a bad time") From 4ee6c254294471f30cf2f07427dc0ff0330a5130 Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 4 Jan 2026 16:12:57 -0800 Subject: [PATCH 09/15] changed logger.error to logger.exception Co-authored-by: Evan Ugarte <36345325+evanugarte@users.noreply.github.com> --- server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index 524c3dc..ba72d81 100644 --- a/server.py +++ b/server.py @@ -151,8 +151,8 @@ def create_copy_of_cicd_branch(repo_config): subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) logger.info(f"Created backup branch {copy_branch_name} for rollback protection.") return copy_branch_name - except Exception as e: - logger.error(f"Failed to create backup branch {copy_branch_name}: {e}") + except Exception: + logger.exception("Failed to create backup branch {copy_branch_name}") return None def do_rollback(repo_config, copy_branch_name, result): rollback_success = False From d767205e9676af2631fa9206b50ac915a8f800e5 Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 4 Jan 2026 16:14:45 -0800 Subject: [PATCH 10/15] fixed code to assume that copy_branch_name is set Co-authored-by: Evan Ugarte <36345325+evanugarte@users.noreply.github.com> --- server.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server.py b/server.py index ba72d81..0af7f6c 100644 --- a/server.py +++ b/server.py @@ -234,8 +234,7 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: result.docker_exit_code = docker_result.returncode # rollback command for terminal if docker_result.returncode != 0 and repo_config.enable_rollback: - return do_rollback(repo_config, copy_branch_name, result) - if repo_config.enable_rollback and copy_branch_name: + rollback_worked = do_rollback(repo_config, copy_branch_name, result) try: subprocess.run(["git", "branch", "-D", copy_branch_name], cwd=repo_config.path, check=True) logger.info(f"Deleted backup branch {copy_branch_name} after successful deployment.") From 469050856b26cf113a0347b3d20c6e3e9dc3b59d Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 4 Jan 2026 16:50:39 -0800 Subject: [PATCH 11/15] Add maybe_rollback_result to server.py Added maybe_rollback_result attribute to track rollback status. --- server.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index 0af7f6c..63152c5 100644 --- a/server.py +++ b/server.py @@ -71,6 +71,7 @@ class RepoUpdateResult: docker_stdout: str = "" docker_stderr: str = "" development: bool = False + maybe_rollback_result: bool | None = None def load_config(development: bool): @@ -108,6 +109,12 @@ def push_update_success_as_discord_embed( repo_name = prefix + " " + repo_name # do a gray color if we are sending "not real" embeds color = 0x99AAB5 + if hasattr(result, 'maybe_rollback_result') and result.maybe_rollback_result is not None: + description_list.append("") + if result.maybe_rollback_result: + description_list.append("**Rollback status:** :white_check_mark: Rollback was attempted and succeeded.") + else: + description_list.append("**Rollback status:** :x: Rollback was attempted but failed.") embed_json = { "embeds": [ @@ -154,9 +161,7 @@ def create_copy_of_cicd_branch(repo_config): except Exception: logger.exception("Failed to create backup branch {copy_branch_name}") return None -def do_rollback(repo_config, copy_branch_name, result): - rollback_success = False - rollback_error = None +def do_rollback(repo_config, copy_branch_name): try: # Reset main to backup branch subprocess.run(["git", "checkout", repo_config.branch], cwd=repo_config.path, check=True) From 13c3a5e1636dafcdaf53211c1614ac5149e9403b Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 4 Jan 2026 17:19:21 -0800 Subject: [PATCH 12/15] Simplify rollback logic in server.py Refactor rollback logic to simplify return statements and remove unnecessary error handling. --- server.py | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/server.py b/server.py index 63152c5..a1d9195 100644 --- a/server.py +++ b/server.py @@ -169,33 +169,10 @@ def do_rollback(repo_config, copy_branch_name): # Delete backup branch subprocess.run(["git", "branch", "-D", copy_branch_name], cwd=repo_config.path, check=True) logger.info(f"Rolled back {repo_config.branch} to {copy_branch_name} and deleted backup branch.") - rollback_success = True + return True except Exception as e: logger.error(f"Rollback failed: {e}") - rollback_error = str(e) - result.git_exit_code = 1 - result.docker_exit_code = 1 - if rollback_success: - result.rollback_message = f"Deployment failed, rollback performed using backup branch {copy_branch_name}." - # Retry docker-compose up after rollback - try: - retry_result = subprocess.run( - ["docker-compose", "up", "--build", "-d"], - cwd=repo_config.path, - capture_output=True, - text=True, - ) - logger.info(f"Docker compose retry stdout: {retry_result.stdout}") - logger.info(f"Docker compose retry stderr: {retry_result.stderr}") - result.docker_stdout += f"\n[rollback retry]\n{retry_result.stdout}" - result.docker_stderr += f"\n[rollback retry]\n{retry_result.stderr}" - result.docker_exit_code = retry_result.returncode - except Exception as e: - logger.error(f"Retry after rollback failed: {e}") - else: - result.rollback_message = f"Deployment failed, rollback logic triggered but failed: {rollback_error or 'No backup branch.'}" - push_update_success_as_discord_embed(repo_config, result) - return result + return False def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: MetricsHandler.last_push_timestamp.labels(repo=repo_config.name).set(time.time()) From 2aa2f00346df23661230763b5760f60a8b98778d Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 4 Jan 2026 22:20:44 -0800 Subject: [PATCH 13/15] removed the hasattr function --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index a1d9195..dfee661 100644 --- a/server.py +++ b/server.py @@ -109,7 +109,7 @@ def push_update_success_as_discord_embed( repo_name = prefix + " " + repo_name # do a gray color if we are sending "not real" embeds color = 0x99AAB5 - if hasattr(result, 'maybe_rollback_result') and result.maybe_rollback_result is not None: + if result.maybe_rollback_result is not None: description_list.append("") if result.maybe_rollback_result: description_list.append("**Rollback status:** :white_check_mark: Rollback was attempted and succeeded.") From fca9ef5b06b83a3b48b82f44c7a68a4677e01fbb Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 5 Jan 2026 21:24:04 -0800 Subject: [PATCH 14/15] removed "as e" Co-authored-by: Evan Ugarte <36345325+evanugarte@users.noreply.github.com> --- server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index dfee661..b7c1a69 100644 --- a/server.py +++ b/server.py @@ -220,8 +220,8 @@ def update_repo(repo_config: RepoToWatch) -> RepoUpdateResult: try: subprocess.run(["git", "branch", "-D", copy_branch_name], cwd=repo_config.path, check=True) logger.info(f"Deleted backup branch {copy_branch_name} after successful deployment.") - except Exception as e: - logger.error(f"Failed to delete backup branch {copy_branch_name}: {e}") + except Exception: + logger.error(f"Failed to delete backup branch {copy_branch_name}:") push_update_success_as_discord_embed(repo_config, result) except Exception: logger.exception("update_repo had a bad time") From 5c9e1ebb73bda2bf06854b35730702da11c47511 Mon Sep 17 00:00:00 2001 From: Brian Date: Sun, 11 Jan 2026 12:13:50 -0800 Subject: [PATCH 15/15] Change type hint for maybe_rollback_result to Optional --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index b7c1a69..d5f6a04 100644 --- a/server.py +++ b/server.py @@ -71,7 +71,7 @@ class RepoUpdateResult: docker_stdout: str = "" docker_stderr: str = "" development: bool = False - maybe_rollback_result: bool | None = None + maybe_rollback_result: Optional[bool] = None def load_config(development: bool):