From aa00efc6048c4bca46acabe18ee6d1b08f52e0e5 Mon Sep 17 00:00:00 2001 From: Numerlor <25886452+Numerlor@users.noreply.github.com> Date: Mon, 30 Aug 2021 22:53:52 +0200 Subject: Allow empty value for inventory url field --- .../api/migrations/0072_doc_allow_blank_base_url.py | 19 +++++++++++++++++++ pydis_site/apps/api/models/bot/documentation_link.py | 1 + 2 files changed, 20 insertions(+) create mode 100644 pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py diff --git a/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py b/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py new file mode 100644 index 00000000..d4899354 --- /dev/null +++ b/pydis_site/apps/api/migrations/0072_doc_allow_blank_base_url.py @@ -0,0 +1,19 @@ +# Generated by Django 3.0.14 on 2021-08-30 21:09 + +from django.db import migrations, models +import pydis_site.apps.api.models.bot.documentation_link + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0071_increase_message_content_4000'), + ] + + operations = [ + migrations.AlterField( + model_name='documentationlink', + name='base_url', + field=models.URLField(blank=True, help_text='The base URL from which documentation will be available for this project. Used to generate links to various symbols within this package.', validators=[pydis_site.apps.api.models.bot.documentation_link.ends_with_slash_validator]), + ), + ] diff --git a/pydis_site/apps/api/models/bot/documentation_link.py b/pydis_site/apps/api/models/bot/documentation_link.py index 3dcc71fc..9941907c 100644 --- a/pydis_site/apps/api/models/bot/documentation_link.py +++ b/pydis_site/apps/api/models/bot/documentation_link.py @@ -30,6 +30,7 @@ class DocumentationLink(ModelReprMixin, models.Model): "The base URL from which documentation will be available for this project. " "Used to generate links to various symbols within this package." ), + blank=True, validators=(ends_with_slash_validator,) ) inventory_url = models.URLField( -- cgit v1.2.3 From 58e061109f3ce09e1d8687f61ad22a335deb893a Mon Sep 17 00:00:00 2001 From: Numerlor <25886452+Numerlor@users.noreply.github.com> Date: Mon, 30 Aug 2021 23:04:40 +0200 Subject: Move base_url field to the end In most cases this won't need to be specified, so it makes more sense to move it out of the way --- pydis_site/apps/api/admin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydis_site/apps/api/admin.py b/pydis_site/apps/api/admin.py index 449e660e..2aca38a1 100644 --- a/pydis_site/apps/api/admin.py +++ b/pydis_site/apps/api/admin.py @@ -48,8 +48,8 @@ class BotSettingAdmin(admin.ModelAdmin): class DocumentationLinkAdmin(admin.ModelAdmin): """Admin formatting for the DocumentationLink model.""" - fields = ("package", "base_url", "inventory_url") - list_display = ("package", "base_url", "inventory_url") + fields = ("package", "inventory_url", "base_url") + list_display = ("package", "inventory_url", "base_url") list_editable = ("base_url", "inventory_url") search_fields = ("package",) -- cgit v1.2.3 From cc3407ee3e9d249a4530d20340ba8055b038f499 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Tue, 31 Aug 2021 19:28:52 +0100 Subject: Update gunicorn options for deployment Remove threads & max requests configuration --- manage.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/manage.py b/manage.py index 8bb5ae0d..a7413ed9 100755 --- a/manage.py +++ b/manage.py @@ -176,10 +176,7 @@ class SiteManager: "--preload", "-b", "0.0.0.0:8000", "pydis_site.wsgi:application", - "--threads", "8", "-w", "2", - "--max-requests", "1000", - "--max-requests-jitter", "50", "--statsd-host", "graphite.default.svc.cluster.local:8125", "--statsd-prefix", "site", ] -- cgit v1.2.3 From 7a537d41d1e998076423ff21b8877dbafead2c98 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 2 Sep 2021 21:13:02 +0000 Subject: Install Django prometheus --- poetry.lock | 32 +++++++++++++++++++++++++++++++- pyproject.toml | 1 + 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 76c8890b..8e66cb57 100644 --- a/poetry.lock +++ b/poetry.lock @@ -157,6 +157,17 @@ category = "main" optional = false python-versions = ">=3.5" +[[package]] +name = "django-prometheus" +version = "2.1.0" +description = "Django middlewares to monitor your application with Prometheus.io." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +prometheus-client = ">=0.7" + [[package]] name = "django-simple-bulma" version = "2.2.0" @@ -455,6 +466,17 @@ pyyaml = ">=5.1" toml = "*" virtualenv = ">=20.0.8" +[[package]] +name = "prometheus-client" +version = "0.11.0" +description = "Python client for the Prometheus monitoring system." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.extras] +twisted = ["twisted"] + [[package]] name = "psutil" version = "5.8.0" @@ -706,7 +728,7 @@ brotli = ["brotli"] [metadata] lock-version = "1.1" python-versions = "3.9.*" -content-hash = "741444c18250124e2d998506b0643fb26240d7481389a13648b02fa1794435e3" +content-hash = "cb345745569d389fcb35f72e34d65c1f9e860f110e521d2f634286bc9127ea2f" [metadata.files] appdirs = [ @@ -819,6 +841,10 @@ django-hosts = [ {file = "django-hosts-4.0.tar.gz", hash = "sha256:59a870d453f113c889a7888bae5408888870350e83e362740f382dad569c2281"}, {file = "django_hosts-4.0-py2.py3-none-any.whl", hash = "sha256:136ac225f34e7f2c007294441a38663ec2bba9637d870ad001def81bca87e390"}, ] +django-prometheus = [ + {file = "django-prometheus-2.1.0.tar.gz", hash = "sha256:dd3f8da1399140fbef5c00d1526a23d1ade286b144281c325f8e409a781643f2"}, + {file = "django_prometheus-2.1.0-py2.py3-none-any.whl", hash = "sha256:c338d6efde1ca336e90c540b5e87afe9287d7bcc82d651a778f302b0be17a933"}, +] django-simple-bulma = [ {file = "django-simple-bulma-2.2.0.tar.gz", hash = "sha256:dfc34839e050d5e4749498806ed7ee8c77794021efa54ab224a2de925c644fea"}, {file = "django_simple_bulma-2.2.0-py3-none-any.whl", hash = "sha256:38530d787b2b6a091b480f7cbb8841a3b3709733ebfa5e543ae339c3d8fece03"}, @@ -935,6 +961,10 @@ pre-commit = [ {file = "pre_commit-2.12.1-py2.py3-none-any.whl", hash = "sha256:70c5ec1f30406250b706eda35e868b87e3e4ba099af8787e3e8b4b01e84f4712"}, {file = "pre_commit-2.12.1.tar.gz", hash = "sha256:900d3c7e1bf4cf0374bb2893c24c23304952181405b4d88c9c40b72bda1bb8a9"}, ] +prometheus-client = [ + {file = "prometheus_client-0.11.0-py2.py3-none-any.whl", hash = "sha256:b014bc76815eb1399da8ce5fc84b7717a3e63652b0c0f8804092c9363acab1b2"}, + {file = "prometheus_client-0.11.0.tar.gz", hash = "sha256:3a8baade6cb80bcfe43297e33e7623f3118d660d41387593758e2fb1ea173a86"}, +] psutil = [ {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"}, {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"}, diff --git a/pyproject.toml b/pyproject.toml index 5bbf86ee..c8029d94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ gunicorn = "~=20.0.4" sentry-sdk = "~=0.19" markdown = "~=3.3.4" python-frontmatter = "~=1.0" +django-prometheus = "^2.1.0" [tool.poetry.dev-dependencies] coverage = "~=5.0" -- cgit v1.2.3 From 89d7dacf3337fed0685aad4409e86b3e137246ad Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 2 Sep 2021 21:15:31 +0000 Subject: Add Django Prometheus to installed apps and middleware --- Dockerfile | 1 + pydis_site/settings.py | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index c07fc2e2..46f45bf3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,7 @@ COPY . . # Set dummy variables so collectstatic can load settings.py RUN \ + BUILDING_DOCKER=yes \ SECRET_KEY=dummy_value \ DATABASE_URL=postgres://localhost \ METRICITY_DB_URL=postgres://localhost \ diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 7df7ad85..61f3b6f8 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -23,7 +23,8 @@ from pydis_site.constants import GIT_SHA env = environ.Env( DEBUG=(bool, False), - SITE_DSN=(str, "") + SITE_DSN=(str, ""), + BUILDING_DOCKER=(bool, False) ) sentry_sdk.init( @@ -84,10 +85,15 @@ INSTALLED_APPS = [ 'django_filters', 'django_simple_bulma', 'rest_framework', - 'rest_framework.authtoken' + 'rest_framework.authtoken', ] +if not env("BUILDING_DOCKER"): + INSTALLED_APPS.append("django_prometheus") + +# Ensure that Prometheus middlewares are first and last here. MIDDLEWARE = [ + 'django_prometheus.middleware.PrometheusBeforeMiddleware', 'django_hosts.middleware.HostsRequestMiddleware', 'django.middleware.security.SecurityMiddleware', @@ -100,7 +106,9 @@ MIDDLEWARE = [ 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django_hosts.middleware.HostsResponseMiddleware', + 'django_prometheus.middleware.PrometheusAfterMiddleware' ] + ROOT_URLCONF = 'pydis_site.urls' TEMPLATES = [ @@ -131,7 +139,7 @@ WSGI_APPLICATION = 'pydis_site.wsgi.application' DATABASES = { 'default': env.db(), - 'metricity': env.db('METRICITY_DB_URL'), + 'metricity': env.db(), } # Password validation -- cgit v1.2.3 From b051c454ac853a145fa961f4409fcadd8b1d5dbc Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 2 Sep 2021 21:15:52 +0000 Subject: Add Django Prometheus to URLs --- pydis_site/apps/home/urls.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py index 1e2af8f3..bb77220b 100644 --- a/pydis_site/apps/home/urls.py +++ b/pydis_site/apps/home/urls.py @@ -7,6 +7,7 @@ app_name = 'home' urlpatterns = [ path('', HomeView.as_view(), name='home'), path('', include('pydis_site.apps.redirect.urls')), + path('', include('django_prometheus.urls')), path('admin/', admin.site.urls), path('resources/', include('pydis_site.apps.resources.urls')), path('pages/', include('pydis_site.apps.content.urls')), -- cgit v1.2.3 From 4a6ea09f3849f86d8307526e23362ea93365ebef Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 2 Sep 2021 21:27:54 +0000 Subject: Revert change to Metricity DB URL Co-Authored-By: jchristgit --- pydis_site/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 61f3b6f8..6f49763b 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -139,7 +139,7 @@ WSGI_APPLICATION = 'pydis_site.wsgi.application' DATABASES = { 'default': env.db(), - 'metricity': env.db(), + 'metricity': env.db('METRICITY_DB_URL'), } # Password validation -- cgit v1.2.3 From 1190c68005f63ff7463dbb9e35d72dbc54f60f3d Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Thu, 2 Sep 2021 23:00:39 +0100 Subject: Follow standard for dependency versioning for django-prometheus Co-authored-by: Vivaan Verma --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c8029d94..c99f1e0b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ gunicorn = "~=20.0.4" sentry-sdk = "~=0.19" markdown = "~=3.3.4" python-frontmatter = "~=1.0" -django-prometheus = "^2.1.0" +django-prometheus = "~=2.1" [tool.poetry.dev-dependencies] coverage = "~=5.0" -- cgit v1.2.3 From fa68a1063d4de205cb34c1f17eda62926b23b9db Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Fri, 3 Sep 2021 10:40:16 +0100 Subject: Timeout when fetching GitHub repository metadata Not having this timeout could cause a worker to hang indefinitely --- pydis_site/apps/home/views/home.py | 15 +++++++++++---- pydis_site/constants.py | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py index 0f26cef3..bbb4b815 100644 --- a/pydis_site/apps/home/views/home.py +++ b/pydis_site/apps/home/views/home.py @@ -9,7 +9,7 @@ from django.utils import timezone from django.views import View from pydis_site.apps.home.models import RepositoryMetadata -from pydis_site.constants import GITHUB_TOKEN +from pydis_site.constants import GITHUB_TOKEN, TIMEOUT_PERIOD log = logging.getLogger(__name__) @@ -51,9 +51,16 @@ class HomeView(View): If we're unable to get that info for any reason, return an empty dict. """ repo_dict = {} - - # Fetch the data from the GitHub API - api_data: List[dict] = requests.get(self.github_api, headers=self.headers).json() + try: + # Fetch the data from the GitHub API + api_data: List[dict] = requests.get( + self.github_api, + headers=self.headers, + timeout=TIMEOUT_PERIOD + ).json() + except requests.exceptions.Timeout: + log.error("Request to fetch GitHub repository metadata for timed out!") + return repo_dict # Process the API data into our dict for repo in api_data: diff --git a/pydis_site/constants.py b/pydis_site/constants.py index e6a63d12..e913f40f 100644 --- a/pydis_site/constants.py +++ b/pydis_site/constants.py @@ -2,3 +2,5 @@ import os GIT_SHA = os.environ.get("GIT_SHA", "development") GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN") +# How long to wait for synchronous requests before timing out +TIMEOUT_PERIOD = int(os.environ.get("TIMEOUT_PERIOD", 5)) -- cgit v1.2.3 From ec64154cf68a7600f78da6d35a7166ea425b3c6f Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 3 Sep 2021 22:31:39 +0100 Subject: Add note on BUILDING_DOCKER --- Dockerfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Dockerfile b/Dockerfile index 46f45bf3..7d1dab74 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,10 @@ COPY . . # Set dummy variables so collectstatic can load settings.py RUN \ + # Set BUILDING_DOCKER to anything but undefined so settings.py + # does not insert django_prometheus into the list of installed apps. + # This prevents django_prometheus from attempting to connect to the database + # when the collectstatic task is ran. BUILDING_DOCKER=yes \ SECRET_KEY=dummy_value \ DATABASE_URL=postgres://localhost \ -- cgit v1.2.3 From 700cc67a9aee27c903f3d55f72c113a643219a5d Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 3 Sep 2021 22:35:21 +0100 Subject: Add gunicorn.conf.py with Prometheus specific settings --- gunicorn.conf.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 gunicorn.conf.py diff --git a/gunicorn.conf.py b/gunicorn.conf.py new file mode 100644 index 00000000..c60b64eb --- /dev/null +++ b/gunicorn.conf.py @@ -0,0 +1,5 @@ +# Code taken from https://github.com/prometheus/client_python#multiprocess-mode-eg-gunicorn +from prometheus_client import multiprocess + +def child_exit(server, worker): + multiprocess.mark_process_dead(worker.pid) -- cgit v1.2.3 From 6bd72f73b761264032907530a9ab1d4c4fa0e97f Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 3 Sep 2021 22:40:38 +0100 Subject: Ignore gunicorn configuration from flake8 --- .flake8 | 2 +- gunicorn.conf.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.flake8 b/.flake8 index 6690af3e..e665771f 100644 --- a/.flake8 +++ b/.flake8 @@ -3,7 +3,7 @@ max-line-length=100 docstring-convention=all import-order-style=pycharm application_import_names=pydis_site -exclude=__pycache__, venv, .venv, **/migrations/**, .cache/ +exclude=__pycache__, venv, .venv, **/migrations/**, .cache/, gunicorn.conf.py ignore= B311,W503,E226,S311,T000 # Missing Docstrings diff --git a/gunicorn.conf.py b/gunicorn.conf.py index c60b64eb..4930ae5b 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -1,5 +1,10 @@ -# Code taken from https://github.com/prometheus/client_python#multiprocess-mode-eg-gunicorn +""" +Configuration file for gunicorn. + +Code taken from https://github.com/prometheus/client_python#multiprocess-mode-eg-gunicorn +""" from prometheus_client import multiprocess -def child_exit(server, worker): + +def child_exit(server, worker) -> None: multiprocess.mark_process_dead(worker.pid) -- cgit v1.2.3 From 593bd1a9a6b1cef9fa16608e19a379dcf6adb203 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 4 Sep 2021 09:02:17 +0100 Subject: Explicitly set gunicorn config argument --- manage.py | 1 + 1 file changed, 1 insertion(+) diff --git a/manage.py b/manage.py index a7413ed9..66ad26f4 100755 --- a/manage.py +++ b/manage.py @@ -179,6 +179,7 @@ class SiteManager: "-w", "2", "--statsd-host", "graphite.default.svc.cluster.local:8125", "--statsd-prefix", "site", + "--config", "file:gunicorn.conf.py" ] # Run gunicorn for the production server. -- cgit v1.2.3 From 8bd260d7e6cf11c556e2e5533c4c70c3a15c2331 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 4 Sep 2021 09:45:45 +0100 Subject: Update in accordance with python-discord/kubernetes#95 --- .github/workflows/deploy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml index 4208f727..0e315327 100644 --- a/.github/workflows/deploy.yaml +++ b/.github/workflows/deploy.yaml @@ -41,7 +41,7 @@ jobs: uses: Azure/k8s-deploy@v1 with: manifests: | - site/deployment.yaml + namespaces/default/site/deployment.yaml images: 'ghcr.io/python-discord/site:${{ steps.sha_tag.outputs.tag }}' kubectl-version: 'latest' -- cgit v1.2.3 From 8a4b1a15262a91d486c4b95e19533d4d44dd7c2b Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 4 Sep 2021 10:32:10 +0100 Subject: Add pod IPs to allowed hosts --- pydis_site/settings.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 6f49763b..0aa66322 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -14,6 +14,7 @@ import os import secrets import sys from pathlib import Path +from socket import gethostname, gethostbyname import environ import sentry_sdk @@ -59,6 +60,8 @@ else: 'api.pythondiscord.com', 'staff.pythondiscord.com', 'pydis-api.default.svc.cluster.local', + gethostname(), + gethostbyname(gethostname()) ] ) SECRET_KEY = env('SECRET_KEY') -- cgit v1.2.3 From cc6fed3b13ba1aa9ec3cf84227048c9d04ebecda Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Sat, 4 Sep 2021 10:34:52 +0100 Subject: Correct import order --- pydis_site/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index 0aa66322..d2cd8698 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -14,7 +14,7 @@ import os import secrets import sys from pathlib import Path -from socket import gethostname, gethostbyname +from socket import gethostbyname, gethostname import environ import sentry_sdk -- cgit v1.2.3 From 3bbb7c0c0ccdfd9a7475095fd5e33e1adafee679 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Sat, 4 Sep 2021 14:55:08 +0100 Subject: Pin platform in Dockerfile Some of our deps don't have wheels for atm processors. With Mac's M1 chips becomming more common, we should make it easier for those users to build our environments. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7d1dab74..046e7f80 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9.5-slim-buster +FROM --platform=linux/amd64 python:3.9-slim-buster # Allow service to handle stops gracefully STOPSIGNAL SIGQUIT -- cgit v1.2.3 From 78d82791afb8fd3da4f767393b918ee401b41aec Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Sun, 5 Sep 2021 22:35:31 +0100 Subject: Initialise metricity at runtime Currently the bot cannot start in dev as the site errors, saying that metricity doesn't exist. Previously this note existing was fine, unless you needed to use metricity data. With the recent addition of django-prometheus, metricity is now required on boot. This PR moves the init of metricity from a docker-compose volume, into running of the site. This means that external projects using site, that don't have access to the init.sql file to mount a volume, now also init metricity. --- docker-compose.yml | 2 -- manage.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++--- postgres/init.sql | 48 +++++++++++++++++++++----------------------- 3 files changed, 77 insertions(+), 31 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 05867a46..37678949 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,8 +18,6 @@ services: POSTGRES_DB: pysite POSTGRES_PASSWORD: pysite POSTGRES_USER: pysite - volumes: - - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql web: build: diff --git a/manage.py b/manage.py index 66ad26f4..ad9bae5f 100755 --- a/manage.py +++ b/manage.py @@ -129,12 +129,58 @@ class SiteManager: name="pythondiscord.local:8000" ) + @staticmethod + def run_metricity_init() -> None: + """ + Initilise metricity relations and populate with some testing data. + + This is done at run time since other projects, like Python bot, + rely on the site initilising it's own db, since they do not have + access to the init.sql file to mount a docker-compose volume. + """ + import psycopg2 + from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT + from urllib.parse import urlsplit + # The database URL has already been validated in `wait_for_postgres()` + db_url_parts = urlsplit(os.environ["DATABASE_URL"]) + db_connection_kwargs = { + "host": db_url_parts.hostname, + "port": db_url_parts.port, + "user": db_url_parts.username, + "password": db_url_parts.password, + } + # Connect to pysite first to create metricity db + conn = psycopg2.connect( + database=db_url_parts.path[1:], + **db_connection_kwargs + ) + conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) + + with conn.cursor() as cursor: + cursor.execute("SELECT 1 FROM pg_catalog.pg_database WHERE datname = 'metricity'") + exists = cursor.fetchone() + if exists: + # Assume metricity is already populated if it exists + print("Metricity already exists, not creating.") + return + print("Creating metricity relations and populating with some data.") + cursor.execute("CREATE DATABASE metricity") + + # Switch connection to metricity and initialise some data + conn = psycopg2.connect( + database="metricity", + **db_connection_kwargs + ) + with conn.cursor() as cursor: + cursor.execute(open("postgres/init.sql").read()) + def prepare_server(self) -> None: """Perform preparation tasks before running the server.""" - django.setup() - + self.wait_for_postgres() if self.debug: - self.wait_for_postgres() + self.run_metricity_init() + + django.setup() print("Applying migrations.") call_command("migrate", verbosity=self.verbosity) @@ -188,6 +234,12 @@ class SiteManager: def main() -> None: """Entry point for Django management script.""" + # Always run metricity init in CI + in_ci = os.environ.get("CI", "false").lower() == "true" + if in_ci: + SiteManager.wait_for_postgres() + SiteManager.run_metricity_init() + # Use the custom site manager for launching the server if len(sys.argv) > 1 and sys.argv[1] == "run": SiteManager(sys.argv).run_server() diff --git a/postgres/init.sql b/postgres/init.sql index 190a705c..ea748480 100644 --- a/postgres/init.sql +++ b/postgres/init.sql @@ -1,8 +1,4 @@ -CREATE DATABASE metricity; - -\c metricity; - -CREATE TABLE users ( +CREATE TABLE IF NOT EXISTS users ( id varchar, joined_at timestamp, primary key(id) @@ -11,14 +7,14 @@ CREATE TABLE users ( INSERT INTO users VALUES ( 0, current_timestamp -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO users VALUES ( 1, current_timestamp -); +) ON CONFLICT (id) DO NOTHING; -CREATE TABLE channels ( +CREATE TABLE IF NOT EXISTS channels ( id varchar, name varchar, primary key(id) @@ -27,44 +23,44 @@ CREATE TABLE channels ( INSERT INTO channels VALUES( '267659945086812160', 'python-general' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '11', 'help-apple' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '12', 'help-cherry' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '21', 'ot0-hello' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '22', 'ot1-world' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '31', 'voice-chat-0' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '32', 'code-help-voice-0' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO channels VALUES( '1234', 'zebra' -); +) ON CONFLICT (id) DO NOTHING; -CREATE TABLE messages ( +CREATE TABLE IF NOT EXISTS messages ( id varchar, author_id varchar references users(id), is_deleted boolean, @@ -79,7 +75,7 @@ INSERT INTO messages VALUES( false, now(), '267659945086812160' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 1, @@ -87,7 +83,7 @@ INSERT INTO messages VALUES( false, now() + INTERVAL '10 minutes,', '1234' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 2, @@ -95,7 +91,7 @@ INSERT INTO messages VALUES( false, now(), '11' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 3, @@ -103,7 +99,7 @@ INSERT INTO messages VALUES( false, now(), '12' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 4, @@ -111,7 +107,7 @@ INSERT INTO messages VALUES( false, now(), '21' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 5, @@ -119,7 +115,7 @@ INSERT INTO messages VALUES( false, now(), '22' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 6, @@ -127,7 +123,7 @@ INSERT INTO messages VALUES( false, now(), '31' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 7, @@ -135,7 +131,7 @@ INSERT INTO messages VALUES( false, now(), '32' -); +) ON CONFLICT (id) DO NOTHING; INSERT INTO messages VALUES( 8, @@ -143,4 +139,4 @@ INSERT INTO messages VALUES( true, now(), '32' -); +) ON CONFLICT (id) DO NOTHING; -- cgit v1.2.3 From a211f99319df66ff11a75746c5f7ab40ac19122a Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Mon, 6 Sep 2021 21:03:14 +0100 Subject: Use context manager for file open Also remove a useless print statement to reduce noise --- manage.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/manage.py b/manage.py index ad9bae5f..63602d63 100755 --- a/manage.py +++ b/manage.py @@ -161,7 +161,6 @@ class SiteManager: exists = cursor.fetchone() if exists: # Assume metricity is already populated if it exists - print("Metricity already exists, not creating.") return print("Creating metricity relations and populating with some data.") cursor.execute("CREATE DATABASE metricity") @@ -171,8 +170,8 @@ class SiteManager: database="metricity", **db_connection_kwargs ) - with conn.cursor() as cursor: - cursor.execute(open("postgres/init.sql").read()) + with conn.cursor() as cursor, open("postgres/init.sql", encoding="utf-8") as f: + cursor.execute(f.read()) def prepare_server(self) -> None: """Perform preparation tasks before running the server.""" -- cgit v1.2.3 From 661454f9d53508f99a244b4a0ebf34be9b6d3008 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 09:37:47 +0100 Subject: Move db url validation to cls method This standardises the way we validate db urls, and ensures each place that uses a db url manually properly validates it first. --- manage.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/manage.py b/manage.py index 63602d63..70855ba8 100755 --- a/manage.py +++ b/manage.py @@ -1,10 +1,9 @@ #!/usr/bin/env python import os -import re import socket import sys import time -from typing import List +from urllib.parse import SplitResult, urlsplit import django from django.contrib.auth import get_user_model @@ -42,7 +41,7 @@ class SiteManager: --verbose Sets verbose console output. """ - def __init__(self, args: List[str]): + def __init__(self, args: list[str]): self.debug = "--debug" in args self.silent = "--silent" in args @@ -55,6 +54,20 @@ class SiteManager: os.environ.setdefault("DEBUG", "true") print("Starting in debug mode.") + @staticmethod + def parse_db_url(db_url: str) -> SplitResult: + """Validate and split the given databse url.""" + db_url_parts = urlsplit(db_url) + if not all(( + db_url_parts.hostname, + db_url_parts.port, + db_url_parts.username, + db_url_parts.password, + db_url_parts.path + )): + raise OSError("Valid DATABASE_URL environment variable not found.") + return db_url_parts + @staticmethod def create_superuser() -> None: """Create a default django admin super user in development environments.""" @@ -90,12 +103,9 @@ class SiteManager: print("Waiting for PostgreSQL database.") # Get database URL based on environmental variable passed in compose - database_url = os.environ["DATABASE_URL"] - match = re.search(r"@([\w.]+):(\d+)/", database_url) - if not match: - raise OSError("Valid DATABASE_URL environmental variable not found.") - domain = match.group(1) - port = int(match.group(2)) + database_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) + domain = database_url_parts.hostname + port = database_url_parts.port # Attempt to connect to the database socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -140,9 +150,8 @@ class SiteManager: """ import psycopg2 from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT - from urllib.parse import urlsplit - # The database URL has already been validated in `wait_for_postgres()` - db_url_parts = urlsplit(os.environ["DATABASE_URL"]) + + db_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) db_connection_kwargs = { "host": db_url_parts.hostname, "port": db_url_parts.port, -- cgit v1.2.3 From 6de87e47e313b4f533e8d3adfeb0b8202e938ca0 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 09:38:16 +0100 Subject: Close db conns when finished psycopg2's context managers don't do this for us, so we need to close conns manually. --- manage.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manage.py b/manage.py index 70855ba8..cb4eb567 100755 --- a/manage.py +++ b/manage.py @@ -173,6 +173,7 @@ class SiteManager: return print("Creating metricity relations and populating with some data.") cursor.execute("CREATE DATABASE metricity") + conn.close() # Switch connection to metricity and initialise some data conn = psycopg2.connect( @@ -181,6 +182,7 @@ class SiteManager: ) with conn.cursor() as cursor, open("postgres/init.sql", encoding="utf-8") as f: cursor.execute(f.read()) + conn.close() def prepare_server(self) -> None: """Perform preparation tasks before running the server.""" -- cgit v1.2.3 From d245bbd600811762a74544aeff6086a6c94dd7f3 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 09:59:18 +0100 Subject: Create and populate metricity in a single connection --- manage.py | 35 ++++++++++------------------------- postgres/init.sql | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/manage.py b/manage.py index cb4eb567..308f917d 100755 --- a/manage.py +++ b/manage.py @@ -152,36 +152,21 @@ class SiteManager: from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT db_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) - db_connection_kwargs = { - "host": db_url_parts.hostname, - "port": db_url_parts.port, - "user": db_url_parts.username, - "password": db_url_parts.password, - } - # Connect to pysite first to create metricity db conn = psycopg2.connect( - database=db_url_parts.path[1:], - **db_connection_kwargs + host=db_url_parts.hostname, + port=db_url_parts.port, + user=db_url_parts.username, + password=db_url_parts.password, + database=db_url_parts.path[1:] ) + # Required to create a db from `cursor.execute()` conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) - with conn.cursor() as cursor: - cursor.execute("SELECT 1 FROM pg_catalog.pg_database WHERE datname = 'metricity'") - exists = cursor.fetchone() - if exists: - # Assume metricity is already populated if it exists - return - print("Creating metricity relations and populating with some data.") - cursor.execute("CREATE DATABASE metricity") - conn.close() - - # Switch connection to metricity and initialise some data - conn = psycopg2.connect( - database="metricity", - **db_connection_kwargs - ) with conn.cursor() as cursor, open("postgres/init.sql", encoding="utf-8") as f: - cursor.execute(f.read()) + cursor.execute( + f.read(), + ("metricity", db_url_parts.username, db_url_parts.password) + ) conn.close() def prepare_server(self) -> None: diff --git a/postgres/init.sql b/postgres/init.sql index ea748480..ee1acd8d 100644 --- a/postgres/init.sql +++ b/postgres/init.sql @@ -1,3 +1,24 @@ +DO +$do$ +DECLARE + _db TEXT := %s; + _user TEXT := %s; + _password TEXT := %s; +BEGIN + CREATE EXTENSION IF NOT EXISTS dblink; + IF EXISTS (SELECT 1 FROM pg_database WHERE datname = _db) THEN + RAISE NOTICE 'Database already exists'; + ELSE + PERFORM dblink_connect( + 'host=localhost user=' || _user || + ' password=' || _password || + ' dbname=' || current_database() + ); + PERFORM dblink_exec('CREATE DATABASE ' || _db); + END IF; +END +$do$; + CREATE TABLE IF NOT EXISTS users ( id varchar, joined_at timestamp, -- cgit v1.2.3 From a6206855c77b34f4e0705fea7fd7ac358dc88d89 Mon Sep 17 00:00:00 2001 From: ChrisJL Date: Tue, 7 Sep 2021 11:17:42 +0100 Subject: Fix spelling of `initialising` in manage.py Co-authored-by: Vivaan Verma <54081925+doublevcodes@users.noreply.github.com> --- manage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manage.py b/manage.py index 308f917d..22ae45d7 100755 --- a/manage.py +++ b/manage.py @@ -142,10 +142,10 @@ class SiteManager: @staticmethod def run_metricity_init() -> None: """ - Initilise metricity relations and populate with some testing data. + Initialise metricity relations and populate with some testing data. This is done at run time since other projects, like Python bot, - rely on the site initilising it's own db, since they do not have + rely on the site initialising it's own db, since they do not have access to the init.sql file to mount a docker-compose volume. """ import psycopg2 -- cgit v1.2.3 From d612110b67269e7132bd0bc891f2c90a9b806c89 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 11:39:09 +0100 Subject: Remove unnecessary variable Co-authored-by: Vivaan Verma <54081925+doublevcodes@users.noreply.github.com> --- manage.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/manage.py b/manage.py index 22ae45d7..0fa8ebe3 100755 --- a/manage.py +++ b/manage.py @@ -229,9 +229,8 @@ class SiteManager: def main() -> None: """Entry point for Django management script.""" - # Always run metricity init in CI - in_ci = os.environ.get("CI", "false").lower() == "true" - if in_ci: + # Always run metricity init when in CI, indicated by the CI env var + if os.environ.get("CI", "false").lower() == "true": SiteManager.wait_for_postgres() SiteManager.run_metricity_init() -- cgit v1.2.3 From 4411ae4bbffabbf962b5270cd7aaee5b6495ab6e Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 18:16:54 +0100 Subject: Raise a ValueError with a useful message for invalid db urls --- manage.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/manage.py b/manage.py index 0fa8ebe3..a8895126 100755 --- a/manage.py +++ b/manage.py @@ -65,7 +65,9 @@ class SiteManager: db_url_parts.password, db_url_parts.path )): - raise OSError("Valid DATABASE_URL environment variable not found.") + raise ValueError( + "The DATABASE_URL environment variable is not a valid PostgreSQL database URL." + ) return db_url_parts @staticmethod -- cgit v1.2.3 From 04ab6e6e10eace3ee103cef61f2ee94f3d2129fb Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 18:19:11 +0100 Subject: Correctly attribute SO author for SQL function --- postgres/init.sql | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/postgres/init.sql b/postgres/init.sql index ee1acd8d..55bb468f 100644 --- a/postgres/init.sql +++ b/postgres/init.sql @@ -1,3 +1,7 @@ +-- The following function is from Stack Overflow +-- https://stackoverflow.com/questions/18389124/simulate-create-database-if-not-exists-for-postgresql/36218838#36218838 +-- User frankhommers (https://stackoverflow.com/users/971229/frankhommers) + DO $do$ DECLARE -- cgit v1.2.3 From 71252e7d40fed7dcee26ef45a2eb1f8f242b83e9 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 18:30:33 +0100 Subject: Add print statement to log when metricity is being initialised --- manage.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/manage.py b/manage.py index a8895126..1e613e93 100755 --- a/manage.py +++ b/manage.py @@ -153,6 +153,8 @@ class SiteManager: import psycopg2 from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT + print("Initialising metricity.") + db_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) conn = psycopg2.connect( host=db_url_parts.hostname, -- cgit v1.2.3 From f12d4ac1a6833a9764035ef32c841ee5d12e066b Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Tue, 7 Sep 2021 18:58:33 +0100 Subject: Remove explicit check for db port, as it's optional We also do not specifiy it in prod, so this crash looped when trying to deploy --- manage.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manage.py b/manage.py index 1e613e93..648d6635 100755 --- a/manage.py +++ b/manage.py @@ -60,7 +60,6 @@ class SiteManager: db_url_parts = urlsplit(db_url) if not all(( db_url_parts.hostname, - db_url_parts.port, db_url_parts.username, db_url_parts.password, db_url_parts.path @@ -107,7 +106,8 @@ class SiteManager: # Get database URL based on environmental variable passed in compose database_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) domain = database_url_parts.hostname - port = database_url_parts.port + # Port may be omitted, 5432 is the default psql port + port = database_url_parts.port or 5432 # Attempt to connect to the database socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -- cgit v1.2.3 From 6730607d389e53276d3791a423f92f3a3f1349ef Mon Sep 17 00:00:00 2001 From: mbaruh Date: Tue, 7 Sep 2021 23:20:10 +0300 Subject: Update embed description length to 4096 --- pydis_site/apps/api/models/utils.py | 2 +- pydis_site/apps/api/tests/test_validators.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pydis_site/apps/api/models/utils.py b/pydis_site/apps/api/models/utils.py index 107231ba..0e220a1d 100644 --- a/pydis_site/apps/api/models/utils.py +++ b/pydis_site/apps/api/models/utils.py @@ -142,7 +142,7 @@ def validate_embed(embed: Any) -> None: ), MaxLengthValidator(limit_value=256) ), - 'description': (MaxLengthValidator(limit_value=2048),), + 'description': (MaxLengthValidator(limit_value=4096),), 'fields': ( MaxLengthValidator(limit_value=25), validate_embed_fields diff --git a/pydis_site/apps/api/tests/test_validators.py b/pydis_site/apps/api/tests/test_validators.py index 8bb7b917..551cc2aa 100644 --- a/pydis_site/apps/api/tests/test_validators.py +++ b/pydis_site/apps/api/tests/test_validators.py @@ -72,7 +72,7 @@ class TagEmbedValidatorTests(TestCase): def test_rejects_too_long_description(self): with self.assertRaises(ValidationError): validate_embed({ - 'description': 'd' * 2049 + 'description': 'd' * 4097 }) def test_allows_valid_embed(self): -- cgit v1.2.3 From 198406da7d45b672bc4213d407f2a4c79acddaa8 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 10 Sep 2021 23:23:31 +0100 Subject: Update repository selection on home page In accordance with a poll in #dev-contrib, King Arthur becomes the 6th repository featured on the Python Discord homepage. --- pydis_site/apps/home/views/home.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/apps/home/views/home.py b/pydis_site/apps/home/views/home.py index bbb4b815..401c768f 100644 --- a/pydis_site/apps/home/views/home.py +++ b/pydis_site/apps/home/views/home.py @@ -27,7 +27,7 @@ class HomeView(View): "python-discord/snekbox", "python-discord/sir-lancebot", "python-discord/metricity", - "python-discord/django-simple-bulma", + "python-discord/king-arthur", ] def __init__(self): -- cgit v1.2.3 From 98eb08ccb82e14326828e00e76b022bdb0c23f1e Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Fri, 10 Sep 2021 23:43:56 +0100 Subject: Update mock GitHub API response Fixes breaking tests --- pydis_site/apps/home/tests/mock_github_api_response.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydis_site/apps/home/tests/mock_github_api_response.json b/pydis_site/apps/home/tests/mock_github_api_response.json index ddbffed8..3b0a7078 100644 --- a/pydis_site/apps/home/tests/mock_github_api_response.json +++ b/pydis_site/apps/home/tests/mock_github_api_response.json @@ -21,7 +21,7 @@ "forks_count": 31 }, { - "full_name": "python-discord/django-simple-bulma", + "full_name": "python-discord/king-arthur", "description": "test", "stargazers_count": 97, "language": "Python", -- cgit v1.2.3 From a2494d4275c6bbe578156601b0fda0cf203e7af7 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Thu, 9 Sep 2021 15:53:32 +0100 Subject: Init metricity using docker-compose init volume --- docker-compose.yml | 2 ++ manage.py | 37 --------------------------- postgres/init.sql | 73 +++++++++++++++++++----------------------------------- 3 files changed, 28 insertions(+), 84 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 37678949..05867a46 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,8 @@ services: POSTGRES_DB: pysite POSTGRES_PASSWORD: pysite POSTGRES_USER: pysite + volumes: + - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql web: build: diff --git a/manage.py b/manage.py index 648d6635..d8258281 100755 --- a/manage.py +++ b/manage.py @@ -141,44 +141,8 @@ class SiteManager: name="pythondiscord.local:8000" ) - @staticmethod - def run_metricity_init() -> None: - """ - Initialise metricity relations and populate with some testing data. - - This is done at run time since other projects, like Python bot, - rely on the site initialising it's own db, since they do not have - access to the init.sql file to mount a docker-compose volume. - """ - import psycopg2 - from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT - - print("Initialising metricity.") - - db_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) - conn = psycopg2.connect( - host=db_url_parts.hostname, - port=db_url_parts.port, - user=db_url_parts.username, - password=db_url_parts.password, - database=db_url_parts.path[1:] - ) - # Required to create a db from `cursor.execute()` - conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT) - - with conn.cursor() as cursor, open("postgres/init.sql", encoding="utf-8") as f: - cursor.execute( - f.read(), - ("metricity", db_url_parts.username, db_url_parts.password) - ) - conn.close() - def prepare_server(self) -> None: """Perform preparation tasks before running the server.""" - self.wait_for_postgres() - if self.debug: - self.run_metricity_init() - django.setup() print("Applying migrations.") @@ -236,7 +200,6 @@ def main() -> None: # Always run metricity init when in CI, indicated by the CI env var if os.environ.get("CI", "false").lower() == "true": SiteManager.wait_for_postgres() - SiteManager.run_metricity_init() # Use the custom site manager for launching the server if len(sys.argv) > 1 and sys.argv[1] == "run": diff --git a/postgres/init.sql b/postgres/init.sql index 55bb468f..190a705c 100644 --- a/postgres/init.sql +++ b/postgres/init.sql @@ -1,29 +1,8 @@ --- The following function is from Stack Overflow --- https://stackoverflow.com/questions/18389124/simulate-create-database-if-not-exists-for-postgresql/36218838#36218838 --- User frankhommers (https://stackoverflow.com/users/971229/frankhommers) - -DO -$do$ -DECLARE - _db TEXT := %s; - _user TEXT := %s; - _password TEXT := %s; -BEGIN - CREATE EXTENSION IF NOT EXISTS dblink; - IF EXISTS (SELECT 1 FROM pg_database WHERE datname = _db) THEN - RAISE NOTICE 'Database already exists'; - ELSE - PERFORM dblink_connect( - 'host=localhost user=' || _user || - ' password=' || _password || - ' dbname=' || current_database() - ); - PERFORM dblink_exec('CREATE DATABASE ' || _db); - END IF; -END -$do$; - -CREATE TABLE IF NOT EXISTS users ( +CREATE DATABASE metricity; + +\c metricity; + +CREATE TABLE users ( id varchar, joined_at timestamp, primary key(id) @@ -32,14 +11,14 @@ CREATE TABLE IF NOT EXISTS users ( INSERT INTO users VALUES ( 0, current_timestamp -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO users VALUES ( 1, current_timestamp -) ON CONFLICT (id) DO NOTHING; +); -CREATE TABLE IF NOT EXISTS channels ( +CREATE TABLE channels ( id varchar, name varchar, primary key(id) @@ -48,44 +27,44 @@ CREATE TABLE IF NOT EXISTS channels ( INSERT INTO channels VALUES( '267659945086812160', 'python-general' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '11', 'help-apple' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '12', 'help-cherry' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '21', 'ot0-hello' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '22', 'ot1-world' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '31', 'voice-chat-0' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '32', 'code-help-voice-0' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO channels VALUES( '1234', 'zebra' -) ON CONFLICT (id) DO NOTHING; +); -CREATE TABLE IF NOT EXISTS messages ( +CREATE TABLE messages ( id varchar, author_id varchar references users(id), is_deleted boolean, @@ -100,7 +79,7 @@ INSERT INTO messages VALUES( false, now(), '267659945086812160' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 1, @@ -108,7 +87,7 @@ INSERT INTO messages VALUES( false, now() + INTERVAL '10 minutes,', '1234' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 2, @@ -116,7 +95,7 @@ INSERT INTO messages VALUES( false, now(), '11' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 3, @@ -124,7 +103,7 @@ INSERT INTO messages VALUES( false, now(), '12' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 4, @@ -132,7 +111,7 @@ INSERT INTO messages VALUES( false, now(), '21' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 5, @@ -140,7 +119,7 @@ INSERT INTO messages VALUES( false, now(), '22' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 6, @@ -148,7 +127,7 @@ INSERT INTO messages VALUES( false, now(), '31' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 7, @@ -156,7 +135,7 @@ INSERT INTO messages VALUES( false, now(), '32' -) ON CONFLICT (id) DO NOTHING; +); INSERT INTO messages VALUES( 8, @@ -164,4 +143,4 @@ INSERT INTO messages VALUES( true, now(), '32' -) ON CONFLICT (id) DO NOTHING; +); -- cgit v1.2.3 From c9aed176706852196fec0fc65ee7552d511316f2 Mon Sep 17 00:00:00 2001 From: Chris Lovering Date: Thu, 9 Sep 2021 15:54:17 +0100 Subject: Move psql health check to docker compose file --- docker-compose.yml | 8 +++++++- manage.py | 52 ---------------------------------------------------- 2 files changed, 7 insertions(+), 53 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 05867a46..eb987624 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,11 @@ services: POSTGRES_DB: pysite POSTGRES_PASSWORD: pysite POSTGRES_USER: pysite + healthcheck: + test: ["CMD-SHELL", "pg_isready -U pysite"] + interval: 2s + timeout: 1s + retries: 5 volumes: - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql @@ -35,7 +40,8 @@ services: ports: - "127.0.0.1:8000:8000" depends_on: - - postgres + postgres: + condition: service_healthy tty: true volumes: - .:/app:ro diff --git a/manage.py b/manage.py index d8258281..578f4748 100755 --- a/manage.py +++ b/manage.py @@ -1,9 +1,6 @@ #!/usr/bin/env python import os -import socket import sys -import time -from urllib.parse import SplitResult, urlsplit import django from django.contrib.auth import get_user_model @@ -54,21 +51,6 @@ class SiteManager: os.environ.setdefault("DEBUG", "true") print("Starting in debug mode.") - @staticmethod - def parse_db_url(db_url: str) -> SplitResult: - """Validate and split the given databse url.""" - db_url_parts = urlsplit(db_url) - if not all(( - db_url_parts.hostname, - db_url_parts.username, - db_url_parts.password, - db_url_parts.path - )): - raise ValueError( - "The DATABASE_URL environment variable is not a valid PostgreSQL database URL." - ) - return db_url_parts - @staticmethod def create_superuser() -> None: """Create a default django admin super user in development environments.""" @@ -98,36 +80,6 @@ class SiteManager: else: print(f"Existing bot token found: {token}") - @staticmethod - def wait_for_postgres() -> None: - """Wait for the PostgreSQL database specified in DATABASE_URL.""" - print("Waiting for PostgreSQL database.") - - # Get database URL based on environmental variable passed in compose - database_url_parts = SiteManager.parse_db_url(os.environ["DATABASE_URL"]) - domain = database_url_parts.hostname - # Port may be omitted, 5432 is the default psql port - port = database_url_parts.port or 5432 - - # Attempt to connect to the database socket - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - attempts_left = 10 - while attempts_left: - try: - # Ignore 'incomplete startup packet' - s.connect((domain, port)) - s.shutdown(socket.SHUT_RDWR) - print("Database is ready.") - break - except socket.error: - attempts_left -= 1 - print("Not ready yet, retrying.") - time.sleep(0.5) - else: - print("Database could not be found, exiting.") - sys.exit(1) - @staticmethod def set_dev_site_name() -> None: """Set the development site domain in admin from default example.""" @@ -197,10 +149,6 @@ class SiteManager: def main() -> None: """Entry point for Django management script.""" - # Always run metricity init when in CI, indicated by the CI env var - if os.environ.get("CI", "false").lower() == "true": - SiteManager.wait_for_postgres() - # Use the custom site manager for launching the server if len(sys.argv) > 1 and sys.argv[1] == "run": SiteManager(sys.argv).run_server() -- cgit v1.2.3 From 2bf473ea1c22ea28de9cbc7a842c465a2f931b3c Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sat, 18 Sep 2021 18:16:35 -0400 Subject: Remove code jam notice from front page --- pydis_site/templates/home/index.html | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html index 072e3817..8e52274d 100644 --- a/pydis_site/templates/home/index.html +++ b/pydis_site/templates/home/index.html @@ -9,21 +9,14 @@ {% block content %} {% include "base/navbar.html" %} - -
- - Summer Code Jam 2021 - -
-
-
+
{# Embedded Welcome video #} -
+
- - {# Code Jam banner #} -
- - Summer Code Jam 2021 - -
-- cgit v1.2.3 From a7afdf4f8742a3f3f61883e92604d0fe08c8f199 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sat, 18 Sep 2021 18:26:32 -0400 Subject: Update wording on main Events page --- pydis_site/templates/events/index.html | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pydis_site/templates/events/index.html b/pydis_site/templates/events/index.html index daad1c9c..352a3aa9 100644 --- a/pydis_site/templates/events/index.html +++ b/pydis_site/templates/events/index.html @@ -9,11 +9,8 @@ {% block event_content %}

Code Jams

-
- The 2021 Summer Code Jam qualifier will open June 21st. Check out the details here. -
-

Each year, we organize a Winter Code Jam and a Summer Code Jam. During these events, members of our community will work together in teams to create something amazing using a technology we picked for them. One such technology that was picked for the Winter Code Jam 2020 was Kivy, a cross-platform GUI framework.

-

To help fuel the creative process, we provide a specific theme, like Ancient Technology or This App Hates You. At the end of the Code Jam, the projects are judged by Python Discord server staff members and guest judges from the larger Python community. The judges will consider creativity, code quality, teamwork, and adherence to the theme.

+

Each year, we organize at least one code jam, one during the summer and sometimes one during the winter. During these events, members of our community will work together in teams to create something amazing using a technology we picked for them. One such technology that was picked for the Summer 2021 Code Jam was text user interfaces (TUIS), where teams could pick from a pre-approved list of frameworks.

+

To help fuel the creative process, we provide a specific theme, like Think Outside the Box or Early Internet. At the end of the Code Jam, the projects are judged by Python Discord server staff members and guest judges from the larger Python community. The judges will consider creativity, code quality, teamwork, and adherence to the theme.

If you want to read more about Code Jams, visit our Code Jam info page or watch this video showcasing the best projects created during the Winter Code Jam 2020: Ancient Technology:

@@ -121,6 +118,5 @@ {% endblock %} {% block sidebar %} - {% include "events/sidebar/ongoing-event.html" %} {% include "events/sidebar/events-list.html" %} {% endblock %} -- cgit v1.2.3 From d7d0f2de54720c257d066fce1bcfc5c66dde2d89 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sat, 18 Sep 2021 18:34:51 -0400 Subject: Update events featured Re-ordered and updated the events listed on the main events page. We're no longer participating in Hacktoberfest, so that was removed. Game jams was moved to the bottom as we have not hosted one and will not for the forseeable future. PyWeek was moved above Advent of Code because AoC is one of the last events we do in the year so it didn't make sense to have PyWeek below it. This also updated the Events Calendar on the sidebar to be accurate for 2021. --- pydis_site/templates/events/index.html | 64 +++++++--------------- .../templates/events/sidebar/events-list.html | 10 ++-- 2 files changed, 26 insertions(+), 48 deletions(-) diff --git a/pydis_site/templates/events/index.html b/pydis_site/templates/events/index.html index 352a3aa9..b5c556e5 100644 --- a/pydis_site/templates/events/index.html +++ b/pydis_site/templates/events/index.html @@ -16,48 +16,27 @@
-

Game Jam

+

PyWeek

- The Game Jam is similar to our Code Jams, but smaller in scope. Instead of having to complete a qualifier - and being teamed up with random strangers, members of our community can just sign-up individually or pair up - with whoever they like. -

-

- The participants will have ten days to create a game using the technology we've selected, and drawing - inspiration from a provided theme. After the event, a panel of judges will play all the games and select a - winner. The top 5 will featured in a special video on our YouTube channel. -

-

- The first edition of the Game Jam ran from - April 17, 2020 to April 26, 2020. + For the past 15 years, PyWeek has been running a bi-annual game jam for the + Python language. As of 2020, we are excited to say we are officially partnered with PyWeek to co-run these + events.

-
-
- -
-
-
- -
-

Hacktoberfest

-
-

- This event revolves around the annual Hacktoberfest - event organized by Digital Ocean. In addition to promoting Hacktoberfest in our community and supporting - those who choose to take their first steps into the world of open source, we will also ease our members into - contributing to open source by starting a low-entry, beginner-friendly open source project where we will - guide our members through the open source process in a safe environment. + During each PyWeek event, we open a special discussion channel in which our members can discuss their + submissions, meet other participants, and talk to PyWeek staff. The PyWeek organizer, + Daniel Pope (@lordmauve) will be present during the entire event to answer + questions and post announcements and information in our community.

- The exact form this event will take has not been decided yet, but we'll make sure to keep you updated in - our community announcements! + Unlike our other events, the community will select the winner from all the submissions + during PyWeek. We may release YouTube content showcasing the best submissions after the events are finished.

- +
@@ -91,27 +70,26 @@
-

PyWeek

+

Game Jam

- For the past 15 years, PyWeek has been running a bi-annual game jam for the - Python language. As of 2020, we are excited to say we are officially partnered with PyWeek to co-run these - events. + The Game Jam is similar to our Code Jams, but smaller in scope. Instead of having to complete a qualifier + and being teamed up with random strangers, members of our community can just sign-up individually or pair up + with whoever they like.

- During each PyWeek event, we open a special discussion channel in which our members can discuss their - submissions, meet other participants, and talk to PyWeek staff. The PyWeek organizer, - Daniel Pope (@lordmauve) will be present during the entire event to answer - questions and post announcements and information in our community. + The participants will have ten days to create a game using the technology we've selected, and drawing + inspiration from a provided theme. After the event, a panel of judges will play all the games and select a + winner. The top 5 will featured in a special video on our YouTube channel.

- Unlike our other events, the community will select the winner from all the submissions - during PyWeek. We may release YouTube content showcasing the best submissions after the events are finished. + The first edition of the Game Jam ran from + April 17, 2020 to April 26, 2020.

- +
diff --git a/pydis_site/templates/events/sidebar/events-list.html b/pydis_site/templates/events/sidebar/events-list.html index 327b0e77..6029ae74 100644 --- a/pydis_site/templates/events/sidebar/events-list.html +++ b/pydis_site/templates/events/sidebar/events-list.html @@ -1,10 +1,10 @@ -- cgit v1.2.3 From c4731bfe1ed27ee8047fa9226158e927ec8600f7 Mon Sep 17 00:00:00 2001 From: Janine vN Date: Sat, 18 Sep 2021 19:13:20 -0400 Subject: Update Code Jam 8 as a finished event This commit adds in the information about the winners of the code jam. Additionally, it adds in Code Jam 8 as a prior event in the sidebar. --- .../templates/events/pages/code-jams/8/_index.html | 52 +++++++++++++++++++--- .../sidebar/code-jams/previous-code-jams.html | 1 + 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/pydis_site/templates/events/pages/code-jams/8/_index.html b/pydis_site/templates/events/pages/code-jams/8/_index.html index 55bdc95b..c789adef 100644 --- a/pydis_site/templates/events/pages/code-jams/8/_index.html +++ b/pydis_site/templates/events/pages/code-jams/8/_index.html @@ -20,6 +20,50 @@ and walking through the program that your team has created.

+

Code Jam Winners

+

Congratulations to our winners and the two runner ups! Check out their projects below.

+

Perceptive Porcupines: WTPython!?

+

VV, Poppinawhile, ethansocal, Jeff Z, Cohan, ¯\_(ツ)_/¯

+

+ What the Python (wtpython) is a simple terminal user interface that allows you to explore relevant answers on Stackoverflow without leaving your terminal or IDE. When you get an error, all you have to do is swap python for wtpython. When your code hits an error, you'll see a textual interface for exploring relevant answers allowing you to stay focused and ship faster! +
+ Demo video +
+ Githib Repository +
+ +

+ +

Lovable Lobsters: Ultimate Tic Tac Toe

+

A5Rocks, Bast, Dacheat, mega_hirtz, CopOnTheRun, richphi

+

+ Thinking inside a box, that is inside a box, that is inside yet another box. + + The terminal program created by the Lovable Lobsters allows you to play Ultimate Tic Tac Toe right form your terminal. The really impressive part though? You can play with your friends and family over your network! Their program has a server-client set-up that lets you play with your friends and family from different computers. +
+ Demo video +
+ Githib Repository +
+

+ +

Robust Reindeer: Rubick's Cube

+

Björn, aaronshenhao, mathsman, Dude Saber, 詭異, Keppo

+

+ This submission is a Rubik's cube, rendered in a text user interface (that was a constraint) using the asciimatics package, and addressing the theme "thinking inside the box". + + Just like a real world Rubik's cube, you can move this cube around to look at it from all sides. And, of course, you can rotate the individual discs it is made up of to first scramble up the order and then to try and solve it into perfect ordering again. +
+ Githib Repository +
+

+ +

Submissions

+

+ 63 teams started out on July 9th 2021. By the end of the jam, 51 teams made project submissions. Check them all out here: +

+

+

Important Dates

  • Tuesday, June 15 - Form to submit theme suggestions opens
  • @@ -43,7 +87,7 @@ The qualifier is a coding challenge that you are required to complete before registering for the code jam. This is meant as a basic assessment of your skills to ensure you have enough python knowledge to effectively contribute in a team environment.

    -

    View the Qualifier

    View the Qualifier

    Please note the requirements for the qualifier.

      @@ -52,11 +96,7 @@
    • The Qualifier must be submitted through the Code Jam sign-up form.

    -

    Submissions

    -

    - 63 teams started out on July 9th 2021. By the end of the jam, 51 teams made project submissions. Check them all out here: -

    -

    +

    Prizes

    Our Code Jam Sponsors have provided prizes for the winners of the code jam. diff --git a/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html b/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html index 9f9ecd1a..393eec6f 100644 --- a/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html +++ b/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html @@ -1,6 +1,7 @@

    - +
    diff --git a/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html b/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html index 393eec6f..21b2ccb4 100644 --- a/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html +++ b/pydis_site/templates/events/sidebar/code-jams/previous-code-jams.html @@ -1,7 +1,7 @@
    Microsoft's Python Development Team also runs a Discord Server for discussions of Python in the Microsoft ecosystem, including Visual Studio Code and Azure. -title_image: http://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE2qVsJ?ver=3f74 +title_image: https://img-prod-cms-rt-microsoft-com.akamaized.net/cms/api/am/imageFileData/RE2qVsJ?ver=3f74 position: 4 urls: - icon: branding/youtube diff --git a/pydis_site/settings.py b/pydis_site/settings.py index d2cd8698..8d092ac9 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -201,7 +201,7 @@ else: PARENT_HOST = env('PARENT_HOST', default='pythondiscord.com') # Django REST framework -# http://www.django-rest-framework.org +# https://www.django-rest-framework.org REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', diff --git a/pydis_site/templates/base/navbar.html b/pydis_site/templates/base/navbar.html index d7cb49b2..ed04995c 100644 --- a/pydis_site/templates/base/navbar.html +++ b/pydis_site/templates/base/navbar.html @@ -44,7 +44,7 @@ {# Patreon #} - +  Patreon diff --git a/pydis_site/templates/events/pages/code-jams/8/frameworks.html b/pydis_site/templates/events/pages/code-jams/8/frameworks.html index 34ac4f0a..1c02e38a 100644 --- a/pydis_site/templates/events/pages/code-jams/8/frameworks.html +++ b/pydis_site/templates/events/pages/code-jams/8/frameworks.html @@ -19,7 +19,7 @@
      -
    • Documentation Link
    • +
    • Documentation Link
    • Supports: Linux, Mac, other unix-like OS
    • Somewhat in-depth tutorial
    • Uses widgets in a fairly straight forward design
    • -- cgit v1.2.3 From b8466fcbb3325b590c4b6ebe508ee35d02dc4b6a Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Wed, 6 Oct 2021 02:17:14 +0400 Subject: Properly Resize Sponsor Logos Ensure sponsor logos don't go past the edge of the screen, and maintain aspect ratio when sized down. Signed-off-by: Hassan Abouelela --- pydis_site/static/css/home/index.css | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pydis_site/static/css/home/index.css b/pydis_site/static/css/home/index.css index ee6f6e4c..7ec8af74 100644 --- a/pydis_site/static/css/home/index.css +++ b/pydis_site/static/css/home/index.css @@ -215,12 +215,20 @@ h1 { } #sponsors .columns { + display: block; justify-content: center; margin: auto; max-width: 80%; } +#sponsors a { + margin: auto; + display: inline-block; +} + #sponsors img { - height: 5rem; - margin: auto 1rem; + width: auto; + height: auto; + + max-height: 5rem; } -- cgit v1.2.3 From bc1aae035a25dca1a894e22421f493175edebac2 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Wed, 6 Oct 2021 02:18:39 +0400 Subject: Adds Netlify To Sponsors Signed-off-by: Hassan Abouelela --- pydis_site/static/images/sponsors/netlify.png | Bin 0 -> 177462 bytes pydis_site/templates/home/index.html | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 pydis_site/static/images/sponsors/netlify.png diff --git a/pydis_site/static/images/sponsors/netlify.png b/pydis_site/static/images/sponsors/netlify.png new file mode 100644 index 00000000..0f14f385 Binary files /dev/null and b/pydis_site/static/images/sponsors/netlify.png differ diff --git a/pydis_site/templates/home/index.html b/pydis_site/templates/home/index.html index 8e52274d..77037ef8 100644 --- a/pydis_site/templates/home/index.html +++ b/pydis_site/templates/home/index.html @@ -187,6 +187,10 @@ StreamYard + + + Netlify + Cloudflare -- cgit v1.2.3 From 81054bdd73c937f184fef828a8f3bacd6d30caaa Mon Sep 17 00:00:00 2001 From: Kronifer <44979306+Kronifer@users.noreply.github.com> Date: Tue, 5 Oct 2021 18:14:02 -0500 Subject: Merge Gitpod Docs (#594) docs: Added site documentation for editing on Gitpod --- .../resources/guides/pydis-guides/contributing/sir-lancebot.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md index 068b08ae..60169c01 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/contributing/sir-lancebot.md @@ -16,6 +16,15 @@ toc: 1 - [MacOS Installer](https://git-scm.com/download/mac) or `brew install git` - [Linux](https://git-scm.com/download/linux) +## Using Gitpod +Sir Lancebot can be edited and tested on Gitpod. Gitpod will automatically install the correct dependencies and Python version, so you can get straight to coding. +To do this, you will need a Gitpod account, which you can get [here](https://www.gitpod.io/#get-started), and a fork of Sir Lancebot. This guide covers forking the repository [here](#fork-the-project). Afterwards, either click the button on Sir Lancebot's README or go to [https://gitpod.io/#/python-discord/sir-lancebot]() and run the following commands in the terminal: +```sh +git remote rename origin upstream +git add remote origin https://github.com/{your_username}/sir-lancebot +``` +Make sure you replace `{your_username}` with your Github username. These commands will set Python Discord as the parent repository, and your branch as the fork. This means you can easily grab new changes from the parent repository. Once you set your environment variables to test your code, you are ready to begin contributing to Sir Lancebot. + ## Using Docker Sir Lancebot can be started using Docker. Using Docker is generally recommended (but not strictly required) because it abstracts away some additional set up work. -- cgit v1.2.3 From 8f596f3b5fd44a502efccc021ab4c50908da3d67 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Wed, 6 Oct 2021 00:18:37 +0100 Subject: Add www.pythondiscord.com to ALLOWED_HOSTS (#601) --- pydis_site/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pydis_site/settings.py b/pydis_site/settings.py index d2cd8698..656676da 100644 --- a/pydis_site/settings.py +++ b/pydis_site/settings.py @@ -55,6 +55,7 @@ else: ALLOWED_HOSTS = env.list( 'ALLOWED_HOSTS', default=[ + 'www.pythondiscord.com', 'pythondiscord.com', 'admin.pythondiscord.com', 'api.pythondiscord.com', -- cgit v1.2.3 From b5b49ef0ea9209ecc140302879383b619e694541 Mon Sep 17 00:00:00 2001 From: Joe Banks Date: Wed, 6 Oct 2021 00:35:59 +0100 Subject: Update hosts.py to default to www --- pydis_site/hosts.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pydis_site/hosts.py b/pydis_site/hosts.py index 5a837a8b..719e93cf 100644 --- a/pydis_site/hosts.py +++ b/pydis_site/hosts.py @@ -9,5 +9,6 @@ host_patterns = patterns( # Internal API ingress (cluster local) host(r'pydis-api', 'pydis_site.apps.api.urls', name='internal_api'), host(r'staff', 'pydis_site.apps.staff.urls', name='staff'), - host(r'.*', 'pydis_site.apps.home.urls', name=settings.DEFAULT_HOST) + host(r'www', 'pydis_site.apps.home.urls', name=settings.DEFAULT_HOST), + host(r'.*', 'pydis_site.apps.home.urls', name="fallback") ) -- cgit v1.2.3