Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*/node_modules
*.sqlite*
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.vscode/
*.pyc
*.egg-info
*.sqlite*
backend/hgmo
4 changes: 2 additions & 2 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[settings]
known_first_party = code_review_bot,code_review_tools,code_review_events,conftest
known_third_party = influxdb,libmozdata,libmozevent,logbook,parsepatch,pytest,raven,requests,responses,setuptools,structlog,taskcluster,toml
known_first_party = code_review_backend,code_review_bot,code_review_tools,code_review_events,conftest
known_third_party = dj_database_url,django,influxdb,libmozdata,libmozevent,logbook,parsepatch,pytest,raven,requests,responses,setuptools,structlog,taskcluster,toml
force_single_line = True
default_section=FIRSTPARTY
line_length=159
91 changes: 91 additions & 0 deletions .taskcluster.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,26 @@ tasks:
owner: bastien@mozilla.com
source: https://github.com/mozilla/code-review

- taskId: {$eval: as_slugid("backend_check_tests")}
provisionerId: aws-provisioner-v1
workerType: github-worker
created: {$fromNow: ''}
deadline: {$fromNow: '1 hour'}
payload:
maxRunTime: 3600
image: python:3
command:
- sh
- -lxce
- "git clone --quiet ${repository} /src && cd /src && git checkout ${head_rev} -b checks &&
cd /src/backend && pip install -q . && pip install -q -r requirements-dev.txt &&
./manage.py test"
metadata:
name: "Code Review Backend checks: unit tests"
description: Check python code with Django tests
owner: bastien@mozilla.com
source: https://github.com/mozilla/code-review

- taskId: {$eval: as_slugid("frontend_build")}
provisionerId: aws-provisioner-v1
workerType: github-worker
Expand Down Expand Up @@ -205,6 +225,47 @@ tasks:
owner: bastien@mozilla.com
source: https://github.com/mozilla/code-review

- taskId: {$eval: as_slugid("backend_build")}
created: {$fromNow: ''}
deadline: {$fromNow: '1 hour'}
provisionerId: aws-provisioner-v1
workerType: releng-svc
dependencies:
- {$eval: as_slugid("check_lint")}
- {$eval: as_slugid("backend_check_tests")}
payload:
capabilities:
privileged: true
maxRunTime: 3600
image: "${taskboot_image}"
env:
GIT_REPOSITORY: ${repository}
GIT_REVISION: ${head_rev}
command:
- taskboot
- build
- --image
- mozilla/code-review
- --tag
- "${channel}"
- --tag
- "${head_rev}"
- --write
- /backend.tar
- backend/Dockerfile
artifacts:
public/code-review-backend.tar:
expires: {$fromNow: '2 weeks'}
path: /backend.tar
type: file
scopes:
- docker-worker:capability:privileged
metadata:
name: Code Review Backend docker build
description: Build docker image of code review backend
owner: bastien@mozilla.com
source: https://github.com/mozilla/code-review

- $if: 'channel in ["testing", "production"]'
then:
taskId: {$eval: as_slugid("frontend_deploy")}
Expand Down Expand Up @@ -326,3 +387,33 @@ tasks:
description: Deploy docker image on Heroku
owner: bastien@mozilla.com
source: https://github.com/mozilla/code-review

- $if: 'channel in ["testing", "production"]'
then:
taskId: {$eval: as_slugid("backend_deploy")}
created: {$fromNow: ''}
deadline: {$fromNow: '1 hour'}
provisionerId: aws-provisioner-v1
workerType: github-worker
dependencies:
- {$eval: as_slugid("backend_build")}
payload:
features:
taskclusterProxy: true
maxRunTime: 3600
image: "${taskboot_image}"
command:
- taskboot
- deploy-heroku
- --heroku-app
- "code-review-backend-${channel}"
- web:public/code-review-backend.tar
env:
TASKCLUSTER_SECRET: "project/relman/code-review/deploy-${channel}"
scopes:
- "secrets:get:project/relman/code-review/deploy-${channel}"
metadata:
name: "Code Review Backend deployment (${channel})"
description: Deploy docker image on Heroku
owner: bastien@mozilla.com
source: https://github.com/mozilla/code-review
15 changes: 15 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM python:3.7-slim

