bsc

Comprehensive codebase and cou...
Log | Files | Refs | Activity | README | LICENSE

root / utils / deploy_pipeline.py

deploy_pipeline.py (9709B)


      1 import os
      2 import subprocess
      3 import shutil
      4 import stat
      5 import socket
      6 import sys
      7 from datetime import datetime
      8 
      9 BSC_REPO_ROOT = r"G:\bsc"
     10 GENERATE_INDEX_SCRIPT = r"G:\bsc\docs\generate_index.py"
     11 ARANAG_SITE_DESKTOP = r"C:\Users\PC\Desktop\amit.is-a.dev"
     12 BSC_LOCAL_BACKUP = r"G:\bsc_local"
     13 ARANAG_REPO_ROOT = r"G:\aranag"
     14 
     15 MIN_DISK_SPACE_MB = 500
     16 
     17 ARANAG_PRESERVE = [
     18     "ada-web",
     19     "compiler",
     20     "README.md",
     21     "sitemap.xml",
     22     ".firebase",
     23     ".git",
     24     "esal",
     25     "amit.is-a.dev"
     26 ]
     27 
     28 def remove_readonly(func, path, exc_info):
     29     try:
     30         os.chmod(path, stat.S_IWRITE)
     31         func(path)
     32     except Exception as e:
     33         print(f"Failed to force delete {path}: {e}")
     34 
     35 def check_internet(host="8.8.8.8", port=53, timeout=3):
     36     try:
     37         socket.setdefaulttimeout(timeout)
     38         socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
     39         return True
     40     except socket.error:
     41         return False
     42 
     43 def get_free_space_mb(folder):
     44     total, used, free = shutil.disk_usage(folder)
     45     return free // (2**20)
     46 
     47 def is_tool_installed(name):
     48     return shutil.which(name) is not None
     49 
     50 def pre_check():
     51     print("\n--- Step 0: System Pre-Checks ---")
     52     
     53     print("Checking internet connection...", end=" ")
     54     if check_internet():
     55         print("[OK]")
     56     else:
     57         print("[FAILED]")
     58         print("Error: No internet connection detected. Cannot push to Git or Firebase.")
     59         return False
     60 
     61     print("Checking required tools...", end=" ")
     62     missing_tools = []
     63     if not is_tool_installed("git"):
     64         missing_tools.append("git")
     65     
     66     if not is_tool_installed("firebase"):
     67         if not is_tool_installed("firebase.cmd"):
     68              missing_tools.append("firebase")
     69 
     70     if missing_tools:
     71         print("[FAILED]")
     72         print(f"Error: The following tools are missing from PATH: {', '.join(missing_tools)}")
     73         return False
     74     print("[OK]")
     75 
     76     backup_drive = os.path.splitdrive(BSC_LOCAL_BACKUP)[0]
     77     if not backup_drive: 
     78         backup_drive = "." 
     79     else:
     80         backup_drive += "\\"
     81         
     82     print(f"Checking disk space on {backup_drive}...", end=" ")
     83     try:
     84         free_space = get_free_space_mb(backup_drive)
     85         if free_space < MIN_DISK_SPACE_MB:
     86             print("[FAILED]")
     87             print(f"Error: Not enough disk space. Free: {free_space}MB, Required: {MIN_DISK_SPACE_MB}MB")
     88             return False
     89         print(f"[OK] ({free_space} MB free)")
     90     except Exception as e:
     91         print(f"[WARNING] Could not check disk space: {e}")
     92 
     93     return True
     94 
     95 def run_generate_index():
     96     print("\n--- Step 1: Generating Index HTML ---")
     97     
     98     index_path = os.path.join(BSC_REPO_ROOT, "docs", "index.html")
     99     old_content = ""
    100     
    101     if os.path.exists(index_path):
    102         try:
    103             with open(index_path, 'r', encoding='utf-8') as f:
    104                 old_content = f.read()
    105         except Exception:
    106             pass
    107 
    108     if os.path.exists(GENERATE_INDEX_SCRIPT):
    109         try:
    110             subprocess.run(["python", GENERATE_INDEX_SCRIPT], check=True)
    111             print("[Success] Index generation script executed.")
    112         except subprocess.CalledProcessError:
    113             print("[Error] Failed to run generate_index.py")
    114             return False
    115     else:
    116         print(f"[Error] Script not found at: {GENERATE_INDEX_SCRIPT}")
    117         return False
    118 
    119     new_content = ""
    120     if os.path.exists(index_path):
    121         try:
    122             with open(index_path, 'r', encoding='utf-8') as f:
    123                 new_content = f.read()
    124         except Exception:
    125             pass
    126 
    127     if old_content != new_content:
    128         print("[Info] Changes detected in index.html.")
    129         return True
    130     else:
    131         print("[Info] No changes detected in index.html.")
    132         return False
    133 
    134 def git_workflow_bsc():
    135     print("\n--- Step 2: Git Push (Primary Repo: bsc) ---")
    136     
    137     if not os.path.exists(BSC_REPO_ROOT):
    138         print(f"[Error] Repository root not found: {BSC_REPO_ROOT}")
    139         return
    140 
    141     os.chdir(BSC_REPO_ROOT)
    142     
    143     print("> git add .")
    144     try:
    145         subprocess.run(["git", "add", "."], check=True)
    146     except subprocess.CalledProcessError:
    147         print("[Error] 'git add' failed.")
    148         return
    149 
    150     try:
    151         result = subprocess.run(
    152             ["git", "diff", "--name-only", "--cached"],
    153             capture_output=True, text=True, check=True
    154         )
    155         changed_files = result.stdout.strip().splitlines()
    156     except subprocess.CalledProcessError:
    157         changed_files = []
    158 
    159     if not changed_files:
    160         print("[Info] No changes detected in 'bsc'. Skipping commit/push.")
    161         return
    162 
    163     # 1. Filter out docs/index.html (it's auto-generated)
    164     relevant_files = [f for f in changed_files if "docs/index.html" not in f.replace('\\', '/')]
    165 
    166     # 2. Separate "docs" files from "source code" files
    167     # We check if a file starts with "docs/"
    168     non_docs_files = [f for f in relevant_files if not f.replace('\\', '/').startswith('docs/')]
    169 
    170     # 3. Decision Logic:
    171     # If we have non-docs changes (like Semester_1/code.c), we prioritize those paths.
    172     # We ignore 'docs/' changes in the path calculation so it doesn't default to Root.
    173     if non_docs_files:
    174         files_to_check = non_docs_files
    175     else:
    176         # If ONLY docs changed (or only index.html changed), use whatever we have
    177         files_to_check = relevant_files if relevant_files else changed_files
    178 
    179     changed_dirs = [os.path.dirname(f.replace('/', os.sep)) for f in files_to_check]
    180     
    181     if not changed_dirs:
    182         common_path = ""
    183     else:
    184         try:
    185             common_path = os.path.commonpath(changed_dirs)
    186         except ValueError:
    187             common_path = ""
    188 
    189     path_str = f".\\{common_path}" if common_path else ".\\{root}"
    190     
    191     print(f"[Detected Changes in]: {path_str}")
    192     user_message = input(f"Enter commit message for '{path_str}': ")
    193     if not user_message:
    194         print("Commit message cannot be empty. Aborting git push.")
    195         return
    196 
    197     today = datetime.now().strftime("%Y-%m-%d")
    198     full_commit_msg = f"[{today}] : {path_str} : {user_message}"
    199     
    200     print(f"> git commit -m \"{full_commit_msg}\"")
    201     try:
    202         subprocess.run(["git", "commit", "-m", full_commit_msg], check=True)
    203         print("> git push")
    204     except subprocess.CalledProcessError as e:
    205         print(f"[Error] Git command failed: {e}")
    206 
    207 def deploy_firebase():
    208     print("\n--- Step 3: Firebase Deploy ---")
    209     if not os.path.exists(ARANAG_SITE_DESKTOP):
    210         print(f"[Error] Firebase project path not found: {ARANAG_SITE_DESKTOP}")
    211         return
    212 
    213     os.chdir(ARANAG_SITE_DESKTOP)
    214     print(f"Deploying from: {ARANAG_SITE_DESKTOP}")
    215     try:
    216         subprocess.run("firebase deploy --only hosting", shell=True, check=True)
    217         print("[Success] Firebase deployment complete.")
    218     except subprocess.CalledProcessError:
    219         print("[Error] Firebase deploy failed.")
    220 
    221 def sync_bsc_local():
    222     print("\n--- Step 4: Syncing to G:\\bsc_local ---")
    223     try:
    224         if os.path.exists(BSC_LOCAL_BACKUP):
    225             print(f"Cleaning {BSC_LOCAL_BACKUP}...")
    226             shutil.rmtree(BSC_LOCAL_BACKUP, onerror=remove_readonly)
    227         
    228         print(f"Copying from {BSC_REPO_ROOT} to {BSC_LOCAL_BACKUP}...")
    229         shutil.copytree(BSC_REPO_ROOT, BSC_LOCAL_BACKUP)
    230         print("[Success] bsc_local synced.")
    231     except Exception as e:
    232         print(f"[Error] Sync failed: {e}")
    233 
    234 def update_and_push_aranag():
    235     print("\n--- Step 5: Updating G:\\aranag & Pushing ---")
    236     
    237     if not os.path.exists(ARANAG_REPO_ROOT):
    238         print(f"[Error] Path not found: {ARANAG_REPO_ROOT}")
    239         return
    240 
    241     print("Cleaning G:\\aranag (preserving specific files)...")
    242     for item in os.listdir(ARANAG_REPO_ROOT):
    243         if item in ARANAG_PRESERVE:
    244             continue
    245         
    246         item_path = os.path.join(ARANAG_REPO_ROOT, item)
    247         try:
    248             if os.path.isdir(item_path):
    249                 shutil.rmtree(item_path, onerror=remove_readonly)
    250             else:
    251                 os.remove(item_path)
    252         except Exception as e:
    253             print(f"Warning: Could not delete {item}: {e}")
    254 
    255     print(f"Copying from {ARANAG_SITE_DESKTOP} to {ARANAG_REPO_ROOT}...")
    256     try:
    257         shutil.copytree(ARANAG_SITE_DESKTOP, ARANAG_REPO_ROOT, dirs_exist_ok=True)
    258     except Exception as e:
    259         print(f"[Error] Copy failed: {e}")
    260         return
    261 
    262     os.chdir(ARANAG_REPO_ROOT)
    263     print("Git pushing G:\\aranag...")
    264     
    265     try:
    266         subprocess.run(["git", "add", "."], check=True)
    267         
    268         status = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True)
    269         if status.stdout.strip():
    270             commit_msg = f"Automated Update: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
    271             subprocess.run(["git", "commit", "-m", commit_msg], check=True)
    272             subprocess.run(["git", "push"], check=True)
    273             print("[Success] G:\\aranag updated and pushed.")
    274         else:
    275             print("[Info] No changes to push in G:\\aranag.")
    276             
    277     except subprocess.CalledProcessError as e:
    278         print(f"[Error] Git operations on aranag failed: {e}")
    279 
    280 def main():
    281     print("=== STARTING AUTOMATION PIPELINE ===")
    282     
    283     if not pre_check():
    284         print("\n[Aborted] Pre-checks failed. Please resolve the errors above.")
    285         return
    286 
    287     index_changed = run_generate_index()
    288 
    289     git_workflow_bsc()
    290 
    291     if index_changed:
    292         deploy_firebase()
    293     else:
    294         print("\n[Skip] Index unchanged. Skipping Firebase deploy.")
    295 
    296     sync_bsc_local()
    297 
    298     # removed the auto git upload for the main website folder.
    299     
    300     print("\n=== PIPELINE FINISHED ===")
    301 
    302 if __name__ == "__main__":
    303     main()
© notamitgamer • Site Built: 2026-09-05 01:53:16 UTC • git-mirror commit: c170d72 [view raw info]
Originally created with stagit • modified by notamitgamer
Forked from github.com/notamitgamer/git-mirror