1+ import ast
2+ import os
3+ import shutil
4+ import subprocess
5+
6+
7+ HOSTED_SITE_DOMAIN = "docs-dev.polygon.technology"
8+
9+
10+ def install_mkdocs_with_pipenv ():
11+ """
12+ Builds a particular branch site.
13+ Having a varying set of requirements can be handled by having each branch
14+ build their dependencies and then running mkdocs build.
15+ """
16+ folder = os .getcwd ()
17+ subprocess .run (["pipenv" , "install" , "--site-packages" ], cwd = folder )
18+ subprocess .run (["pipenv" , "install" , "-r" , "requirements.txt" ], cwd = folder )
19+ subprocess .run (["pipenv" , "run" , "mkdocs" , "build" ], cwd = folder )
20+
21+ def copy_folder (source_dir , target_dir ):
22+ """
23+ Copies contents from source directory to target directory
24+ :param source_dir: Source directory from which contents are to be copied
25+ :param target_dir: Target Directory where the contents are copied to.
26+ """
27+ os .makedirs (target_dir , exist_ok = True )
28+
29+ for item in os .listdir (source_dir ):
30+ source_path = os .path .join (source_dir , item )
31+ target_path = os .path .join (target_dir , item )
32+
33+ if os .path .isdir (source_path ):
34+ shutil .copytree (source_path , target_path , dirs_exist_ok = True )
35+ else :
36+ if os .path .exists (target_path ):
37+ os .remove (target_path )
38+ shutil .copy2 (source_path , target_path )
39+
40+ def delete_folders (folder_paths ):
41+ """
42+ Cleans existing folders for app and branches before executing the builds
43+ :param folder_paths: List of folders to be deleted under the current working directory
44+ """
45+ for folder_path in folder_paths :
46+ try :
47+ shutil .rmtree (folder_path )
48+ print (f"Folder { folder_path } deletion successful." )
49+ except OSError as e :
50+ print (f"Error deleting folder: { e } " )
51+
52+ def clone_data_to_branch_folder (branch_name , remote_url , parent_dir , pr_number = None ):
53+ """
54+ Clones data to branch folder in branch/<PR Number> or branch/dev folder
55+ :param branch_name: Branch to clone and build
56+ :param remote_url: Remote url for the git repository
57+ :param parent_dir: Parent directory to get context of where data is stored
58+ :param pr_number: PR number for the branch to host data into the folder
59+ """
60+ common_dir = "branch"
61+ target_path = os .path .join (common_dir , pr_number )
62+ os .makedirs (target_path , exist_ok = True )
63+ os .chdir (target_path )
64+ subprocess .run (["git" , "init" ])
65+ subprocess .run (["git" , "remote" , "add" , "origin" , remote_url ])
66+ print (f"Checking out branch { branch_name } " )
67+ subprocess .run (["git" , "fetch" , "--depth" , "1" , "origin" , branch_name ])
68+ subprocess .run ([
69+ "git" , "checkout" , "-b" , branch_name , "--track" ,
70+ f"origin/{ branch_name } "
71+ ])
72+ install_mkdocs_with_pipenv ()
73+ source_dir = os .path .join (os .getcwd (), "site" )
74+ copy_folder (source_dir , os .path .join (parent_dir , "app" , pr_number ))
75+ os .chdir (parent_dir )
76+
77+
78+ def update_pr_description (pr_number :str ):
79+ """
80+ Updates PR description by adding the url to access the hosted environment under dev
81+ if it does not already exist in the definition
82+ :param pr_number: PR number for the branch hosting website
83+ """
84+ command = ["gh" , "pr" , "view" , pr_number , "--json" , "body" , "--jq" , ".body" ]
85+ pr_description = subprocess .run (command , capture_output = True , text = True ).stdout .strip ()
86+ hosted_url = f"{ HOSTED_SITE_DOMAIN } /{ pr_number } "
87+ if hosted_url not in pr_description :
88+ new_pr_description = f"Hosted url: [{ hosted_url } ](https://{ hosted_url } )\n " + pr_description
89+ command = ["gh" , "pr" , "edit" , pr_number , "--body" , new_pr_description ]
90+ subprocess .run (command )
91+
92+
93+ def process_branch_folders ():
94+ """
95+ Clones the branch specific code to hosted/<branch-name> folder.
96+ It then executes the build command and copy the built site to apps folder
97+ under the same branch name
98+ :return: PR numbers in str list where the site data is copied to
99+ """
100+ delete_folders (["branch" , "app" ])
101+
102+ command = ["gh" , "pr" , "list" , "--json" , "number,headRefName" ]
103+ command_run_result = subprocess .run (command , capture_output = True , text = True ).stdout .strip ()
104+ branches_data = ast .literal_eval (command_run_result )
105+ remote_url = subprocess .run (["git" , "remote" , "get-url" , "origin" ],
106+ capture_output = True ,
107+ text = True ).stdout .strip ()
108+ parent_dir = os .getcwd ()
109+ clone_data_to_branch_folder ("dev" , remote_url , parent_dir , "dev" )
110+ pr_numbers = []
111+ for branch_data in branches_data :
112+ if not branch_data ["headRefName" ].startswith ("hosted/" ) or not branch_data .get ("number" ):
113+ continue
114+ pr_number = str (branch_data ["number" ])
115+ clone_data_to_branch_folder (branch_data ["headRefName" ], remote_url , parent_dir , pr_number )
116+ update_pr_description (pr_number )
117+ pr_numbers .append (pr_number )
118+
119+ return pr_numbers
120+
121+ def update_nginx_config (pr_numbers ):
122+ """
123+ Updates nginx.conf file with branches built information to host multiple versions
124+ of software at the same time.
125+ :param pr_numbers: pr numbers a str list of open pr numbers to be hosted
126+ """
127+ config_file = os .path .join (os .getcwd (), "nginx.conf" )
128+ nginx_location_blocks = ""
129+
130+ for pr_number in pr_numbers :
131+ location_block = f"""location /{ pr_number } {{
132+ alias /app/{ pr_number } ;
133+ try_files $uri $uri/ /index.html;
134+ error_page 404 /404.html;
135+ }}
136+ """
137+ nginx_location_blocks += location_block
138+ print (f"Hosted site: https://{ HOSTED_SITE_DOMAIN } /{ pr_number } " )
139+
140+ with open (config_file , "r+" ) as f :
141+ content = f .read ()
142+ content = content .replace ("#REPLACE_APPS" , nginx_location_blocks )
143+ f .seek (0 )
144+ f .write (content )
145+ f .truncate ()
146+
147+ print ("NGINX configuration updated successfully!" )
148+
149+ if __name__ == "__main__" :
150+ current_dir = os .getcwd ()
151+ open_prs = process_branch_folders ()
152+ update_nginx_config (open_prs )
0 commit comments