ADD backend /src/backend

WORKDIR /src/backend

# Activate Django settings for in docker image
ENV DJANGO_DOCKER=true

RUN pip install --no-cache-dir .

# Collect all static files
RUN ./manage.py collectstatic --no-input

CMD gunicorn code_review_backend.app.wsgi
14 changes: 14 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Code Review Backend

## Developer setup

```
mkvirtualenv -p /usr/bin/python3 code-review-backend
cd backend
pip install -r requirements.txt
./manage.py migrate
./manage.py createsuperuser
./manage.py runserver
```

At this point, you can log into http://127.0.0.1:8000/admin/ with the credentials you mentioned during the `createsuperuser` step.
1 change: 1 addition & 0 deletions backend/VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.4
Empty file.
Empty file.
179 changes: 179 additions & 0 deletions backend/code_review_backend/app/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# -*- coding: utf-8 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
Django settings for backend project.

Generated by 'django-admin startproject' using Django 2.2.6.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import logging
import os

import dj_database_url

logger = logging.getLogger(__name__)

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ROOT_DIR = os.path.dirname(BASE_DIR)


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "t!+s!@x5p!85x19q83jufr#95_z0fv7$!u5z*c&gi!%hr3^w+r"

# Only use DEBUG mode for local development
# When running on Heroku, we disable that mode (see end of file & DYNO mode)
DEBUG = True
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment here to explain that, for production, this is overwritten in the Heroku section at the end of the file?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added that line to load DRF

]

MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "code_review_backend.app.urls"

TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
]
},
}
]

WSGI_APPLICATION = "code_review_backend.app.wsgi.application"


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(ROOT_DIR, "db.sqlite3"),
}
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
},
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_L10N = True

USE_TZ = True

# API configuration
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticatedOrReadOnly"
],
# Setup pagination
"PAGE_SIZE": 50,
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
}
Comment on lines +123 to +133
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config for the API (could be in #162)



# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = "/static/"

# Static files are set in a dedicated path in Docker image
if "DJANGO_DOCKER" in os.environ:
STATIC_ROOT = "/static"

# Enable GZip and cache, and build a manifest during collectstatic
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"


# Internal logging setup
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {"console": {"class": "logging.StreamHandler"}},
"loggers": {
"django": {"handlers": ["console"], "level": "INFO"},
"code_review_backend": {"handlers": ["console"], "level": "INFO"},
},
}

# Heroku settings override to run the web app in production mode
if "DYNO" in os.environ:
logger.info("Setting up Heroku environment")
ALLOWED_HOSTS = ["*"]
DEBUG = os.environ.get("DEBUG", "false").lower() == "true"

# Database setup
if "DATABASE_URL" in os.environ:
logger.info("Using remote database from $DATABASE_URL")
DATABASES["default"] = dj_database_url.parse(
os.environ["DATABASE_URL"], ssl_require=True
)
else:
logger.info("DATABASE_URL not found, will use sqlite. Data may be lost.")

# Insert Whitenoise Middleware after the security one
MIDDLEWARE.insert(1, "whitenoise.middleware.WhiteNoiseMiddleware")
Comment on lines +141 to +176
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added these lines to run on Heroku


# Use Secret key from env
SECRET_KEY = os.environ.get("SECRET_KEY", SECRET_KEY)
13 changes: 13 additions & 0 deletions backend/code_review_backend/app/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from django.contrib import admin
from django.shortcuts import redirect
from django.urls import path

urlpatterns = [
path("", lambda request: redirect("admin/", permanent=False)),
path("admin/", admin.site.urls),
]
21 changes: 21 additions & 0 deletions backend/code_review_backend/app/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

"""
WSGI config for backend project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
"""

import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "code_review_backend.app.settings")

application = get_wsgi_application()
Loading