Mercurial > piecrust2
comparison foodtruck/sites.py @ 613:e2e955a3bb25
publish: Add publish command.
* Add `shell` publisher.
* Refactor admin panel's publishing backend to use that, along with the new
PID file support.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 04 Feb 2016 08:05:03 -0800 |
parents | efc1dc916e7c |
children |
comparison
equal
deleted
inserted
replaced
612:2edaefcb82cd | 613:e2e955a3bb25 |
---|---|
1 import os | 1 import os |
2 import os.path | 2 import os.path |
3 import copy | 3 import copy |
4 import shlex | |
5 import logging | 4 import logging |
6 import threading | 5 import threading |
7 import subprocess | 6 import subprocess |
8 from piecrust.app import PieCrust | 7 from piecrust.app import PieCrust |
9 from piecrust.configuration import merge_dicts | 8 from piecrust.configuration import merge_dicts |
25 self.name = name | 24 self.name = name |
26 self.root_dir = root_dir | 25 self.root_dir = root_dir |
27 self._global_config = config | 26 self._global_config = config |
28 self._piecrust_app = None | 27 self._piecrust_app = None |
29 self._scm = None | 28 self._scm = None |
30 self._publish_thread = None | |
31 logger.debug("Creating site object for %s" % self.name) | 29 logger.debug("Creating site object for %s" % self.name) |
32 | 30 |
33 @property | 31 @property |
34 def piecrust_app(self): | 32 def piecrust_app(self): |
35 if self._piecrust_app is None: | 33 if self._piecrust_app is None: |
54 self._scm = False | 52 self._scm = False |
55 | 53 |
56 return self._scm | 54 return self._scm |
57 | 55 |
58 @property | 56 @property |
59 def is_publish_running(self): | 57 def publish_pid_file(self): |
60 return (self._publish_thread is not None and | 58 return os.path.join(self.piecrust_app.cache_dir, 'publish.pid') |
61 self._publish_thread.is_alive()) | |
62 | 59 |
63 @property | 60 @property |
64 def publish_thread(self): | 61 def publish_log_file(self): |
65 return self._publish_thread | 62 return os.path.join(self.piecrust_app.cache_dir, 'publish.log') |
66 | 63 |
67 def publish(self, target): | 64 def publish(self, target): |
68 target_cfg = self.piecrust_app.config.get('publish/%s' % target) | 65 args = [ |
69 if not target_cfg: | 66 'chef', |
70 raise Exception("No such publish target: %s" % target) | 67 '--pid-file', self.publish_pid_file, |
68 'publish', target, | |
69 '--log-publisher', self.publish_log_file] | |
70 proc = subprocess.Popen(args, cwd=self.root_dir) | |
71 | 71 |
72 target_cmd = target_cfg.get('cmd') | 72 def _comm(): |
73 if not target_cmd: | 73 proc.communicate() |
74 raise Exception("No command specified for publish target: %s" % | |
75 target) | |
76 publish_args = shlex.split(target_cmd) | |
77 | 74 |
78 logger.debug( | 75 t = threading.Thread(target=_comm, daemon=True) |
79 "Executing publish target '%s': %s" % (target, publish_args)) | 76 t.start() |
80 proc = subprocess.Popen(publish_args, cwd=self.root_dir, | |
81 stdout=subprocess.PIPE, | |
82 stderr=subprocess.PIPE) | |
83 | |
84 pid_file_path = os.path.join(self.root_dir, '.ft_pub.pid') | |
85 with open(pid_file_path, 'w') as fp: | |
86 fp.write(str(proc.pid)) | |
87 | |
88 logger.debug("Running publishing monitor for PID %d" % proc.pid) | |
89 self._publish_thread = _PublishThread( | |
90 self.name, self.root_dir, proc, self._onPublishEnd) | |
91 self._publish_thread.start() | |
92 | |
93 def _onPublishEnd(self): | |
94 os.unlink(os.path.join(self.root_dir, '.ft_pub.pid')) | |
95 self._publish_thread = None | |
96 | |
97 | |
98 class _PublishThread(threading.Thread): | |
99 def __init__(self, sitename, siteroot, proc, callback): | |
100 super(_PublishThread, self).__init__( | |
101 name='%s_publish' % sitename, daemon=True) | |
102 self.sitename = sitename | |
103 self.siteroot = siteroot | |
104 self.proc = proc | |
105 self.callback = callback | |
106 | |
107 log_file_path = os.path.join(self.siteroot, '.ft_pub.log') | |
108 self.log_fp = open(log_file_path, 'w', encoding='utf8') | |
109 | |
110 def run(self): | |
111 for line in self.proc.stdout: | |
112 self.log_fp.write(line.decode('utf8')) | |
113 for line in self.proc.stderr: | |
114 self.log_fp.write(line.decode('utf8')) | |
115 self.proc.communicate() | |
116 if self.proc.returncode != 0: | |
117 self.log_fp.write("Error, publish process returned code %d" % | |
118 self.proc.returncode) | |
119 self.log_fp.close() | |
120 | |
121 logger.debug("Publish ended for %s." % self.sitename) | |
122 self.callback() | |
123 | 77 |
124 | 78 |
125 class FoodTruckSites(): | 79 class FoodTruckSites(): |
126 def __init__(self, config, current_site): | 80 def __init__(self, config, current_site): |
127 self._sites = {} | 81 self._sites = {} |