diff --git a/.github/workflows/test-and-deploy.yml b/.github/workflows/test-and-deploy.yml index 0b024b27..dbc62c18 100644 --- a/.github/workflows/test-and-deploy.yml +++ b/.github/workflows/test-and-deploy.yml @@ -1,6 +1,6 @@ name: Test than deploy -on: +on: push: branches: [master] pull_request: @@ -24,7 +24,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install -r requirements.txt + pip install -r requirements.txt -r requirements-test.txt - name: Install JS/CSS dependencies run: npm install - name: Build JS/CSS with webpack @@ -51,7 +51,7 @@ jobs: fail_ci_if_error: true verbose: true if: matrix.python-version == 3.8 - + deploy: if: github.ref == 'refs/heads/master' runs-on: ubuntu-latest diff --git a/Dockerfile b/Dockerfile index e5e5de27..1e39be69 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,60 @@ -FROM node:current-alpine AS build_frontend +FROM node:16-alpine3.13 AS build-frontend WORKDIR /app -COPY package.json package-lock.json ./ -RUN npm ci -COPY webpack.config.js . -COPY frontend ./frontend -RUN npm run build +COPY package.json \ + package-lock.json \ + ./ +RUN npm clean-install +COPY webpack.config.js . +COPY frontend ./frontend +RUN npm run build -FROM python:alpine +FROM python:3.9-alpine3.13 AS runner WORKDIR /usr/src/app -ENV PYTHONDONTWRITEBYTECODE 1 -ENV PYTHONUNBUFFERED 1 - -RUN apk update && apk add postgresql-dev gcc python3-dev musl-dev libffi-dev zlib-dev jpeg-dev - -RUN pip install --upgrade pip -COPY requirements.txt . -RUN pip install -r requirements.txt -RUN pip install gunicorn - -COPY . . -COPY --from=build_frontend /app/static/dist static/dist - -RUN echo "import os" > wwwapp/local_settings.py -RUN echo "SECRET_KEY = os.environ['SECRET_KEY']" >> wwwapp/local_settings.py -RUN echo "ALLOWED_HOSTS = ['*']" >> wwwapp/local_settings.py -RUN echo "DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql_psycopg2', 'HOST': 'db', 'NAME': 'aplikacjawww', 'USER': 'app', 'PASSWORD': 'app'}}" >> wwwapp/local_settings.py -RUN echo "GOOGLE_ANALYTICS_KEY = None" >> wwwapp/local_settings.py -RUN echo "MEDIA_ROOT = os.environ['MEDIA_ROOT']" >> wwwapp/local_settings.py -RUN echo "SENDFILE_ROOT = os.environ['SENDFILE_ROOT']" >> wwwapp/local_settings.py -RUN echo "USE_X_FORWARDED_HOST = True" >> wwwapp/local_settings.py -RUN echo "SESSION_COOKIE_SECURE = False" >> wwwapp/local_settings.py -RUN echo "CSRF_COOKIE_SECURE = False" >> wwwapp/local_settings.py - -CMD gunicorn wwwapp.wsgi:application --bind 0.0.0.0:8000 -ENTRYPOINT ["./entrypoint.sh"] \ No newline at end of file + + +RUN apk update \ +&& apk add \ + cargo \ + gcc \ + jpeg-dev \ + libffi-dev \ + musl-dev \ + openssl-dev \ + postgresql-dev \ + python3-dev \ + zlib-dev \ +; + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +RUN pip install --upgrade pip setuptools +COPY requirements.txt . +RUN pip install gunicorn -r requirements.txt + +COPY --from=build-frontend \ + /app/static/dist \ + static/dist +COPY . . + +RUN echo "import os" >>wwwapp/local_settings.py \ +&& echo "DEBUG = True" >>wwwapp/local_settings.py \ +&& echo "SECRET_KEY = os.environ['SECRET_KEY']" >>wwwapp/local_settings.py \ +&& echo "ALLOWED_HOSTS = ['*']" >>wwwapp/local_settings.py \ +&& echo "class Anything: __contains__ = lambda *args: True" >>wwwapp/local_settings.py \ +&& echo "INTERNAL_IPS = Anything()" >>wwwapp/local_settings.py \ +&& echo "DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql_psycopg2', 'HOST': 'db', 'NAME': 'aplikacjawww', 'USER': 'app', 'PASSWORD': 'app'}}" >>wwwapp/local_settings.py \ +&& echo "GOOGLE_ANALYTICS_KEY = None" >>wwwapp/local_settings.py \ +&& echo "MEDIA_ROOT = os.environ['MEDIA_ROOT']" >>wwwapp/local_settings.py \ +&& echo "SENDFILE_ROOT = os.environ['SENDFILE_ROOT']" >>wwwapp/local_settings.py \ +&& echo "USE_X_FORWARDED_HOST = True" >>wwwapp/local_settings.py \ +&& echo "SESSION_COOKIE_SECURE = False" >>wwwapp/local_settings.py \ +&& echo "CSRF_COOKIE_SECURE = False" >>wwwapp/local_settings.py \ +; + + +EXPOSE 8000 +CMD ./entrypoint.sh diff --git a/README.md b/README.md index 9c4bdf6b..886b5be6 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Django-based application to manage registration of people for [scientific summer - `./manage.py populate_with_test_data` - script to populate the database with data for development ### Run: +- install postgresql - activate virtualenv (if not yet activated) - `pip install -r requirements.txt` - `./manage.py runserver` diff --git a/docker-compose.yml b/docker-compose.yml index 81d552a6..ba34f1a0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,14 +1,13 @@ version: '3.7' services: + django: build: . volumes: - static_volume:/usr/src/static - media_volume:/usr/src/media - uploads_volume:/usr/src/uploads - expose: - - 8000 environment: - DJANGO_SETTINGS_MODULE=wwwapp.settings_prod - MEDIA_ROOT=/usr/src/media @@ -20,6 +19,7 @@ services: - SOCIAL_AUTH_FACEBOOK_SECRET=${SOCIAL_AUTH_FACEBOOK_SECRET} depends_on: - db + db: image: postgres:alpine volumes: @@ -28,6 +28,7 @@ services: - POSTGRES_DB=aplikacjawww - POSTGRES_USER=app - POSTGRES_PASSWORD=app + nginx: image: nginx:alpine volumes: diff --git a/entrypoint.sh b/entrypoint.sh index 5fc54272..7c7e8c22 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,14 +1,26 @@ #!/bin/sh -echo "Collecting static files" +set -o pipefail -o nounset + + +echo >&2 "Collecting static files." rm -rf /usr/src/static/* -python manage.py collectstatic +python3 manage.py collectstatic -echo "Waiting for postgres..." +echo >&2 "Waiting for postgres..." while ! nc -z db 5432; do - sleep 0.1 + sleep 0.1 done -echo "PostgreSQL started" -python manage.py migrate +echo >&2 "PostgreSQL started." + +echo >&2 "Migrating database." +python3 manage.py migrate + +echo >&2 "Creating admin user (username: admin, password: admin)." +export DJANGO_SUPERUSER_EMAIL=admin@admin.admin +export DJANGO_SUPERUSER_PASSWORD=admin \ +export DJANGO_SUPERUSER_USERNAME=admin +# This will fail if admin user already exists. +python3 manage.py createsuperuser --noinput || true -exec "$@" \ No newline at end of file +exec gunicorn wwwapp.wsgi:application --bind 0.0.0.0:8000 diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 00000000..f124858b --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1,6 @@ +coverage==5.5 +django-coverage-plugin==1.8.0 +django-stubs==1.7.0 +freezegun==1.1.0 +mock==4.0.3 +mypy==0.812 diff --git a/requirements.txt b/requirements.txt index 3c17050f..02fac19b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,23 +1,15 @@ -Django==3.1.8 -django-crispy-forms==1.11.1 -django-tinymce==3.2.0 +django-admin-sortable2==0.7.8 django-bleach==0.6.1 django-cleanup==5.1.0 -django-sendfile2==0.6.0 +django-crispy-forms==1.11.1 django-debug-toolbar==3.2 -django-select2==7.6.2 -social-auth-app-django==4.0.0 -django-admin-sortable2==0.7.8 django-imagekit==4.0.2 -Pillow==8.1.2 -python-dateutil==2.8.1 +django-select2==7.6.2 +django-sendfile2==0.6.0 +django-tinymce==3.2.0 +Django==3.1.8 Faker==6.6.2 +Pillow==8.1.2 psycopg2==2.8.6 - -mock==4.0.3 -freezegun==1.1.0 -coverage==5.5 -django-coverage-plugin==1.8.0 - -mypy==0.812 -django-stubs==1.7.0 +python-dateutil==2.8.1 +social-auth-app-django==4.0.0