1+ from .logger import logger
2+
3+ class DeployManager :
4+ def __init__ (self , ssh , workdir , venvdir , wsgi ):
5+ self .ssh = ssh
6+ self .workdir = workdir
7+ self .venv = f"source { venvdir } /bin/activate"
8+ self .wsgi = wsgi
9+ self .prev_commit = ""
10+
11+ def post_pull_tasks (self , changes ):
12+ def changed (path ): return any (path in f for f in changes )
13+
14+ if changed ("requirements.txt" ):
15+ logger .info ("requirements.txt changed. Installing dependencies..." )
16+ self .ssh .exec (f"cd { self .workdir } && { self .venv } && pip install -r requirements.txt" )
17+
18+ if any ("models.py" in f or f .startswith ("migrations/" ) for f in changes ):
19+ logger .info ("Model or migration changes detected. Running migrations..." )
20+ self .ssh .exec (f"cd { self .workdir } && { self .venv } && python manage.py makemigrations" )
21+ self .ssh .exec (f"cd { self .workdir } && { self .venv } && python manage.py migrate" )
22+
23+ if any ("static" in f for f in changes ):
24+ logger .info ("Static files changed. Running collectstatic..." )
25+ self .ssh .exec (f"cd { self .workdir } && { self .venv } && python manage.py collectstatic --noinput" )
26+
27+ logger .info ("Running tests..." )
28+ out , err = self .ssh .exec (f"cd { self .workdir } && { self .venv } && python manage.py test" )
29+ if err and not "Ran 0 tests" in err :
30+ logger .error ("Tests failed" )
31+ raise Exception (err )
32+ else :
33+ logger .info ("Tests passed successfully." )
34+
35+ def get_changed_files (self ):
36+ out , _ = self .ssh .exec (f"cd { self .workdir } && git rev-parse HEAD" )
37+ self .prev_commit = out .strip ()
38+ logger .info (f"Previous commit: { self .prev_commit } " )
39+
40+ logger .info ("Checking for changes in the remote repository..." )
41+ self .ssh .exec (f"cd { self .workdir } && git fetch origin" )
42+ out , _ = self .ssh .exec (f"cd { self .workdir } && git diff --name-only origin/main..HEAD" )
43+ return out .splitlines ()
44+
45+ def rollback_to_previous_commit (self ):
46+ logger .warning ("Rolling back to previous commit..." )
47+ self .ssh .exec (f"cd { self .workdir } && git reset --hard { self .prev_commit } " )
48+
49+ def deploy (self ):
50+ try :
51+ changes = self .get_changed_files ()
52+ if changes :
53+ logger .info ("Changed files:\n " + "\n " .join (changes ))
54+ self .ssh .exec (f"cd { self .workdir } && git pull origin main" )
55+ logger .info ("Pulled latest changes from remote repository." )
56+ try :
57+ self .post_pull_tasks (changes )
58+ except Exception :
59+ logger .exception ("Error during post-pull tasks" )
60+ self .rollback_to_previous_commit ()
61+ logger .warning ("Rolled back due to test failure." )
62+ raise
63+ else :
64+ logger .info ("No files changed." )
65+
66+ logger .info ("Reloading application (touch WSGI)..." )
67+ self .ssh .exec (f"touch { self .wsgi } " )
68+ logger .info ("Deployment completed successfully!" )
69+
70+ except Exception :
71+ logger .exception ("Error during deployment" )
72+ self .rollback_to_previous_commit ()
73+ raise
0 commit comments