diff options
author | Oliver Poignant <oliver@poignant.se> | 2017-01-08 17:15:58 +0100 |
---|---|---|
committer | Oliver Poignant <oliver@poignant.se> | 2017-01-08 17:15:58 +0100 |
commit | 465cb9263fb1ffc9ba2d4a912847322920180caa (patch) | |
tree | 59932075b5f6426088704abac7c53f8c476da2a4 | |
parent | 324c3518d4b98da5bb660c62fa1503c47139c088 (diff) | |
download | Git-Auto-Deploy-origin/master.zip Git-Auto-Deploy-origin/master.tar.gz Git-Auto-Deploy-origin/master.tar.bz2 |
RefactoringHEADorigin/masterorigin/HEADmaster
-rw-r--r-- | gitautodeploy/__init__.py | 5 | ||||
-rw-r--r-- | gitautodeploy/cli/__init__.py | 1 | ||||
-rw-r--r-- | gitautodeploy/cli/config.py | 8 | ||||
-rw-r--r-- | gitautodeploy/events.py | 9 | ||||
-rw-r--r-- | gitautodeploy/gitautodeploy.py | 15 | ||||
-rw-r--r-- | gitautodeploy/httpserver.py | 43 | ||||
-rw-r--r-- | gitautodeploy/models/__init__.py | 1 | ||||
-rw-r--r-- | gitautodeploy/models/project.py (renamed from gitautodeploy/webhook.py) | 272 | ||||
-rw-r--r-- | gitautodeploy/parsers/__init__.py | 49 | ||||
-rw-r--r-- | gitautodeploy/parsers/base.py (renamed from gitautodeploy/parsers/common.py) | 5 | ||||
-rw-r--r-- | gitautodeploy/parsers/bitbucket.py | 7 | ||||
-rw-r--r-- | gitautodeploy/parsers/coding.py | 8 | ||||
-rw-r--r-- | gitautodeploy/parsers/generic.py | 7 | ||||
-rw-r--r-- | gitautodeploy/parsers/github.py | 7 | ||||
-rw-r--r-- | gitautodeploy/parsers/gitlab.py | 7 | ||||
-rw-r--r-- | gitautodeploy/parsers/gitlabci.py | 7 | ||||
-rw-r--r-- | test/test_parsers.py | 6 | ||||
-rw-r--r-- | test/utils.py | 9 | ||||
-rw-r--r-- | webui/src/Components/WebSocketStatus.scss | 2 | ||||
-rw-r--r-- | webui/src/Event.js | 3 |
20 files changed, 258 insertions, 213 deletions
diff --git a/gitautodeploy/__init__.py b/gitautodeploy/__init__.py index 8f762c3..81e2119 100644 --- a/gitautodeploy/__init__.py +++ b/gitautodeploy/__init__.py @@ -1,2 +1,5 @@ +from __future__ import absolute_import + from .gitautodeploy import * -from .cli import *
\ No newline at end of file +from .cli import * +from .parsers import * diff --git a/gitautodeploy/cli/__init__.py b/gitautodeploy/cli/__init__.py index 27c9ec6..ae8757c 100644 --- a/gitautodeploy/cli/__init__.py +++ b/gitautodeploy/cli/__init__.py @@ -1 +1,2 @@ from .config import * +from .models import * diff --git a/gitautodeploy/cli/config.py b/gitautodeploy/cli/config.py index 3af4e3d..5c5cd06 100644 --- a/gitautodeploy/cli/config.py +++ b/gitautodeploy/cli/config.py @@ -342,6 +342,7 @@ def init_config(config): import os import re import logging + from .models import Project logger = logging.getLogger() # Translate any ~ in the path into /home/<user> @@ -360,6 +361,8 @@ def init_config(config): if 'repositories' not in config: config['repositories'] = [] + deserialized = [] + for repo_config in config['repositories']: # Setup branch if missing @@ -425,6 +428,11 @@ def init_config(config): filter['pull_request'] = True + project = Project(repo_config) + deserialized.append(project) + + config['repositories'] = deserialized + return config diff --git a/gitautodeploy/events.py b/gitautodeploy/events.py index 5a4cef5..ab3cdec 100644 --- a/gitautodeploy/events.py +++ b/gitautodeploy/events.py @@ -97,8 +97,8 @@ class WebhookAction(SystemEvent): class DeployEvent(SystemEvent): - def __init__(self, repo_config): - self.repo_config = repo_config + def __init__(self, project): + self.project = project super(DeployEvent, self).__init__() def __repr__(self): @@ -106,12 +106,9 @@ class DeployEvent(SystemEvent): def dict_repr(self): data = super(DeployEvent, self).dict_repr() - data['name'] = self.get_name() + data['name'] = self.project.get_name() return data - def get_name(self): - return self.repo_config['url'].split('/')[-1].split('.git')[0] - class StartupEvent(SystemEvent): diff --git a/gitautodeploy/gitautodeploy.py b/gitautodeploy/gitautodeploy.py index 31e1696..eaca8b0 100644 --- a/gitautodeploy/gitautodeploy.py +++ b/gitautodeploy/gitautodeploy.py @@ -30,6 +30,7 @@ class GitAutoDeploy(object): _default_stderr = None _startup_event = None _ws_clients = [] + _http_port = None def __new__(cls, *args, **kwargs): """Overload constructor to enable singleton access""" @@ -260,7 +261,7 @@ class GitAutoDeploy(object): #if 'daemon-mode' not in self._config or not self._config['daemon-mode']: # self._startup_event.log_info('Git Auto Deploy started') - def serve_http(self): + def serve_http(self, serve_forever=True): """Starts a HTTP server that listens for webhook requests and serves the web ui.""" import sys import socket @@ -288,8 +289,8 @@ class GitAutoDeploy(object): # Setup SSL for HTTP server sa = self._http_server.socket.getsockname() - self._server_status['http-uri'] = "http://%s:%s" % (self._config['http-host'], self._config['http-port']) - + self._http_port = sa[1] + self._server_status['http-uri'] = "http://%s:%s" % (self._config['http-host'], sa[1]) self._startup_event.log_info("Listening for connections on %s" % self._server_status['http-uri']) self._startup_event.http_address = sa[0] self._startup_event.http_port = sa[1] @@ -299,17 +300,22 @@ class GitAutoDeploy(object): self._startup_event.log_critical("Unable to start HTTP server: %s" % e) return + if not serve_forever: + return + # Run forever try: self._http_server.serve_forever() except socket.error as e: + print e event = SystemEvent() self._event_store.register_action(event) event.log_critical("Error on socket: %s" % e) sys.exit(1) except KeyboardInterrupt as e: + print e event = SystemEvent() self._event_store.register_action(event) event.log_info('Requested close by keyboard interrupt signal') @@ -359,7 +365,8 @@ class GitAutoDeploy(object): server_side=True) sa = self._https_server.socket.getsockname() - self._server_status['https-uri'] = "https://%s:%s" % (self._config['https-host'], self._config['https-port']) + self._http_port = sa[1] + self._server_status['https-uri'] = "https://%s:%s" % (self._config['https-host'], sa[1]) self._startup_event.log_info("Listening for connections on %s" % self._server_status['https-uri']) self._startup_event.http_address = sa[0] diff --git a/gitautodeploy/httpserver.py b/gitautodeploy/httpserver.py index 857f5f3..4377078 100644 --- a/gitautodeploy/httpserver.py +++ b/gitautodeploy/httpserver.py @@ -1,6 +1,7 @@ from __future__ import absolute_import -from .webhook import WebhookRequestFilter, WebbhookRequestProcessor from .events import WebhookAction +from .parsers import get_service_handler + def WebhookRequestHandlerFactory(config, event_store, server_status, is_https=False): """Factory method for webhook request handler class""" @@ -119,10 +120,8 @@ def WebhookRequestHandlerFactory(config, event_store, server_status, is_https=Fa try: - request_processor = WebbhookRequestProcessor() - # Will raise a ValueError exception if it fails - ServiceRequestHandler = request_processor.get_service_handler(request_headers, request_body, action) + ServiceRequestHandler = get_service_handler(request_headers, request_body, action) # Unable to identify the source of the request if not ServiceRequestHandler: @@ -138,26 +137,32 @@ def WebhookRequestHandlerFactory(config, event_store, server_status, is_https=Fa action.log_info("Handling the request with %s" % ServiceRequestHandler.__name__) # Could be GitHubParser, GitLabParser or other - repo_configs = service_handler.get_repo_configs(request_headers, request_body, action) + projects = service_handler.get_matching_projects(request_headers, request_body, action) - action.log_info("%s candidates found" % len(repo_configs)) + action.log_info("%s candidates matches the request" % len(projects)) - request_filter = WebhookRequestFilter() + # request_filter = WebhookRequestFilter() - if len(repo_configs) == 0: + if len(projects) == 0: self.send_error(400, 'Bad request') test_case['expected']['status'] = 400 - action.log_error("No matching repository config") + action.log_error("No matching projects") action.set_waiting(False) action.set_success(False) return # Apply filters - repo_configs = request_filter.apply_filters(repo_configs, request_headers, request_body, action) + matching_projects = [] + for project in projects: + if project.apply_filters(request_headers, request_body, action): + matching_projects.append(project) + + # Only keep projects that matches + projects = matching_projects - action.log_info("%s candidates matches the filters" % len(repo_configs)) + action.log_info("%s candidates matches after applying filters" % len(projects)) - if not service_handler.validate_request(request_headers, repo_configs, action): + if not service_handler.validate_request(request_headers, projects, action): self.send_error(400, 'Bad request') test_case['expected']['status'] = 400 action.log_warning("Request is not valid") @@ -171,26 +176,26 @@ def WebhookRequestHandlerFactory(config, event_store, server_status, is_https=Fa self.send_header('Content-type', 'text/plain') self.end_headers() - if len(repo_configs) == 0: + if len(projects) == 0: action.set_waiting(False) action.set_success(False) return - action.log_info("Proceeding with %s candidates" % len(repo_configs)) + action.log_info("Proceeding with %s candidates" % len(projects)) action.set_waiting(False) action.set_success(True) - for repo_config in repo_configs: + for project in projects: # Schedule the execution of the webhook (git pull and trigger deploy etc) - thread = threading.Thread(target=request_processor.execute_webhook, args=[repo_config, self._event_store]) + thread = threading.Thread(target=project.execute_webhook, args=[self._event_store]) thread.start() # Add additional test case data test_case['config'] = { - 'url': 'url' in repo_config and repo_config['url'], - 'branch': 'branch' in repo_config and repo_config['branch'], - 'remote': 'remote' in repo_config and repo_config['remote'], + 'url': 'url' in project and project['url'], + 'branch': 'branch' in project and project['branch'], + 'remote': 'remote' in project and project['remote'], 'deploy': 'echo test!' } diff --git a/gitautodeploy/models/__init__.py b/gitautodeploy/models/__init__.py new file mode 100644 index 0000000..e2ebdf8 --- /dev/null +++ b/gitautodeploy/models/__init__.py @@ -0,0 +1 @@ +from .project import *
\ No newline at end of file diff --git a/gitautodeploy/webhook.py b/gitautodeploy/models/project.py index 752717e..954da99 100644 --- a/gitautodeploy/webhook.py +++ b/gitautodeploy/models/project.py @@ -1,75 +1,140 @@ -from .parsers import CodingRequestParser, GitLabCIRequestParser -from .parsers import GitLabRequestParser, GitHubRequestParser -from .parsers import BitBucketRequestParser, GenericRequestParser +import collections +from ..wrappers import GitWrapper +from ..lock import Lock +from ..wrappers import GitWrapper +from ..events import DeployEvent -class WebbhookRequestProcessor(object): +class Project(collections.MutableMapping): - def get_service_handler(self, request_headers, request_body, action): - """Parses the incoming request and attempts to determine whether - it originates from GitHub, GitLab or any other known service.""" - import json + """A dictionary that applies an arbitrary key-altering + function before accessing the keys""" - payload = json.loads(request_body) + def __init__(self, *args, **kwargs): + self.store = dict() + self.update(dict(*args, **kwargs)) # use the free update to set keys + + def __getitem__(self, key): + return self.store[self.__keytransform__(key)] + + def __setitem__(self, key, value): + self.store[self.__keytransform__(key)] = value + + def __delitem__(self, key): + del self.store[self.__keytransform__(key)] + + def __iter__(self): + return iter(self.store) + + def __len__(self): + return len(self.store) + + def __keytransform__(self, key): + return key + + def get_name(self): + return self['url'].split('/')[-1].split('.git')[0] + + def passes_payload_filter(self, payload, action): + + # At least one filter must match + for filter in self['payload-filter']: + + # All options specified in the filter must match + for filter_key, filter_value in filter.items(): + + # Ignore filters with value None (let them pass) + if filter_value == None: + continue + + # Interpret dots in filter name as path notations + node_value = payload + for node_key in filter_key.split('.'): + + # If the path is not valid the filter does not match + if not node_key in node_value: + action.log_info("Filter '%s' does not match since the path is invalid" % (filter_key)) + + # Filter does not match, do not process this repo config + return False + + node_value = node_value[node_key] + + if filter_value == node_value: + continue + + # If the filter value is set to True. the filter + # will pass regardless of the actual value + if filter_value == True: + continue + + action.log_debug("Filter '%s' does not match ('%s' != '%s')" % (filter_key, filter_value, (str(node_value)[:75] + '..') if len(str(node_value)) > 75 else str(node_value))) + + # Filter does not match, do not process this repo config + return False - if not isinstance(payload, dict): - raise ValueError("Invalid JSON object") + # Filter does match, proceed + return True - user_agent = 'user-agent' in request_headers and request_headers['user-agent'] - content_type = 'content-type' in request_headers and request_headers['content-type'] + def passes_header_filter(self, request_headers): - # Assume Coding if the X-Coding-Event HTTP header is set - if 'x-coding-event' in request_headers: - return CodingRequestParser + # At least one filter must match + for key in self['header-filter']: + + # Verify that the request has the required header attribute + if key.lower() not in request_headers: + return False + + # "True" indicates that any header value is accepted + if self['header-filter'][key] is True: + continue - # Assume GitLab if the X-Gitlab-Event HTTP header is set - elif 'x-gitlab-event' in request_headers: + # Verify that the request has the required header value + if self['header-filter'][key] != request_headers[key.lower()]: + return False - # Special Case for Gitlab CI - if content_type == "application/json" and "build_status" in payload: - return GitLabCIRequestParser - else: - return GitLabRequestParser + # Filter does match, proceed + return True - # Assume GitHub if the X-GitHub-Event HTTP header is set - elif 'x-github-event' in request_headers: + def apply_filters(self, request_headers, request_body, action): + """Verify that the suggested repositories has matching settings and + issue git pull and/or deploy commands.""" + import os + import time + import json - return GitHubRequestParser + payload = json.loads(request_body) - # Assume BitBucket if the User-Agent HTTP header is set to - # 'Bitbucket-Webhooks/2.0' (or something similar) - elif user_agent and user_agent.lower().find('bitbucket') != -1: + # Verify that all payload filters matches the request (if any payload filters are specified) + if 'payload-filter' in self and not self.passes_payload_filter(payload, action): - return BitBucketRequestParser + # Filter does not match, do not process this repo config + return False - # This handles old GitLab requests and Gogs requests for example. - elif content_type == "application/json": + # Verify that all header filters matches the request (if any header filters are specified) + if 'header-filter' in self and not self.passes_header_filter(request_headers): - action.log_info("Received event from unknown origin.") - return GenericRequestParser + # Filter does not match, do not process this repo config + return False - action.log_error("Unable to recognize request origin. Don't know how to handle the request.") - return + return True - def execute_webhook(self, repo_config, event_store): + def execute_webhook(self, event_store): """Verify that the suggested repositories has matching settings and issue git pull and/or deploy commands.""" import os import time - from .wrappers import GitWrapper - from .events import DeployEvent - from .lock import Lock import json - event = DeployEvent(repo_config) + event = DeployEvent(self) event_store.register_action(event) event.set_waiting(True) event.log_info("Running deploy commands") # In case there is no path configured for the repository, no pull will # be made. - if 'path' not in repo_config: - res = GitWrapper.deploy(repo_config) + if 'path' not in self: + res = GitWrapper.deploy(self) event.log_info("%s" % res) event.set_waiting(False) event.set_success(True) @@ -77,22 +142,22 @@ class WebbhookRequestProcessor(object): # If the path does not exist, a warning will be raised and no pull or # deploy will be made. - if not os.path.isdir(repo_config['path']): - event.log_error("The repository '%s' does not exist locally. Make sure it was pulled properly without errors by reviewing the log." % repo_config['path']) + if not os.path.isdir(self['path']): + event.log_error("The repository '%s' does not exist locally. Make sure it was pulled properly without errors by reviewing the log." % self['path']) event.set_waiting(False) event.set_success(False) return # If the path is not writable, a warning will be raised and no pull or # deploy will be made. - if not os.access(repo_config['path'], os.W_OK): - event.log_error("The path '%s' is not writable. Make sure that GAD has write access to that path." % repo_config['path']) + if not os.access(self['path'], os.W_OK): + event.log_error("The path '%s' is not writable. Make sure that GAD has write access to that path." % self['path']) event.set_waiting(False) event.set_success(False) return - running_lock = Lock(os.path.join(repo_config['path'], 'status_running')) - waiting_lock = Lock(os.path.join(repo_config['path'], 'status_waiting')) + running_lock = Lock(os.path.join(self['path'], 'status_running')) + waiting_lock = Lock(os.path.join(self['path'], 'status_waiting')) try: # Attempt to obtain the status_running lock @@ -113,7 +178,7 @@ class WebbhookRequestProcessor(object): while n > 0: # Attempt to pull up a maximum of 4 times - res = GitWrapper.pull(repo_config) + res = GitWrapper.pull(self) # Return code indicating success? if res == 0: @@ -122,10 +187,10 @@ class WebbhookRequestProcessor(object): n -= 1 if 0 < n: - res = GitWrapper.deploy(repo_config) + res = GitWrapper.deploy(self) #except Exception as e: - # 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' % self['path']) # logger.error(e) # raise e @@ -143,106 +208,3 @@ class WebbhookRequestProcessor(object): event.set_waiting(False) event.set_success(True) - -class WebhookRequestFilter(object): - - def passes_payload_filter(self, payload_filters, payload, action): - import logging - - logger = logging.getLogger() - - # At least one filter must match - for filter in payload_filters: - - # All options specified in the filter must match - for filter_key, filter_value in filter.items(): - - # Ignore filters with value None (let them pass) - if filter_value == None: - continue - - # Interpret dots in filter name as path notations - node_value = payload - for node_key in filter_key.split('.'): - - # If the path is not valid the filter does not match - if not node_key in node_value: - action.log_info("Filter '%s' does not match since the path is invalid" % (filter_key)) - - # Filter does not match, do not process this repo config - return False - - node_value = node_value[node_key] - - if filter_value == node_value: - continue - - # If the filter value is set to True. the filter - # will pass regardless of the actual value - if filter_value == True: - continue - - action.log_debug("Filter '%s' does not match ('%s' != '%s')" % (filter_key, filter_value, (str(node_value)[:75] + '..') if len(str(node_value)) > 75 else str(node_value))) - - # Filter does not match, do not process this repo config - return False - - # Filter does match, proceed - return True - - def passes_header_filter(self, header_filter, request_headers): - import logging - - logger = logging.getLogger() - - # At least one filter must match - for key in header_filter: - - # Verify that the request has the required header attribute - if key.lower() not in request_headers: - return False - - # "True" indicates that any header value is accepted - if header_filter[key] is True: - continue - - # Verify that the request has the required header value - if header_filter[key] != request_headers[key.lower()]: - return False - - # Filter does match, proceed - return True - - def apply_filters(self, repo_configs, request_headers, request_body, action): - """Verify that the suggested repositories has matching settings and - issue git pull and/or deploy commands.""" - import os - import time - import logging - from .wrappers import GitWrapper - from .lock import Lock - import json - - logger = logging.getLogger() - payload = json.loads(request_body) - - matches = [] - - # Process each matching repository - for repo_config in repo_configs: - - # Verify that all payload filters matches the request (if any payload filters are specified) - if 'payload-filter' in repo_config and not self.passes_payload_filter(repo_config['payload-filter'], payload, action): - - # Filter does not match, do not process this repo config - continue - - # Verify that all header filters matches the request (if any header filters are specified) - if 'header-filter' in repo_config and not self.passes_header_filter(repo_config['header-filter'], request_headers): - - # Filter does not match, do not process this repo config - continue - - matches.append(repo_config) - - return matches
\ No newline at end of file diff --git a/gitautodeploy/parsers/__init__.py b/gitautodeploy/parsers/__init__.py index cecd1c7..f213339 100644 --- a/gitautodeploy/parsers/__init__.py +++ b/gitautodeploy/parsers/__init__.py @@ -3,4 +3,51 @@ from .github import GitHubRequestParser from .gitlab import GitLabRequestParser from .gitlabci import GitLabCIRequestParser from .generic import GenericRequestParser -from .coding import CodingRequestParser
\ No newline at end of file +from .coding import CodingRequestParser + + +def get_service_handler(request_headers, request_body, action): + """Parses the incoming request and attempts to determine whether + it originates from GitHub, GitLab or any other known service.""" + import json + + payload = json.loads(request_body) + + if not isinstance(payload, dict): + raise ValueError("Invalid JSON object") + + user_agent = 'user-agent' in request_headers and request_headers['user-agent'] + content_type = 'content-type' in request_headers and request_headers['content-type'] + + # Assume Coding if the X-Coding-Event HTTP header is set + if 'x-coding-event' in request_headers: + return CodingRequestParser + + # Assume GitLab if the X-Gitlab-Event HTTP header is set + elif 'x-gitlab-event' in request_headers: + + # Special Case for Gitlab CI + if content_type == "application/json" and "build_status" in payload: + return GitLabCIRequestParser + else: + return GitLabRequestParser + + # Assume GitHub if the X-GitHub-Event HTTP header is set + elif 'x-github-event' in request_headers: + + return GitHubRequestParser + + # Assume BitBucket if the User-Agent HTTP header is set to + # 'Bitbucket-Webhooks/2.0' (or something similar) + elif user_agent and user_agent.lower().find('bitbucket') != -1: + + return BitBucketRequestParser + + # This handles old GitLab requests and Gogs requests for example. + elif content_type == "application/json": + + action.log_info("Received event from unknown origin.") + return GenericRequestParser + + action.log_error("Unable to recognize request origin. Don't know how to handle the request.") + return
\ No newline at end of file diff --git a/gitautodeploy/parsers/common.py b/gitautodeploy/parsers/base.py index b194062..f641d4c 100644 --- a/gitautodeploy/parsers/common.py +++ b/gitautodeploy/parsers/base.py @@ -1,5 +1,4 @@ - -class WebhookRequestParser(object): +class WebhookRequestParserBase(object): """Abstract parent class for git service parsers. Contains helper methods.""" @@ -27,4 +26,4 @@ class WebhookRequestParser(object): return configs def validate_request(self, request_headers, repo_configs, action): - return True
\ No newline at end of file + return True diff --git a/gitautodeploy/parsers/bitbucket.py b/gitautodeploy/parsers/bitbucket.py index b80f6aa..8905bfc 100644 --- a/gitautodeploy/parsers/bitbucket.py +++ b/gitautodeploy/parsers/bitbucket.py @@ -1,8 +1,9 @@ -from .common import WebhookRequestParser +from .base import WebhookRequestParserBase -class BitBucketRequestParser(WebhookRequestParser): - def get_repo_configs(self, request_headers, request_body, action): +class BitBucketRequestParser(WebhookRequestParserBase): + + def get_matching_projects(self, request_headers, request_body, action): import json data = json.loads(request_body) diff --git a/gitautodeploy/parsers/coding.py b/gitautodeploy/parsers/coding.py index 3d114d4..588ea22 100644 --- a/gitautodeploy/parsers/coding.py +++ b/gitautodeploy/parsers/coding.py @@ -1,8 +1,9 @@ -from .common import WebhookRequestParser +from .base import WebhookRequestParserBase -class CodingRequestParser(WebhookRequestParser): - def get_repo_configs(self, request_headers, request_body, action): +class CodingRequestParser(WebhookRequestParserBase): + + def get_matching_projects(self, request_headers, request_body, action): import json data = json.loads(request_body) @@ -35,6 +36,5 @@ class CodingRequestParser(WebhookRequestParser): return repo_configs - def verify_token(self, secret_token, request_token): return secret_token == request_token diff --git a/gitautodeploy/parsers/generic.py b/gitautodeploy/parsers/generic.py index c71bced..f8e8f31 100644 --- a/gitautodeploy/parsers/generic.py +++ b/gitautodeploy/parsers/generic.py @@ -1,8 +1,9 @@ -from .common import WebhookRequestParser +from .base import WebhookRequestParserBase -class GenericRequestParser(WebhookRequestParser): - def get_repo_configs(self, request_headers, request_body, action): +class GenericRequestParser(WebhookRequestParserBase): + + def get_matching_projects(self, request_headers, request_body, action): import json data = json.loads(request_body) diff --git a/gitautodeploy/parsers/github.py b/gitautodeploy/parsers/github.py index 5f2ba5d..a6659bd 100644 --- a/gitautodeploy/parsers/github.py +++ b/gitautodeploy/parsers/github.py @@ -1,8 +1,9 @@ -from .common import WebhookRequestParser +from .base import WebhookRequestParserBase -class GitHubRequestParser(WebhookRequestParser): - def get_repo_configs(self, request_headers, request_body, action): +class GitHubRequestParser(WebhookRequestParserBase): + + def get_matching_projects(self, request_headers, request_body, action): import json data = json.loads(request_body) diff --git a/gitautodeploy/parsers/gitlab.py b/gitautodeploy/parsers/gitlab.py index 6767907..6c6ca90 100644 --- a/gitautodeploy/parsers/gitlab.py +++ b/gitautodeploy/parsers/gitlab.py @@ -1,8 +1,9 @@ -from .common import WebhookRequestParser +from .base import WebhookRequestParserBase -class GitLabRequestParser(WebhookRequestParser): - def get_repo_configs(self, request_headers, request_body, action): +class GitLabRequestParser(WebhookRequestParserBase): + + def get_matching_projects(self, request_headers, request_body, action): import json data = json.loads(request_body) diff --git a/gitautodeploy/parsers/gitlabci.py b/gitautodeploy/parsers/gitlabci.py index eebf2bd..35d5ed4 100644 --- a/gitautodeploy/parsers/gitlabci.py +++ b/gitautodeploy/parsers/gitlabci.py @@ -1,8 +1,9 @@ -from .common import WebhookRequestParser +from .base import WebhookRequestParserBase -class GitLabCIRequestParser(WebhookRequestParser): - def get_repo_configs(self, request_headers, request_body, action): +class GitLabCIRequestParser(WebhookRequestParserBase): + + def get_matching_projects(self, request_headers, request_body, action): import json data = json.loads(request_body) diff --git a/test/test_parsers.py b/test/test_parsers.py index 420f9ff..7a30f2e 100644 --- a/test/test_parsers.py +++ b/test/test_parsers.py @@ -1,6 +1,7 @@ import unittest from utils import WebhookTestCaseBase + class WebhookTestCase(WebhookTestCaseBase): test_case = None @@ -19,7 +20,10 @@ class WebhookTestCase(WebhookTestCaseBase): # GAD configuration for this test case config = { - 'port': 0, + 'http-port': 0, + 'https-enabled': False, + 'wss-enabled': False, + 'web-ui-require-https': False, 'intercept-stdout': False, 'detailed-response': True, 'log-level': 'ERROR', diff --git a/test/utils.py b/test/utils.py index 30eeff6..551f809 100644 --- a/test/utils.py +++ b/test/utils.py @@ -48,7 +48,7 @@ class WebhookTestCaseBase(unittest.TestCase): for current_thread in threading.enumerate(): if current_thread == main_thread: continue - #print "Waiting for thread %s to finish" % current_thread + # print "Waiting for thread %s to finish" % current_thread current_thread.join() def tearDown(self): @@ -103,12 +103,15 @@ class GADRunnerThread(threading.Thread): self._app = GitAutoDeploy() self._app.setup(config) + # Setup HTTP server, but do not start serving + self._app.serve_http(serve_forever=False) + # Store PID and port in thread instance self.pid = self._app._pid - self.port = self._app._port + self.port = self._app._http_port def run(self): - self._app.handle_request() + self._app._http_server.handle_request() def exit(self): self._app.stop() diff --git a/webui/src/Components/WebSocketStatus.scss b/webui/src/Components/WebSocketStatus.scss index d287c72..8cb8997 100644 --- a/webui/src/Components/WebSocketStatus.scss +++ b/webui/src/Components/WebSocketStatus.scss @@ -2,7 +2,7 @@ .WebSocketStatus { - position: absolute; + position: fixed; bottom: 4rem; right: .3rem; z-index: 1010; diff --git a/webui/src/Event.js b/webui/src/Event.js index e5c8394..f5a2dd2 100644 --- a/webui/src/Event.js +++ b/webui/src/Event.js @@ -21,6 +21,9 @@ class Event { if(this.event.type === "WebhookAction") return "blue"; + if(this.event.type === "DeployEvent") + return "blue"; + return "blue"; // return "purple"; } |