diff --git a/.travis.yml b/.travis.yml index 0adf597..f6e8bb7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,15 @@ -language: python -python: - - "3.5" +language: generic +sudo: required +services: + - docker before_script: - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter - chmod +x ./cc-test-reporter - ./cc-test-reporter before-build script: - - flake8 api_graphql app data_models - - yapf -pdr api_graphql app data_models -e '**/migrations' -e '**/snapshots' - - isort -c -rc api_graphql app data_models - - py.test --cov-report=xml + - docker-compose run test after_script: - - ./cc-test-reporter after-build + - docker-compose run test ./cc-test-reporter after-build env: global: - GIT_COMMITTED_AT=$(if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then git log -1 --pretty=format:%ct; else git log -1 --skip 1 --pretty=format:%ct; fi) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..11df5f6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,48 @@ +# Base +FROM alpine:3.7 as base + +WORKDIR /srv/app + +RUN apk add --update --no-cache git gcc libc-dev python3 python3-dev jpeg-dev zlib-dev +ENV LIBRARY_PATH=/lib:/usr/lib + +COPY requirements.txt . +RUN pip3 install --no-cache-dir wheel && pip3 wheel -r requirements.txt --wheel-dir=/srv/wheels + + +# Development +FROM alpine:3.7 as dev + +WORKDIR /srv/app +RUN apk add --update --no-cache python3 git jpeg zlib +COPY --from=base /srv/wheels /srv/wheels +COPY requirements.txt . +RUN pip3 install --no-index --no-cache-dir --find-links=/srv/wheels -r requirements.txt + +EXPOSE 8000 +CMD ["./docker/run_dev.sh"] + +# Testing +FROM alpine:3.7 as test + +WORKDIR /srv/app +RUN apk add --update --no-cache python3 git jpeg zlib +COPY --from=base /srv/wheels /srv/wheels +COPY requirements.txt . +COPY requirements-test.txt . +RUN pip3 install --no-index --no-cache-dir --find-links=/srv/wheels -r requirements.txt +RUN pip3 install --no-cache-dir -r requirements-test.txt + +CMD ["./docker/run_tests.sh"] + +# Production +FROM alpine:3.7 as production + +WORKDIR /srv/app +RUN apk add --update --no-cache python3 git jpeg zlib uwsgi-python3 +COPY --from=base /srv/wheels /srv/wheels +COPY requirements.txt . +RUN pip3 install --no-index --no-cache-dir --find-links=/srv/wheels -r requirements.txt + +EXPOSE 8000 +CMD ["./docker/run_production.sh"] diff --git a/README.md b/README.md index 7d85261..67da383 100644 --- a/README.md +++ b/README.md @@ -19,11 +19,27 @@ By default settings are configured for development and should just work, but som |REVOLT_SECRET_KEY|replace_this_secret_key|[See Django SECRET_KEY](https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-SECRET_KEY). **It is important that this is changed in production.** |REVOLT_RAVEN_DSN|(Empty)|Sentry DSN using this format: https://user:pass@sentry.io/project| +## Testing and linting + +The projects uses flake8, yapf, and isort to lint the project. + +The easiest way to run the tests is to use Docker: `docker-compose run test`. +Alternatively use the docker script: `./docker/run_tests.sh`. ## Setup - Development +### Docker + +To start the project using Docker run `docker-compose up dev` which runs on http://localhost:8000 +To update requirements run `docker-compose up --build dev`. +Migrations are automatically applied on start up. + +No further changes are needed to run the backend for development. + ### Virtualenv +To run the project without using Docker virtualenv is recommended. + ```bash pip install virtualenv virtualenv -p python3 venv @@ -56,6 +72,14 @@ python manage.py runserver ## Setup - Deployment +### Docker + +Docker can be used to run the backend in production. +It is configured to use uwsgi on port 800. +Staticfiles and mediafiles are served from local folders with the same name. + +Start the backend using `docker-compose up production`. + ### Nginx ```bash diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1f207e6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,46 @@ +version: '3.4' +services: + test: + build: + context: . + target: test + dockerfile: Dockerfile + volumes: + - .:/srv/app/ + environment: + - GIT_COMMITTED_AT + - CC_TEST_REPORTER_ID + dev: + build: + context: . + target: dev + dockerfile: Dockerfile + volumes: + - .:/srv/app/ + ports: + - "8000:8000" + environment: + - REVOLT_DEBUG + - REVOLT_ALLOWED_HOSTS + - REVOLT_STATIC_ROOT + - REVOLT_MEDIA_ROOT + - REVOLT_SECRET_KEY + - REVOLT_RAVEN_DSN + - DATABASE_URL + production: + build: + context: . + target: production + dockerfile: Dockerfile + volumes: + - .:/srv/app/ + ports: + - "8000:8000" + environment: + - REVOLT_DEBUG=false + - REVOLT_ALLOWED_HOSTS + - REVOLT_STATIC_ROOT + - REVOLT_MEDIA_ROOT + - REVOLT_SECRET_KEY + - REVOLT_RAVEN_DSN + - DATABASE_URL diff --git a/docker/run_dev.sh b/docker/run_dev.sh new file mode 100755 index 0000000..cef3595 --- /dev/null +++ b/docker/run_dev.sh @@ -0,0 +1,3 @@ +#!/bin/sh +python3 manage.py migrate +python3 manage.py runserver 0.0.0.0:8000 diff --git a/docker/run_production.sh b/docker/run_production.sh new file mode 100755 index 0000000..d5fa9ad --- /dev/null +++ b/docker/run_production.sh @@ -0,0 +1,4 @@ +#!/bin/sh +python3 manage.py migrate +python3 manage.py collectstatic --no-input +uwsgi -i uwsgi.ini diff --git a/docker/run_tests.sh b/docker/run_tests.sh new file mode 100755 index 0000000..78e6848 --- /dev/null +++ b/docker/run_tests.sh @@ -0,0 +1,5 @@ +#!/bin/sh +flake8 api_graphql app data_models +yapf -pdr api_graphql app data_models -e '**/migrations' -e '**/snapshots' +isort -c -rc api_graphql app data_models +py.test --cov-report=xml diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 0000000..ca5ee38 --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1,12 @@ +# Testing +pytest==3.4.1 +pytest-django==3.1.2 +snapshottest==0.5.0 + +# Coverage +pytest-cov==2.5.1 + +# Linting +yapf==0.20.2 +flake8==3.5.0 +isort==4.3.4 diff --git a/requirements.txt b/requirements.txt index b987eff..943d2bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,16 +20,3 @@ python-decouple==3.1 # Error reporting raven==6.5.0 - -# Testing -pytest==3.4.1 -pytest-django==3.1.2 -snapshottest==0.5.0 - -# Coverage -pytest-cov==2.5.1 - -# Linting -yapf==0.20.2 -flake8==3.5.0 -isort==4.3.4 diff --git a/uwsgi.ini b/uwsgi.ini new file mode 100644 index 0000000..4bb4090 --- /dev/null +++ b/uwsgi.ini @@ -0,0 +1,8 @@ +[uwsgi] +module = app.wsgi:application +vacuum = True +master = True +http-socket = :8000 +static-map = /static=./staticfiles +static-map = /media=./mediafiles +plugins = python3