aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Gareth Coles <[email protected]>2018-02-08 16:01:20 +0000
committerGravatar Gareth Coles <[email protected]>2018-02-08 16:01:20 +0000
commit428eb9a6afb85fca51e87f6d16a1044a5fa24bf8 (patch)
treeee991943fd2bb05a574d8ae035fb6fc5be3f8c52
parentPffft (diff)
parentTravis deploy on master (#5) (diff)
Merge remote-tracking branch 'origin/master'
-rw-r--r--.travis.yml4
-rw-r--r--deploy.py21
-rw-r--r--gunicorn_config.py46
-rw-r--r--pysite/base_route.py22
-rw-r--r--pysite/route_manager.py59
-rw-r--r--pysite/views/healthcheck.py7
-rw-r--r--pysite/views/index.py6
-rw-r--r--pysite/views/invite.py7
-rw-r--r--requirements-ci.txt17
-rw-r--r--requirements.txt3
-rw-r--r--static/favicon.icobin0 -> 28957 bytes
-rw-r--r--static/logos/logo_banner.pngbin0 -> 54554 bytes
-rw-r--r--templates/.gitkeep0
-rw-r--r--templates/base.html17
-rw-r--r--templates/index.html9
-rw-r--r--templates/navigation.html19
16 files changed, 208 insertions, 29 deletions
diff --git a/.travis.yml b/.travis.yml
index 90ae14fd..30032dfe 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,11 +1,11 @@
language: python
python:
- "3.6"
-
+
install:
- pip install -r requirements.txt
- pip install -r requirements-ci.txt
script:
- snekchek
after_success:
- "curl $AUTODEPLOY_WEBHOOK -H \"token: $AUTODEPLOY_TOKEN\"" \ No newline at end of file
+ - python deploy.py
diff --git a/deploy.py b/deploy.py
new file mode 100644
index 00000000..189b5f0c
--- /dev/null
+++ b/deploy.py
@@ -0,0 +1,21 @@
+import os
+
+import requests
+
+
+branch = os.environ.get("TRAVIS_BRANCH")
+url = os.environ.get("AUTODEPLOY_WEBHOOK")
+token = os.environ.get("AUTODEPLOY_TOKEN")
+
+PR = os.environ.get("TRAVIS_PULL_REQUEST")
+
+print('branch:', branch)
+print('is_pr:', PR)
+
+if branch == 'master' and PR == 'false':
+ print("deploying..")
+ result = requests.get(url=url, headers={'token': token})
+ print(result.text)
+
+else:
+ print("skipping deploy")
diff --git a/gunicorn_config.py b/gunicorn_config.py
new file mode 100644
index 00000000..34d9fa55
--- /dev/null
+++ b/gunicorn_config.py
@@ -0,0 +1,46 @@
+def when_ready(server):
+ """ server hook that only runs when the gunicorn master process loads """
+
+ import os
+ import traceback
+ import rethinkdb as r
+
+ try:
+ server.log.info("rethinkdb initialising")
+
+ DB_HOST = os.environ.get("RETHINKDB_HOST")
+ DB_PORT = os.environ.get("RETHINKDB_PORT")
+ DB_DATABASE = os.environ.get("RETHINKDB_DATABASE")
+ DB_TABLE = os.environ.get("RETHINKDB_TABLE")
+ indexes = ['test']
+
+ conn = r.connect(host=DB_HOST, port=DB_PORT, db=DB_DATABASE)
+
+ # Check if database exists, if not create it
+ db_exists = r.db_list().contains(DB_DATABASE).run(conn)
+
+ if not db_exists:
+ server.log.info('adding database {0}'.format(DB_DATABASE))
+ r.db_create(DB_DATABASE).run(conn)
+
+ # Check if table exist, if not create it
+ table_exists = r.db(DB_DATABASE).table_list().contains(DB_TABLE).run(conn)
+
+ if not table_exists:
+ server.log.info('adding table {0}'.format(DB_TABLE))
+ r.db(DB_DATABASE).table_create(DB_TABLE).run(conn)
+
+ # Check if index exists if not add it
+ rtable = r.db(DB_DATABASE).table(DB_TABLE)
+ current_indexes = rtable.index_list().run(conn)
+
+ for index in indexes:
+ if index not in current_indexes:
+ server.log.info('adding index {0}'.format(index))
+ rtable.index_create(index).run(conn)
+
+ server.log.info("rethinkdb ready")
+
+ except Exception as e:
+ server.log.error(traceback.format_exc())
+ server.log.error("rethinkdb failed to initialise")
diff --git a/pysite/base_route.py b/pysite/base_route.py
index 4fdad857..916e7fae 100644
--- a/pysite/base_route.py
+++ b/pysite/base_route.py
@@ -1,23 +1,31 @@
# coding=utf-8
-from flask import Flask
+from flask import Flask, render_template
from flask.views import MethodView
class BaseView(MethodView):
- path = None #: str
- name = None #: str
+ name = None # type: str
+
+ def render(self, *template_names, **context):
+ context["current_page"] = self.name
+ context["view"] = self
+
+ return render_template(template_names, **context)
+
+
+class RouteView(BaseView):
+ path = None # type: str
@classmethod
- def setup(cls: "BaseView", app: Flask):
+ def setup(cls: "RouteView", app: Flask):
if not cls.path or not cls.name:
raise RuntimeError("Route views must have both `path` and `name` defined")
app.add_url_rule(cls.path, view_func=cls.as_view(cls.name))
-class ErrorView(MethodView):
- name = None #: str
- error_code = None #: int
+class ErrorView(BaseView):
+ error_code = None # type: int
@classmethod
def setup(cls: "ErrorView", app: Flask):
diff --git a/pysite/route_manager.py b/pysite/route_manager.py
index 5fe22ba0..09202d0c 100644
--- a/pysite/route_manager.py
+++ b/pysite/route_manager.py
@@ -3,20 +3,35 @@ import importlib
import inspect
import os
-from flask import Flask
+from flask import Flask, abort, g
from pysite.base_route import BaseView, ErrorView
+import rethinkdb
+
+from pysite.base_route import BaseView, ErrorView, RouteView
+
+DB_HOST = os.environ.get("RETHINKDB_HOST")
+DB_PORT = os.environ.get("RETHINKDB_PORT")
+DB_DATABASE = os.environ.get("RETHINKDB_DATABASE")
+DB_TABLE = os.environ.get("RETHINKDB_TABLE")
+
+TEMPLATES_PATH = "../templates"
+STATIC_PATH = "../static"
class RouteManager:
def __init__(self):
- self.app = Flask(__name__)
+ self.app = Flask(
+ __name__, template_folder=TEMPLATES_PATH, static_folder=STATIC_PATH, static_url_path="/static",
+ )
self.app.secret_key = os.environ.get("WEBPAGE_SECRET_KEY")
self.load_views()
def run(self):
- self.app.run(port=int(os.environ.get("WEBPAGE_PORT")), debug=False)
+ self.app.run(
+ port=int(os.environ.get("WEBPAGE_PORT")), debug="FLASK_DEBUG" in os.environ
+ )
def load_views(self, location="pysite/views"):
for filename in os.listdir(location):
@@ -33,7 +48,43 @@ class RouteManager:
inspect.isclass(cls) and
cls is not BaseView and
cls is not ErrorView and
- (BaseView in cls.__mro__ or ErrorView in cls.__mro__)
+ cls is not RouteView and
+ BaseView in cls.__mro__
):
cls.setup(self.app)
print(f"View loaded: {cls.name: <25} ({module.__name__}.{cls_name})")
+
+ def setup_db(self):
+ connection = self.get_db_connection(connect_database=False)
+
+ try:
+ rethinkdb.db_create(DB_DATABASE).run(connection)
+ rethinkdb.db(DB_DATABASE).table_create(DB_TABLE).run(connection)
+ print("Database created")
+ except rethinkdb.RqlRuntimeError:
+ print("Database found")
+ finally:
+ connection.close()
+
+ self.app.before_request(self.db_before_request)
+ self.app.teardown_request(self.db_teardown_request)
+
+ def get_db_connection(self, connect_database=True):
+ if connect_database:
+ return rethinkdb.connect(host=DB_HOST, port=DB_PORT, db=DB_DATABASE)
+ else:
+ return rethinkdb.connect(host=DB_HOST, port=DB_PORT)
+
+ def db_before_request(self):
+ try:
+ # g is the Flask global context object
+ g.rdb_conn = self.get_db_connection()
+ except rethinkdb.RqlDriverError:
+ abort(503, "Database connection could be established.")
+
+ def db_teardown_request(self, _):
+ try:
+ # g is the Flask global context object
+ g.rdb_conn.close()
+ except AttributeError:
+ pass
diff --git a/pysite/views/healthcheck.py b/pysite/views/healthcheck.py
index 3931100c..088bc7b3 100644
--- a/pysite/views/healthcheck.py
+++ b/pysite/views/healthcheck.py
@@ -1,10 +1,13 @@
# coding=utf-8
from flask import jsonify
-from pysite.base_route import BaseView
+from pysite.base_route import RouteView
-class IndexView(BaseView):
+__author__ = "Gareth Coles"
+
+
+class IndexView(RouteView):
path = "/healthcheck"
name = "healthcheck"
diff --git a/pysite/views/index.py b/pysite/views/index.py
index 48a98fac..0c2d1578 100644
--- a/pysite/views/index.py
+++ b/pysite/views/index.py
@@ -1,10 +1,10 @@
# coding=utf-8
-from pysite.base_route import BaseView
+from pysite.base_route import RouteView
-class IndexView(BaseView):
+class IndexView(RouteView):
path = "/"
name = "index"
def get(self):
- return "Coming soon:tm:"
+ return self.render("index.html")
diff --git a/pysite/views/invite.py b/pysite/views/invite.py
index 65cd75a5..07ddc830 100644
--- a/pysite/views/invite.py
+++ b/pysite/views/invite.py
@@ -1,10 +1,13 @@
# coding=utf-8
from flask import redirect
-from pysite.base_route import BaseView
+from pysite.base_route import RouteView
-class InviteView(BaseView):
+__author__ = "Gareth Coles"
+
+
+class InviteView(RouteView):
path = "/invite"
name = "invite"
diff --git a/requirements-ci.txt b/requirements-ci.txt
index 04e3aabe..50d0f297 100644
--- a/requirements-ci.txt
+++ b/requirements-ci.txt
@@ -1,9 +1,10 @@
-snekchek
-flake8
-flake8-bugbear
-flake8-bandit
-flake8-import-order
-flake8-tidy-imports
-flake8-string-format
-safety
+snekchek
+flake8
+flake8-bugbear
+flake8-bandit
+flake8-import-order
+flake8-tidy-imports
+flake8-string-format
+safety
dodgy
+requests
diff --git a/requirements.txt b/requirements.txt
index 69ca547f..e6a3877f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,2 @@
-flask==0.12.2 \ No newline at end of file
+flask==0.12.2
+rethinkdb
diff --git a/static/favicon.ico b/static/favicon.ico
new file mode 100644
index 00000000..046480bf
--- /dev/null
+++ b/static/favicon.ico
Binary files differ
diff --git a/static/logos/logo_banner.png b/static/logos/logo_banner.png
new file mode 100644
index 00000000..3036fb19
--- /dev/null
+++ b/static/logos/logo_banner.png
Binary files differ
diff --git a/templates/.gitkeep b/templates/.gitkeep
deleted file mode 100644
index e69de29b..00000000
--- a/templates/.gitkeep
+++ /dev/null
diff --git a/templates/base.html b/templates/base.html
new file mode 100644
index 00000000..9e00af20
--- /dev/null
+++ b/templates/base.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ {% block head %}
+ <title>Python | {% block title %}{% endblock %}</title>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>
+ <script defer src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.39/js/uikit.min.js"></script>
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.0.0-beta.39/css/uikit.min.css" />
+ {% endblock %}
+</head>
+<body>
+{% include "navigation.html" %}
+{% block content %}{% endblock %}
+</body>
+</html> \ No newline at end of file
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 00000000..418347d2
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+{% block title %}Home{% endblock %}
+{% block content %}
+ <div class="uk-container uk-section">
+ <h1 class="uk-title uk-text-center">
+ Coming soon :tm:
+ </h1>
+ </div>
+{% endblock %} \ No newline at end of file
diff --git a/templates/navigation.html b/templates/navigation.html
new file mode 100644
index 00000000..cbd6a36a
--- /dev/null
+++ b/templates/navigation.html
@@ -0,0 +1,19 @@
+<div class="uk-container uk-container-expand uk-section-secondary">
+ <nav data-uk-navbar class="uk-navbar-container uk-navbar-transparent">
+ <div class="uk-navbar-left">
+ <a href="/" class="uk-navbar-item uk-logo">
+ <img src="/static/logos/logo_banner.png" style="height: 50px;"/>
+ </a>
+ </div>
+ <div class="uk-navbar-right">
+ <ul class="uk-navbar-nav">
+ {% if current_page == "index" %}
+ <li class="uk-active"><a href="/"><i class="uk-icon fas fa-home"></i> &nbsp;Home</a></li>
+ {% else %}
+ <li><a href="/"><i class="uk-icon fas fa-home"></i> &nbsp;Home</a></li>
+ {% endif %}
+ <li><a href="/invite"><i class="uk-icon fab fa-discord"></i> &nbsp;Discord</a></li>
+ </ul>
+ </div>
+ </nav>
+</div> \ No newline at end of file