summaryrefslogtreecommitdiffstats
path: root/GitAutoDeploy.py
diff options
context:
space:
mode:
authorOliver Poignant <oliver@poignant.se>2016-03-05 02:02:08 +0100
committerOliver Poignant <oliver@poignant.se>2016-03-05 02:02:08 +0100
commit1331a34fb18270fbcfada8655d21d0a6a666e021 (patch)
treefa4d90d0ee6d71c903095d0f0c638c4968bc5676 /GitAutoDeploy.py
parent5b525b98a9226e1232e233fcbaea684a49c52255 (diff)
downloadGit-Auto-Deploy-1331a34fb18270fbcfada8655d21d0a6a666e021.zip
Git-Auto-Deploy-1331a34fb18270fbcfada8655d21d0a6a666e021.tar.gz
Git-Auto-Deploy-1331a34fb18270fbcfada8655d21d0a6a666e021.tar.bz2
Refactoring and cleanup after last PR
Diffstat (limited to 'GitAutoDeploy.py')
-rwxr-xr-xGitAutoDeploy.py172
1 files changed, 108 insertions, 64 deletions
diff --git a/GitAutoDeploy.py b/GitAutoDeploy.py
index 2ef3aae..f053245 100755
--- a/GitAutoDeploy.py
+++ b/GitAutoDeploy.py
@@ -119,31 +119,17 @@ class GitWrapper():
if 'path' in repo_config:
path = repo_config['path']
- cmds = []
- if 'deploy' in repo_config:
- cmds.append(repo_config['deploy'])
-
- gd = GitAutoDeploy().get_config()['global_deploy']
- if len(gd[0]) is not 0:
- cmds.insert(0, gd[0])
- if len(gd[1]) is not 0:
- cmds.append(gd[1])
-
logger.info('Executing deploy command(s)')
+
+ # Use repository path as default cwd when executing deploy commands
+ cwd = (repo_config['path'] if 'path' in repo_config else None)
- if logFilePath:
- with open(logFilePath, 'a') as logfile:
- for cmd in cmds:
- if 'path' in repo_config:
- call(['cd "' + path + '" && ' + cmd], stdout=logfile, stderr=logfile, shell=True)
- else:
- call([cmd], stdout=logfile, stderr=logfile, shell=True)
- else:
- for cmd in cmds:
- if 'path' in repo_config:
- call(['cd "' + path + '" && ' + cmd], shell=True)
- else:
- call([cmd], shell=True)
+ for cmd in repo_config['deploy_commands']:
+ if logFilePath:
+ with open(logFilePath, 'a') as logfile:
+ call([cmd], cwd=cwd, stdout=logfile, stderr=logfile, shell=True)
+ else:
+ call([cmd], cwd=cwd, shell=True)
class WebhookRequestHandler(BaseHTTPRequestHandler):
@@ -283,6 +269,10 @@ class WebhookRequestHandler(BaseHTTPRequestHandler):
return repo_urls, ref or "master", action
+# Used to describe when a filter does not match a request
+class FilterMatchError(Exception): pass
+
+
class GitAutoDeploy(object):
config_path = None
debug = True
@@ -369,28 +359,45 @@ class GitAutoDeploy(object):
# Process each matching repository
for repo_config in repo_configs:
- if repo_config['pullrequestfilter'] and (repo_config['ref'] != ref or repo_config['action'] != action):
+ try:
+ # Verify that all filters matches the request if specified
+ if 'filters' in repo_config:
+ for filter in repo_config['filters']:
+ if filter['type'] == 'pull-request-filter':
+ if filter['ref'] == ref and filter['action'] == action:
+ continue
+ raise FilterMatchError()
+ else:
+ logger.error('Unrecognized filter: ' % filter)
+ raise FilterMatchError()
+
+ except FilterMatchError as e:
continue
-
- if 'path' in repo_config:
- running_lock = Lock(os.path.join(repo_config['path'], 'status_running'))
- waiting_lock = Lock(os.path.join(repo_config['path'], 'status_waiting'))
+
+
+ # In case there is no path configured for the repository, no pull will
+ # be made.
+ if not 'path' in repo_config:
+ GitWrapper.deploy(repo_config)
+ continue
+
+ running_lock = Lock(os.path.join(repo_config['path'], 'status_running'))
+ waiting_lock = Lock(os.path.join(repo_config['path'], 'status_waiting'))
try:
- if 'path' in repo_config:
- # Attempt to obtain the status_running lock
- while not running_lock.obtain():
+ # Attempt to obtain the status_running lock
+ while not running_lock.obtain():
- # If we're unable, try once to obtain the status_waiting lock
- if not waiting_lock.has_lock() and not waiting_lock.obtain():
- logger.error("Unable to obtain the status_running lock nor the status_waiting lock. Another process is " +
- "already waiting, so we'll ignore the request.")
+ # If we're unable, try once to obtain the status_waiting lock
+ if not waiting_lock.has_lock() and not waiting_lock.obtain():
+ logger.error("Unable to obtain the status_running lock nor the status_waiting lock. Another process is " +
+ "already waiting, so we'll ignore the request.")
- # If we're unable to obtain the waiting lock, ignore the request
- break
+ # If we're unable to obtain the waiting lock, ignore the request
+ break
- # Keep on attempting to obtain the status_running lock until we succeed
- time.sleep(5)
+ # Keep on attempting to obtain the status_running lock until we succeed
+ time.sleep(5)
n = 4
while 0 < n and 0 != GitWrapper.pull(repo_config):
@@ -400,20 +407,18 @@ class GitAutoDeploy(object):
GitWrapper.deploy(repo_config)
except Exception as e:
- if 'path' in repo_config:
- logger.error('Error during \'pull\' or \'deploy\' operation on path: %s' % repo_config['path'])
+ logger.error('Error during \'pull\' or \'deploy\' operation on path: %s' % repo_config['path'])
logger.error(e)
finally:
- if 'path' in repo_config:
- # Release the lock if it's ours
- if running_lock.has_lock():
- running_lock.release()
+ # Release the lock if it's ours
+ if running_lock.has_lock():
+ running_lock.release()
- # Release the lock if it's ours
- if waiting_lock.has_lock():
- waiting_lock.release()
+ # Release the lock if it's ours
+ if waiting_lock.has_lock():
+ waiting_lock.release()
def get_default_config_path(self):
import os
@@ -483,6 +488,30 @@ class GitAutoDeploy(object):
for repo_config in self._config['repositories']:
+ # Setup branch if missing
+ if 'branch' not in repo_config:
+ repo_config['branch'] = "master"
+
+ # Setup remote if missing
+ if 'remote' not in repo_config:
+ repo_config['remote'] = "origin"
+
+ # Setup deploy commands list if not present
+ if 'deploy_commands' not in repo_config:
+ repo_config['deploy_commands'] = []
+
+ # Check if any global pre deploy commands is specified
+ if len(self._config['global_deploy'][0]) is not 0:
+ repo_config['deploy_commands'].insert(0, self._config['global_deploy'][0])
+
+ # Check if any repo specific deploy command is specified
+ if 'deploy' in repo_config:
+ repo_config['deploy_commands'].append(repo_config['deploy'])
+
+ # Check if any global post deploy command is specified
+ if len(self._config['global_deploy'][1]) is not 0:
+ repo_config['deploy_commands'].append(self._config['global_deploy'][1])
+
# If a Bitbucket repository is configured using the https:// URL, a username is usually
# specified in the beginning of the URL. To be able to compare configured Bitbucket
# repositories with incoming web hook events, this username needs to be stripped away in a
@@ -496,29 +525,39 @@ class GitAutoDeploy(object):
if 'path' in repo_config:
repo_config['path'] = os.path.expanduser(repo_config['path'])
- if 'path' in repo_config:
- if not os.path.isdir(repo_config['path']):
+ return self._config
- logger.error("Directory %s not found" % repo_config['path'])
- GitWrapper.clone(url=repo_config['url'], branch=repo_config['branch'] if 'branch' in repo_config else None, path=repo_config['path'])
+ def clone_all_repos(self):
+ """Iterates over all configured repositories and clones them to their
+ configured paths."""
+ import os
+ import re
- if not os.path.isdir(repo_config['path']):
- logger.warning("Unable to clone %s branch of repository %s. So repo will not pull. Only deploy command will run(if it exist)" % (repo_config['branch'] if 'branch' in repo_config else "default", repo_config['url']))
- # sys.exit(2)
+ # Iterate over all configured repositories
+ for repo_config in self._config['repositories']:
+
+ # Only clone repositories with a configured path
+ if 'path' not in repo_config:
+ logger.info("Repository %s will not be cloned (no path configured)" % repo_config['url'])
+ continue
+
+ if os.path.isdir(repo_config['path']) and os.path.isdir(repo_config['path']+'/.git'):
+ logger.info("Repository %s already present" % repo_config['url'])
+ continue
- else:
- logger.info("Repository %s successfully cloned" % repo_config['url'])
- if not os.path.isdir(repo_config['path'] + '/.git'):
- logger.warning("Directory %s is not a Git repository. So repo will not pull. Only deploy command will run(if it exist)" % repo_config['path'])
- # sys.exit(2)
+ # Clone repository
+ GitWrapper.clone(url=repo_config['url'], branch=repo_config['branch'], path=repo_config['path'])
+
+ if os.path.isdir(repo_config['path']):
+ logger.info("Repository %s successfully cloned" % repo_config['url'])
else:
- logger.warning("'Path' was not found in config. So repo will not pull. Only deploy command will run(if it exist)")
+ logger.error("Unable to clone %s branch of repository %s" % (repo_config['branch'], repo_config['url']))
- return self._config
def get_matching_repo_configs(self, urls):
- """Iterates over the various repo URLs provided as argument (git://, ssh:// and https:// for the repo) and
- compare them to any repo URL specified in the config"""
+ """Iterates over the various repo URLs provided as argument (git://,
+ ssh:// and https:// for the repo) and compare them to any repo URL
+ specified in the config"""
config = self.get_config()
configs = []
@@ -682,6 +721,9 @@ class GitAutoDeploy(object):
# Initialize base config
self.get_config()
+
+ # Clone all repos once initially
+ self.clone_all_repos()
if self.daemon:
logger.info('Starting Git Auto Deploy in daemon mode')
@@ -697,6 +739,8 @@ class GitAutoDeploy(object):
# Clear any existing lock files, with no regard to possible ongoing processes
for repo_config in self.get_config()['repositories']:
+
+ # Do we have a physical repository?
if 'path' in repo_config:
Lock(os.path.join(repo_config['path'], 'status_running')).clear()
Lock(os.path.join(repo_config['path'], 'status_waiting')).clear()