From e235a806bf740656ccd8ed288420c4ff63158569 Mon Sep 17 00:00:00 2001 From: Florent 'Skia' Jacquet Date: Thu, 7 May 2026 17:27:48 +0200 Subject: [PATCH 1/3] charm: add basic Makefile --- charm/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 charm/Makefile diff --git a/charm/Makefile b/charm/Makefile new file mode 100644 index 0000000..b8911e1 --- /dev/null +++ b/charm/Makefile @@ -0,0 +1,9 @@ +BASE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +.PHONY: tests pack + +pack: + charmcraft pack --project-dir $(BASE_DIR).. + +tests: + uv run --all-extras pytest -o log_cli=1 -v --log-level=INFO --pdb --charm-path ../error-tracker_ubuntu@24.04-amd64.charm tests/ From f6d9273a40267f461eff6bc6f04646e46acd4bde Mon Sep 17 00:00:00 2001 From: Florent 'Skia' Jacquet Date: Thu, 7 May 2026 17:29:01 +0200 Subject: [PATCH 2/3] errors: better default settings --- .gitignore | 2 ++ src/errors/settings.py | 25 +++++++++++++++++-------- src/errortracker/config.py | 7 ++++++- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 77369fc..84e30ee 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,8 @@ local_config.py db.sqlite3 db.sqlite3-journal src/static +src/errors/errors.sqlite +src/errors/.errors_secret_key # Flask stuff: instance/ diff --git a/src/errors/settings.py b/src/errors/settings.py index b3e2ec3..00d0a23 100644 --- a/src/errors/settings.py +++ b/src/errors/settings.py @@ -1,13 +1,15 @@ # Django settings for errors project. -import os +import random +import string +from pathlib import Path from errortracker import config ALLOWED_HOSTS = ["*"] -PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) +PROJECT_ROOT = Path(__file__).absolute().parent -DEBUG = True +DEBUG = config.errors_debug WSGI_APPLICATION = "errors.wsgi.application" @@ -23,14 +25,14 @@ DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", - "NAME": os.path.join(os.environ.get("XDG_RUNTIME_DIR", "/tmp"), "errors.sqlite"), + "NAME": str(PROJECT_ROOT / "errors.sqlite"), } } # Absolute path to the directory static files should be collected to. # Don't put anything in this directory yourself; store your static files # in apps' "static/" subdirectories and in STATICFILES_DIRS. -STATIC_ROOT = os.path.join(PROJECT_ROOT, "../static") +STATIC_ROOT = str(PROJECT_ROOT / "../static") # URL prefix for static files. STATIC_URL = "/static/" @@ -40,7 +42,7 @@ # Put strings here, like "/home/html/static" or "C:/www/django/static". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. - os.path.join(PROJECT_ROOT, "static"), + str(PROJECT_ROOT / "static"), ] # List of finder classes that know how to find static files in @@ -51,7 +53,14 @@ ] # Make this unique, and don't share it with anybody. -SECRET_KEY = config.errors_secret_key +secret_key_path = PROJECT_ROOT / ".errors_secret_key" +try: + SECRET_KEY = secret_key_path.read_text() +except Exception: + SECRET_KEY = "".join( + random.SystemRandom().choice(string.ascii_letters + string.digits) for _ in range(32) + ) + secret_key_path.write_text(SECRET_KEY) MIDDLEWARE = ( "django.middleware.common.CommonMiddleware", @@ -71,7 +80,7 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [os.path.join(PROJECT_ROOT, "templates")], + "DIRS": [str(PROJECT_ROOT / "templates")], "OPTIONS": { "context_processors": [ "django.template.context_processors.request", diff --git a/src/errortracker/config.py b/src/errortracker/config.py index 3cb7788..e6c89f9 100644 --- a/src/errortracker/config.py +++ b/src/errortracker/config.py @@ -51,8 +51,13 @@ # Path used to keep some crashes in case of failure, for manual investigation failure_storage = None -errors_secret_key = "hellotheregeneralkenobi" +# Is the Django app running in debug mode +errors_debug = True + +# Allow the Django app to fill bugs allow_bug_filing = True + +# Some variable still used by the launchpad.py module lp_oauth_token = "todofixme" lp_oauth_secret = "todofixme" lp_use_staging = True From f4624e1bc2e00f7529a62843c60a491978dd744e Mon Sep 17 00:00:00 2001 From: Florent 'Skia' Jacquet Date: Thu, 7 May 2026 17:34:57 +0200 Subject: [PATCH 3/3] charm: errors: also test some static files --- charm/tests/integration/test_errors.py | 37 +++++++++++++++----------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/charm/tests/integration/test_errors.py b/charm/tests/integration/test_errors.py index aa90b73..8fc7a49 100644 --- a/charm/tests/integration/test_errors.py +++ b/charm/tests/integration/test_errors.py @@ -55,19 +55,24 @@ def test_http(juju: jubilant.Juju): session = Session() session.mount("https://", DNSResolverHTTPSAdapter(external_hostname, haproxy_ip)) - # Let give this test a few chances to succeed, as it can sometimes be a bit - # early and hit 503 - for attempt in Retrying( - stop=stop_after_attempt(10), - wait=wait_exponential(min=5, max=30), - reraise=True, - ): - with attempt: - response = session.get( - f"https://{haproxy_ip}/", - headers={"Host": external_hostname}, - verify=False, - timeout=30, - ) - assert response.status_code == 200 - assert "We collect hundreds of thousands of error reports daily" in response.text + for uri, content in [ + ("/", "We collect hundreds of thousands of error reports daily"), + ("/static/css/main.css", "body {"), + ("/static/js/yui/build/yui/yui-min.js", "/* YUI 3.9.0 (build 5827)"), + ]: + # Let give this test a few chances to succeed, as it can sometimes be a bit + # early and hit 503 + for attempt in Retrying( + stop=stop_after_attempt(10), + wait=wait_exponential(min=5, max=30), + reraise=True, + ): + with attempt: + response = session.get( + f"https://{haproxy_ip}{uri}", + headers={"Host": external_hostname}, + verify=False, + timeout=30, + ) + assert response.status_code == 200 + assert content in response.text