Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
omardeleo committed Feb 27, 2021
0 parents commit 8c6413f
Show file tree
Hide file tree
Showing 55 changed files with 38,768 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
*node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

__pycache__
48 changes: 48 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
VOLUME=$(shell basename $(PWD))

develop: clean build migrations.upgrade run

clean:
docker-compose rm -vf

build:
docker-compose build

run:
docker-compose up

frontend-shell:
docker-compose run frontend \
sh

backend-shell:
docker-compose run worker \
sh

python-shell:
docker-compose run worker \
poetry run flask shell

postgres.data.delete: clean
docker volume rm $(VOLUME)_postgres

postgres.start:
docker-compose up -d postgres
docker-compose exec postgres \
sh -c 'while ! nc -z postgres 5432; do sleep 0.1; done'

migrations.blank: postgres.start
docker-compose run worker \
poetry run flask db revision

migrations.create: postgres.start
docker-compose run worker \
poetry run flask db migrate

migrations.upgrade: postgres.start
docker-compose run worker \
poetry run flask db upgrade

migrations.heads: postgres.start
docker-compose run worker \
poetry run flask db heads
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# The React + Flask Template · [![Version Badge](https://img.shields.io/badge/version-1.0.0-brightgreen)](#)

A React starter project with Flask backend that works with [Docker](https://www.docker.com), [Docker Compose](https://docs.docker.com/compose),
and [Shipyard](https://shipyard.build) out of the box.

## Includes

- [React](https://github.com/facebook/react) - JavaScript library for building user interfaces
- [Material-UI](https://github.com/mui-org/material-ui) - React components for faster and simpler web development
- [Flask](https://github.com/pallets/flask) - lightweight WSGI web application framework
- [Jinja](https://github.com/pallets/jinja) + [Bootstrap](https://pythonhosted.org/Flask-Bootstrap) (from CDN)
- [uWSGI](https://github.com/unbit/uwsgi) - entrypoint
- [Celery](https://github.com/celery/celery) (with example heartbeat task configured) - distributed task queue
- [Flask-SQLAlchemy](https://github.com/pallets/flask-sqlalchemy) - ORM toolkit
- [LocalStack](https://github.com/localstack/localstack) - fully functional local AWS cloud stack

## Dependencies

- [Docker](https://www.docker.com) & [Docker Compose](https://docs.docker.com/compose) - to build and run the app
- [Make](https://www.gnu.org/software/make/manual/make.html) - to easily run commands needed for development

## Getting Started

- Run `make develop` at the root of this project.
- Visit the app at http://localhost:3000.
- Visit http://localhost:8080/api/v1/files to list objects in LocalStack s3 bucket.
- Make your code changes! The app will reload whenever you save.
1 change: 1 addition & 0 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__
49 changes: 49 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FROM python:3.8-alpine3.13

WORKDIR /srv

# Install system dependencies for: uWSGI, poetry, watchman
RUN apk add --update --no-cache \
gcc \
libc-dev \
libffi-dev \
openssl-dev \
bash \
git \
libtool \
m4 \
g++ \
autoconf \
automake \
build-base \
postgresql-dev

# cryptography module incompatibility with PEP517
# https://github.com/pyca/cryptography/issues/5771
ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1

# Install poetry
RUN pip install poetry

# Create an app user, prepare permissions, and run as the user
RUN adduser -S app
RUN mkdir -p /var/run/celery && \
chown -R app /var/run/celery /srv
USER app

# Install Python dependencies
ADD pyproject.toml poetry.lock ./
RUN poetry install

# Add the project
# NOTE Run the install again to install the project
ADD src ./src
ADD migrations ./migrations
RUN poetry install

# Add system files
ADD filesystem /

# Set the default command
ENV FLASK_APP src/entry:flask_app
CMD /entrypoints/web.sh
4 changes: 4 additions & 0 deletions backend/filesystem/entrypoints/restart-worker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

CELERY_PID=$(cat /var/run/celery/worker.pid)
kill -HUP $CELERY_PID
11 changes: 11 additions & 0 deletions backend/filesystem/entrypoints/web.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

if [ ${DEV:-false} = 'true' ]; then
poetry run flask run --host 0.0.0.0 --port 8080
else
poetry run uwsgi -s /tmp/uwsgi.sock \
--manage-script-name \
--mount /=src/entry.py \
--callable flask_app \
--http 0.0.0.0:8080
fi
15 changes: 15 additions & 0 deletions backend/filesystem/entrypoints/worker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

if [ ${DEV:-False} = 'true' ]; then
# Run celery in the background
# NOTE: -B is for the heartbeat task scheduler
poetry run celery -B \
-A src.entry.celery worker \
--loglevel=info \
--pidfile=/var/run/celery/worker.pid
else
# Run celery in the foreground
poetry run celery -B \
-A src.entry.celery worker \
--loglevel=info
fi
1 change: 1 addition & 0 deletions backend/migrations/README
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Generic single-database configuration.
45 changes: 45 additions & 0 deletions backend/migrations/alembic.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# A generic, single database configuration.

[alembic]
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s

# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false


# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic

[handlers]
keys = console

[formatters]
keys = generic

[logger_root]
level = WARN
handlers = console
qualname =

[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine

[logger_alembic]
level = INFO
handlers =
qualname = alembic

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic

[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
87 changes: 87 additions & 0 deletions backend/migrations/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from __future__ import with_statement
from alembic import context
from sqlalchemy import engine_from_config, pool
from logging.config import fileConfig
import logging

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env')

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app
config.set_main_option('sqlalchemy.url',
current_app.config.get('SQLALCHEMY_DATABASE_URI'))
target_metadata = current_app.extensions['migrate'].db.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline():
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(url=url)

with context.begin_transaction():
context.run_migrations()


def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""

# this callback is used to prevent an auto-migration from being generated
# when there are no changes to the schema
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
def process_revision_directives(context, revision, directives):
if getattr(config.cmd_opts, 'autogenerate', False):
script = directives[0]
if script.upgrade_ops.is_empty():
directives[:] = []
logger.info('No changes in schema detected.')

engine = engine_from_config(config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=pool.NullPool)

connection = engine.connect()
context.configure(connection=connection,
target_metadata=target_metadata,
process_revision_directives=process_revision_directives,
**current_app.extensions['migrate'].configure_args)

try:
with context.begin_transaction():
context.run_migrations()
finally:
connection.close()

if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
25 changes: 25 additions & 0 deletions backend/migrations/script.py.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""${message}

Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}

"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
${imports if imports else ""}

# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}


def upgrade():
${upgrades if upgrades else "pass"}


def downgrade():
${downgrades if downgrades else "pass"}
35 changes: 35 additions & 0 deletions backend/migrations/versions/fb060a24643d_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Add Counter model
Revision ID: fb060a24643d
Revises:
Create Date: 2020-03-19 23:13:15.829771
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils


# revision identifiers, used by Alembic.
revision = 'fb060a24643d'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('counter',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=True),
sa.Column('count', sa.Integer(), nullable=False),
sa.Column('label', sa.String(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('counter')
# ### end Alembic commands ###
Loading

0 comments on commit 8c6413f

Please sign in to comment.