From 775e1abede896836e2406fe3bf8cdb66c0953c2a Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Mon, 20 May 2024 16:18:54 +0200 Subject: [PATCH 01/44] health check token docs --- deployment/production-checklist.md | 14 +++++++++++++- release-notes.md | 4 +++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/deployment/production-checklist.md b/deployment/production-checklist.md index 18c828e..b31efc2 100644 --- a/deployment/production-checklist.md +++ b/deployment/production-checklist.md @@ -51,6 +51,7 @@ Ensure that you have configured the following variables (if you are using them): `STRIPE_LIVE_PUBLIC_KEY`, and `STRIPE_LIVE_SECRET_KEY` config vars (or whatever subset you are using). - If you set up email, ensure whatever keys/secrets you need are set. - If you're using Mailchimp, set `MAILCHIMP_API_KEY` and `MAILCHIMP_LIST_ID`. +- If you're using Health Checks, set `HEALTH_CHECK_TOKENS`. Refer to your [chosen platform's documentation](/deployment.rst) for details on how to set environment variables in that platform. @@ -104,7 +105,18 @@ see any errors that are encountered. It's also recommended to enable the health check endpoint and connect it to a monitoring tool like [StatusCake](https://www.statuscake.com/) or [Uptime Robot](https://uptimerobot.com/) so that you can be alerted whenever your site or services are having an outage. -The URL you should connect is: yourdomain.com/health/. +The URL you should connect is: `yourdomain.com/health/`. + +If you have the "Health Check Endpoint" option enabled for your project you should also ensure that +you have set the `HEALTH_CHECK_TOKENS` environment variable to a secure value. This can be a comma-separated +list of tokens that are required to access the health check endpoint: + +``` +yourdomain.com/health/?token=your_secret_token +``` + +You can then use this URL with the monitoring tool to ensure that only your monitoring tool can +access the health check endpoint. ## Double-check your language settings diff --git a/release-notes.md b/release-notes.md index 234dc6f..ef82da1 100644 --- a/release-notes.md +++ b/release-notes.md @@ -49,6 +49,9 @@ and Celery workers and returns a non-200 response code if there are any identifi These endpoints can be connected to a monitoring tool like [StatusCake](https://www.statuscake.com/) or [Uptime Robot](https://uptimerobot.com/) so that you can be alerted whenever your site is having issues. +See the section on [monitoring](./deployment/production-checklist.md#set-up-monitoring) in the +production checklist for more information. + ### Allauth updates The [django-allauth](https://docs.allauth.org/en/latest/) library was updated to the latest version, @@ -3426,4 +3429,3 @@ Documentation for subscriptions can be [found here](/subscriptions). ## Version 0.4 and earlier Release notes for earlier versions are no longer publicly available. - From 51a801304a4aed8076f89230fc1dc6af021d3ab3 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 14 May 2024 09:08:27 +0200 Subject: [PATCH 02/44] release notes dump --- release-notes.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/release-notes.md b/release-notes.md index ef82da1..18fc718 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,17 @@ Version History and Release Notes Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus.com/) are documented here. +## Next Release + +- Remove `static/css` and `static/js` directories from the `dockerignore` file so that other project files + can be included. Also updated the production Docker build process so that any existing files are overwritten + by the built versions. (Thanks Raul for reporting!) +- Made some performance improvements to the production Dockerfile build + (don't rebuilding front end if there are no changes in the dependent files). +- Changed behavior when team role checks fail from raising a `TeamPermissionError` to returning a 403 response, + and updated affected tests. This also removes confusing stack traces from successful test runs. +- Removed no longer used `TeamPermissionError` class. + ## Version 2024.5.2 This is a hotfix release that fixes a bug that prevented the team management page From 05474ccfaad96a283263ff186e83cd53c5730b22 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 21 May 2024 10:07:20 +0200 Subject: [PATCH 03/44] add release note --- release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release-notes.md b/release-notes.md index 18fc718..a68ae4a 100644 --- a/release-notes.md +++ b/release-notes.md @@ -13,6 +13,7 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - Changed behavior when team role checks fail from raising a `TeamPermissionError` to returning a 403 response, and updated affected tests. This also removes confusing stack traces from successful test runs. - Removed no longer used `TeamPermissionError` class. +- Fixed a bug where team names longer than 50 characters could cause a crash during sign up. ## Version 2024.5.2 From bb282d7d952c9708cd5f2820871f457c5d92ead8 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 21 May 2024 10:09:09 +0200 Subject: [PATCH 04/44] add release notes for 2024.5.3 --- release-notes.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/release-notes.md b/release-notes.md index 234dc6f..abe267f 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,13 @@ Version History and Release Notes Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus.com/) are documented here. +## Version 2024.5.3 + +This is a hotfix release that fixes a bug where the landing and dashboard page image was accidentally +removed if you built without the examples enabled. + +*May 21, 2024* + ## Version 2024.5.2 This is a hotfix release that fixes a bug that prevented the team management page From 4325c9fe39100aeec24df7e52c751f55f1dd76cc Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 22 May 2024 13:40:28 +0200 Subject: [PATCH 05/44] add pricing table video --- subscriptions.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/subscriptions.md b/subscriptions.md index 501cae6..f4ae75e 100644 --- a/subscriptions.md +++ b/subscriptions.md @@ -89,6 +89,14 @@ If you've set things up correctly you should see a page that looks like this ### Using the embedded Stripe pricing table +The following 5-minute video walks through setting up an embedded pricing table in your project. + +
+ +
+ +Here are the detailed instructions: + If you are using the Stripe embedded pricing table, then all customization happens within the Stripe dashboard. You can change the products, names, descriptions, images, and features by editing the products in Stripe with the desired changes. You can also change the color scheme and other options. From 639f6929e8220f7e75b59d653af77473f099e549 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 22 May 2024 13:43:21 +0200 Subject: [PATCH 06/44] s3 media --- configuration.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configuration.md b/configuration.md index 47fc403..cb23747 100644 --- a/configuration.md +++ b/configuration.md @@ -358,6 +358,12 @@ you to have persistent storage available for your site such as a Docker volume. ### Setting up S3 media storage +*For a video walkthrough of this content (using kamal deployment), see below:* + +
+ +
+ This section assumes you have set up your SaaS Pegasus project with the **S3 media file storage** enabled. In order to use S3 for media storage you will need to create an S3 bucket and provide authentication From 116a12c4c1bb95f6e76e034ef8cd2c0b60eae131 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 22 May 2024 13:59:19 +0200 Subject: [PATCH 07/44] qr bugfix --- release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release-notes.md b/release-notes.md index 402d80f..269d33e 100644 --- a/release-notes.md +++ b/release-notes.md @@ -14,6 +14,7 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. and updated affected tests. This also removes confusing stack traces from successful test runs. - Removed no longer used `TeamPermissionError` class. - Fixed a bug where team names longer than 50 characters could cause a crash during sign up. +- Fixed a bug where 2fa QR codes had a dark background when dark mode was enabled. ## Version 2024.5.3 From a76578eba56f8e652ae20fed477e4de187d3873a Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Sat, 25 May 2024 16:58:25 +0200 Subject: [PATCH 08/44] more release notes --- release-notes.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/release-notes.md b/release-notes.md index 269d33e..568708d 100644 --- a/release-notes.md +++ b/release-notes.md @@ -15,6 +15,12 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - Removed no longer used `TeamPermissionError` class. - Fixed a bug where team names longer than 50 characters could cause a crash during sign up. - Fixed a bug where 2fa QR codes had a dark background when dark mode was enabled. +- Make Team IDs optional on the create team page (HTMX builds). +- Switch celerybeat to use the database instead of the filesystem for the scheduler, which makes it work more reliably + on docker-based systems like Kamal. (Thanks Peter and Artem for the suggestion!) +- Add display and sort on the number of active members in the teams admin. +- Fixed a bug where creating an API key crashed if your user's first + last name combined to more than 40 characters. + (Thanks Luc for reporting!) ## Version 2024.5.3 From 23045dbe4a43b349dacefa93ea67510e0223f85a Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Sat, 25 May 2024 16:58:35 +0200 Subject: [PATCH 09/44] update docs --- configuration.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/configuration.md b/configuration.md index cb23747..6d154c1 100644 --- a/configuration.md +++ b/configuration.md @@ -106,8 +106,11 @@ The domain name of this `Site` will be used for your server address. If you need to change the URL after installation, you can go to the site admin at `admin/sites/site/` and modify the values accordingly, leaving off any http/https prefix. -In development you'll typically want a domain name of `localhost:8000`, and in production this should +In development, you'll typically want a domain name of `localhost:8000`, and in production this should be the domain where your users access your app. +Note that this URL must match *exactly* what is in the browser address bar. +So, for example, if you load your development site from `127.0.0.1:8000` instead of `localhost:8000` then +that is what you should put in. **Example Development Configuration** From f25d89303fb31ecfc743ca1e554a770489363aec Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 4 Jun 2024 16:16:16 +0200 Subject: [PATCH 10/44] draft release notes for 2024.6 --- release-notes.md | 98 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 13 deletions(-) diff --git a/release-notes.md b/release-notes.md index 568708d..91406de 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,25 +3,97 @@ Version History and Release Notes Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus.com/) are documented here. -## Next Release +## Version 2024.6 + +This is a feature release with a few bigger updates. + +### AI model changes + +Use LiteLLM instead of LLM. Docs. + +### Spam prevention updates + +Turnstile TODO docs + +### Ruff support + import removal + +TODO docs + +### Added + +- Added configurable captcha support on sign up pages, using [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/). + See updated documentation TODO +- Added API views for two-factor authentication, and to change the logged-in user's password. (Thanks Finbar for suggesting!) +- Add UI to tell users they need a verified email address prior to setting up two-factor auth. + - Also added a `has_verified_email` helper class to the `CustomUser` model. +- Added tests for the delete team view for both team admins and members. (HTMX builds only) +- Added test for team member removal permissions. + +### Fixed -- Remove `static/css` and `static/js` directories from the `dockerignore` file so that other project files - can be included. Also updated the production Docker build process so that any existing files are overwritten - by the built versions. (Thanks Raul for reporting!) -- Made some performance improvements to the production Dockerfile build - (don't rebuilding front end if there are no changes in the dependent files). -- Changed behavior when team role checks fail from raising a `TeamPermissionError` to returning a 403 response, - and updated affected tests. This also removes confusing stack traces from successful test runs. -- Removed no longer used `TeamPermissionError` class. - Fixed a bug where team names longer than 50 characters could cause a crash during sign up. -- Fixed a bug where 2fa QR codes had a dark background when dark mode was enabled. -- Make Team IDs optional on the create team page (HTMX builds). -- Switch celerybeat to use the database instead of the filesystem for the scheduler, which makes it work more reliably - on docker-based systems like Kamal. (Thanks Peter and Artem for the suggestion!) +- Fixed a bug where multi-factor authentication QR codes had a dark background when dark mode was enabled (Tailwind builds only). + (Thanks Artem for reporting!) +- Fixed a bug where it was possible to bypass two-factor-authentication when using the API authentication views. + (Thanks Finbar for reporting and helping with the fix!) - Add display and sort on the number of active members in the teams admin. +- Fixed a bug where deleting the user's only team while impersonating them resulted in a temporary crash. + (Thanks EJ for reporting!) - Fixed a bug where creating an API key crashed if your user's first + last name combined to more than 40 characters. (Thanks Luc for reporting!) + +### Changed + +- Non-OpenAI builds now use `litellm` instead of `llm`. TODO more. +- **Changed the formatter/linter from `black` and `isort` to [ruff](https://github.com/astral-sh/ruff).** + - Also addressed a handful of minor linting errors that came up as a result of this change. + Codebase linting is now substantially faster. +- Removed the `static/css` and `static/js` directories from the `dockerignore` file so that other project files + can be included. Also updated the production Docker build process so that any existing files are overwritten + by the built versions. (Thanks Raul for reporting!) +- Made some performance improvements to the production Dockerfile build (don't rebuild the front end if there are + no changes in the dependent files). +- The login API response has changed, to allow for two-factor auth prompts, and more machine-readable status fields. +- **Upgraded all Python packages to the latest versions.** +- **Upgraded all JavaScript packages to the latest versions.** +- Removed the no-longer-used `use_json_field=True` argument from wagtail `StreamField`s. +- The user dashboard no longer shows users with unconfirmed email addresses if you have set + `ACCOUNT_EMAIL_VERIFICATION = 'mandatory'`. This helps filter out likely bots from the report. +- The user dashboard now includes sign ups from the current date, by default. +- Better support trialing subscriptions with no payment methods. + The subscription UI will now show the date the trial ends and won't log errors about missing invoices. (Thanks Jarrett for reporting!) +- Changed behavior when team role checks fail from raising a `TeamPermissionError` to returning a 403 response, + and updated affected tests. One side effect of this is that the stack traces are removed from successful test runs. +- Secret keys should no longer change every time you build your Pegasus project. + They are also now clearly prefixed with `django-insecure-` to indicate that they should be changed in production. +- Updated the default OpenAI chat model to gpt-4o. +- Upgraded the openapi client generator to version 7.5.0 and also pinned the version used by `make build-api-client` + to the same one. +- **Celerybeat now uses the `django-celery-beat` library to store tasks in the database instead of on the filesystem.** + This improves support for celerybeat on Docker-based platforms. (Thanks Peter and Artem for the suggestion!) + - Also added a migration to save the default scheduled tasks in the database. +- Make Team IDs optional on the create team page (HTMX builds only). +- Add clearer error message when charts are broken due to api config issue. (Thanks Yngve for reporting!) +- Added `assume_scheme="https"` to form `URLField`s to be compatible with Django 6 behavior. +- Added `FORMS_URLFIELD_ASSUME_HTTPS = True` to be compatible with Django 6 behavior. +- Set `ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = False` by default, so that "forgot password" emails do not get sent to unknown accounts. + This can help prevent spam bots. + +### Removed + +- Removed `black` and `isort` from dev-requirements, since they have been replaced by `ruff`. +- Removed `llm` library and associated code, since it has been replaced by `litellm`. +- Removed no longer used `TeamPermissionError` class. + +### Standalone front end + +The following changes affect the experimental [standalone front end](./experimental/react-front-end.md): + +- The standalone React front end now supports two-factor-authentication. +- Improve the UI when you have login issues in the standalone React front end. + + ## Version 2024.5.3 This is a hotfix release that fixes a bug where the landing and dashboard page image was accidentally From a863d791c28b38f5bb73e4290692ff511baa7c81 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 4 Jun 2024 16:53:24 +0200 Subject: [PATCH 11/44] update defaults to gpt-4o --- ai.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ai.md b/ai.md index 2ef0b8d..01e5ed2 100644 --- a/ai.md +++ b/ai.md @@ -20,7 +20,7 @@ We recommend choosing "OpenAI" unless you know you want to use a different model ### Configuring OpenAI If you're using OpenAI, you need to set `OPENAI_API_KEY` in your environment or settings file (`.env` in development). -You can also change the model used by setting `OPENAI_MODEL`, which defaults to `"gpt-3.5-turbo"`. +You can also change the model used by setting `OPENAI_MODEL`, which defaults to `"gpt-4o"`. See [this page](https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key) for help finding your OpenAI API key. @@ -33,7 +33,7 @@ values in your `settings.py`. For example: ```python LLM_MODELS = { "gpt-3.5-turbo": {"api_key": env("OPENAI_API_KEY", default="")}, - "gpt4": {"api_key": env("OPENAI_API_KEY", default="")}, + "gpt-4o": {"api_key": env("OPENAI_API_KEY", default="")}, "claude-3-opus-20240229": {"api_key": env("ANTHROPIC_API_KEY", default="")}, "ollama_chat/llama3": {"api_base": env("OLLAMA_API_BASE", default="http://localhost:11434")}, # requires a running ollama instance } From 539a4ca6696c9b074cec6f7b9a2f7eb4af920f54 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 4 Jun 2024 16:53:35 +0200 Subject: [PATCH 12/44] add blurb about ollama --- release-notes.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index 91406de..4824d4c 100644 --- a/release-notes.md +++ b/release-notes.md @@ -9,7 +9,16 @@ This is a feature release with a few bigger updates. ### AI model changes -Use LiteLLM instead of LLM. Docs. +The library used for non-OpenAI LLMs was changed from [`llm`](https://github.com/simonw/llm) to [`litellm`](https://docs.litellm.ai/docs/). +Reasons for this change include: + +- It has far fewer additional dependencies. +- It supports async APIs out of the box. +- The `llm` library is optimized for the command line use-case, whereas `litellm` offers similar functionality as a native + Python library. + +Litellm can still be used with all common AI models, including OpenAI, Anthropic/Claude, and Meta/Llama models +(with ollama). For details on getting started with `litellm` see the updated [AI documentation](./ai.md). ### Spam prevention updates From 97e6b5a38941ae43dfd91a934f22ed568387262d Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 4 Jun 2024 16:53:54 +0200 Subject: [PATCH 13/44] update code formatting docs --- code-structure.md | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/code-structure.md b/code-structure.md index 956fc15..27d5209 100644 --- a/code-structure.md +++ b/code-structure.md @@ -83,7 +83,9 @@ The majority of the project's base template layouts are in the `templates/web` f ## Code formatting For projects that have enabled the `Autoformat code` option, the code will have been formatted -using [black](https://black.readthedocs.io/en/stable/) and [isort](https://pycqa.github.io/isort/). +using [ruff](https://github.com/astral-sh/ruff)—a drop-in replacement for +[black](https://black.readthedocs.io/en/stable/) and [isort](https://pycqa.github.io/isort/) that runs +much faster than those tools. The project will also include [pre-commit](https://pre-commit.com/) as a dependency in the requirements file as well as the `.pre-commit-config.yaml` file in the root directory. pre-commit is a tool for managing pre-commit @@ -96,19 +98,18 @@ $ pre-commit install --install-hooks pre-commit installed at .git/hooks/pre-commit ``` -The default configuration that ships with Pegasus will run `isort` and `black` prior to every Git +The default configuration that ships with Pegasus will run `ruff` and `ruff-format` prior to every Git commit. If there are fixes that are needed you will be notified in the shell output. ### pre-commit Usage **Manually running hooks** + ```shell # run all hooks against currently staged files pre-commit run # run all the hooks against all the files. This is a useful invocation if you are using pre-commit in CI. pre-commit run --all-files -# only run the isort hook against all staged files -pre-commit run isort ``` **Temporarily disable hooks** @@ -120,27 +121,16 @@ For more information on using and configuring pre-commit check out the ### Tool configurations -The configuration for the tools can be found in the [`pyproject.toml`][toml] file. - -[toml]: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#what-on-earth-is-a-pyproject-toml-file -**isort** +The configuration for the tools can be found in the [`pyproject.toml`][toml] file, using the same syntax as `black`. -| Parameter | Value | -|--------------|---------| -| Filter Files | `true` | -| Profile | `black` | -| Line Length | `120` | - -[iSort docs](https://pycqa.github.io/isort/docs/configuration/options) - -**black** +[toml]: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#what-on-earth-is-a-pyproject-toml-file -| Parameter | Value | -|--------------|---------| -| Line Length | `120` | +For the most part the default black/ruff formats have been preserved, with a few updates, for example, +increasing the line length to 120. -[Black docs](https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html) +You can find more information about these values in the +[ruff README](https://github.com/astral-sh/ruff?tab=readme-ov-file#configuration). ### Upgrading From 8ef7b42dbcd5af49c0e70b50c52f37016812567b Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 4 Jun 2024 16:54:55 +0200 Subject: [PATCH 14/44] add caveat --- cookbooks.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cookbooks.md b/cookbooks.md index 65c0c95..5f15c1c 100644 --- a/cookbooks.md +++ b/cookbooks.md @@ -28,6 +28,9 @@ Now you should be able to access the django admin at http://localhost:8000/admin As of February, 2023 all Pegasus projects have the option to auto-format your Python code. +As of Jun, 2024, this formatting is done by `ruff`. +This guide will be updated to use `ruff` soon, but for now is still written for `black`/`isort`. + To migrate a project from non-formatted to formatted code, you can go through the following steps: 1. First, do a full Pegasus upgrade to the version you want to update to, as described [here](./upgrading.md). From 0e061918c53186cc69fb9cf2725fdac0a13c420b Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 4 Jun 2024 16:59:09 +0200 Subject: [PATCH 15/44] rewrite config to use ruff --- cookbooks.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cookbooks.md b/cookbooks.md index 5f15c1c..0a25f7e 100644 --- a/cookbooks.md +++ b/cookbooks.md @@ -28,17 +28,14 @@ Now you should be able to access the django admin at http://localhost:8000/admin As of February, 2023 all Pegasus projects have the option to auto-format your Python code. -As of Jun, 2024, this formatting is done by `ruff`. -This guide will be updated to use `ruff` soon, but for now is still written for `black`/`isort`. - To migrate a project from non-formatted to formatted code, you can go through the following steps: 1. First, do a full Pegasus upgrade to the version you want to update to, as described [here](./upgrading.md). **Do *not* check the "autoformat" checkbox yet.** 2. Next, run the formatting tools on your project's `main` branch: - 1. Install black and isort: `pip install black isort` - 2. Run black: `black --extend-exclude migrations --line-length 120 .` - 3. Run isort: `isort -l 120 --profile black .` + 1. Install ruff: `pip install ruff` + 2. Run ruff linting `ruff check --extend-exclude migrations --line-length 120 . --fix` + 3. Run ruff formatting: `ruff format --line-length 120 .` 3. Commit the result: 1. `git add .` 2. `git commit -m "apply formatting changes"` From 1ddb12f162464fae5cf1fdebfc4d42eaaa2824c6 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 5 Jun 2024 08:58:54 +0200 Subject: [PATCH 16/44] add turnstile documentation --- configuration.md | 14 ++++++++++++++ deployment/production-checklist.md | 2 +- images/turnstile.png | Bin 0 -> 31476 bytes release-notes.md | 2 +- 4 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 images/turnstile.png diff --git a/configuration.md b/configuration.md index cb23747..2261a93 100644 --- a/configuration.md +++ b/configuration.md @@ -281,6 +281,20 @@ For help configuring LLMs and AIs, see the [AI docs](./ai.md). See the [celery docs](/celery) for set up and configuration of Celery. +## Turnstile + +To enable support for [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/), +set `TURNSTILE_KEY` and `TURNSTILE_SECRET` in your settings or environment variables. + +This should automatically enable turnstile on your sign up pages. + +It is recommended to create two different Turnstile accounts on Cloudflare for development and production. +In development you can specify "localhost" as your domain like this: + +![Turnstile Dev](/images/turnstile.png) + +In production, you should replace that with your site's production domain. + ## Mailing List diff --git a/deployment/production-checklist.md b/deployment/production-checklist.md index b31efc2..e6d9e35 100644 --- a/deployment/production-checklist.md +++ b/deployment/production-checklist.md @@ -95,7 +95,7 @@ The platform-specific docs have some guidance on setting this up where possible. ## Update other configuration options See [the configuration page](/configuration.md) for a larger list of options, -including social login, sign up flow changes, analytics, logging, and so on. +including social login, sign up flow changes, analytics, logging, adding captchas, and so on. ## Set up monitoring diff --git a/images/turnstile.png b/images/turnstile.png new file mode 100644 index 0000000000000000000000000000000000000000..b56b4dce5e3d6bb250fddfe3ac18e90938d82738 GIT binary patch literal 31476 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 bO~?dkrf1THD;;(sHICYAEu~5Y%dr0emAfZr literal 0 HcmV?d00001 diff --git a/release-notes.md b/release-notes.md index 4824d4c..a39b430 100644 --- a/release-notes.md +++ b/release-notes.md @@ -31,7 +31,7 @@ TODO docs ### Added - Added configurable captcha support on sign up pages, using [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/). - See updated documentation TODO + See [the turnstile documentation](./configuration.md#turnstile) for more information on setting this up. - Added API views for two-factor authentication, and to change the logged-in user's password. (Thanks Finbar for suggesting!) - Add UI to tell users they need a verified email address prior to setting up two-factor auth. - Also added a `has_verified_email` helper class to the `CustomUser` model. From db773b54e584bd85071ad39282683a46646b1d26 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 5 Jun 2024 10:29:17 +0200 Subject: [PATCH 17/44] final(?) release notes --- release-notes.md | 102 ++++++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/release-notes.md b/release-notes.md index a39b430..18fffe1 100644 --- a/release-notes.md +++ b/release-notes.md @@ -9,69 +9,98 @@ This is a feature release with a few bigger updates. ### AI model changes -The library used for non-OpenAI LLMs was changed from [`llm`](https://github.com/simonw/llm) to [`litellm`](https://docs.litellm.ai/docs/). -Reasons for this change include: +The library used for non-OpenAI LLMs has been changed from [`llm`](https://github.com/simonw/llm) +to [`litellm`](https://docs.litellm.ai/docs/). Reasons for this change include: - It has far fewer additional dependencies. -- It supports async APIs out of the box. -- The `llm` library is optimized for the command line use-case, whereas `litellm` offers similar functionality as a native - Python library. - +- It supports async APIs out of the box (for most models). +- The `llm` library is more targeted for the command line use-case, whereas `litellm` offers similar functionality + as a native Python library with a cleaner API. + Litellm can still be used with all common AI models, including OpenAI, Anthropic/Claude, and Meta/Llama models -(with ollama). For details on getting started with `litellm` see the updated [AI documentation](./ai.md). +(via ollama). For details on getting started with `litellm` see the updated [AI documentation](./ai.md). + +### Formatting and linting now use Ruff + +Black and isort have been replaced with [ruff](https://github.com/astral-sh/ruff)---a Python linter/formatter +that offers the same functionality as those tools but is much faster. + +Additionally, Pegasus will now remove unused imports from your files automatically, both +when building your project and if you have set up `pre-commit`. + +This change should be a relatively seamless drop-in replacement, though you may see some new lint errors +in your projects which you can choose to address. ### Spam prevention updates -Turnstile TODO docs +There has been a dramatic increase in spam-bots over the last month. +Many of these bots target seemingly-innocuous functionality like sign up and password reset forms. -### Ruff support + import removal +This version includes a few updates to help combat these bots. +First, you can now easily add [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/) to your sign up forms, +which will present the user with a captcha and should help reduce bot sign-ups. +See [the turnstile documentation](./configuration.md#turnstile) for information on setting this up. -TODO docs +Additionally, the `ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS` setting has been set to `False` by default. +This prevents "forgot password" and "magic link" emails from being sent out to unknown accounts. +It should also help reduce unnecessary email sending. -### Added +Finally, the [admin dashboard](#admin-dashboard) no longer shows users with unconfirmed email addresses if you have set +`ACCOUNT_EMAIL_VERIFICATION = 'mandatory'`. +This helps filter out likely bots from the report to provide clearer visibilty of people actually signing up for your app. + +### Complete changelog + +Below is the complete set of changes in this release. + +#### Added -- Added configurable captcha support on sign up pages, using [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/). +- **Added configurable captcha support on sign up pages, using [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/).** See [the turnstile documentation](./configuration.md#turnstile) for more information on setting this up. - Added API views for two-factor authentication, and to change the logged-in user's password. (Thanks Finbar for suggesting!) - Add UI to tell users they need a verified email address prior to setting up two-factor auth. - Also added a `has_verified_email` helper class to the `CustomUser` model. - Added tests for the delete team view for both team admins and members. (HTMX builds only) - Added test for team member removal permissions. +- Add display and sort on the number of active members in the teams admin. -### Fixed +#### Fixed - Fixed a bug where team names longer than 50 characters could cause a crash during sign up. - Fixed a bug where multi-factor authentication QR codes had a dark background when dark mode was enabled (Tailwind builds only). (Thanks Artem for reporting!) - Fixed a bug where it was possible to bypass two-factor-authentication when using the API authentication views. (Thanks Finbar for reporting and helping with the fix!) -- Add display and sort on the number of active members in the teams admin. - Fixed a bug where deleting the user's only team while impersonating them resulted in a temporary crash. (Thanks EJ for reporting!) - Fixed a bug where creating an API key crashed if your user's first + last name combined to more than 40 characters. (Thanks Luc for reporting!) - - -### Changed - -- Non-OpenAI builds now use `litellm` instead of `llm`. TODO more. -- **Changed the formatter/linter from `black` and `isort` to [ruff](https://github.com/astral-sh/ruff).** - - Also addressed a handful of minor linting errors that came up as a result of this change. - Codebase linting is now substantially faster. -- Removed the `static/css` and `static/js` directories from the `dockerignore` file so that other project files - can be included. Also updated the production Docker build process so that any existing files are overwritten +- Improved the UI feedback when LLMs fail (e.g. if your API key is wrong or ollama is not running). +- Removed the `static/css` and `static/js` directories from the `.dockerignore` file so that other project files + can be included in these directories. + Also updated the production Docker build process so that any existing files are overwritten by the built versions. (Thanks Raul for reporting!) - Made some performance improvements to the production Dockerfile build (don't rebuild the front end if there are no changes in the dependent files). -- The login API response has changed, to allow for two-factor auth prompts, and more machine-readable status fields. +- Better support trialing subscriptions with no payment methods. + The subscription UI will now show the date the trial ends and won't log errors about missing invoices. (Thanks Jarrett for reporting!) + +#### Changed + - **Upgraded all Python packages to the latest versions.** - **Upgraded all JavaScript packages to the latest versions.** +- **Non-OpenAI builds now use `litellm` instead of `llm`.** See above. +- **Changed the formatter/linter from `black` and `isort` to [ruff](https://github.com/astral-sh/ruff).** See above. + - Also addressed a handful of minor linting errors that came up as a result of this change. + - Codebase linting is now substantially faster. + - Unused imports are now automatically removed when building your projects. +- **Celerybeat now uses the `django-celery-beat` library to store tasks in the database instead of on the filesystem.** + This improves support for celerybeat on Docker-based platforms. (Thanks Peter and Artem for the suggestion!) + - Also added a migration to save the default scheduled tasks in the database. +- The login API response has changed, to allow for two-factor auth prompts, and more machine-readable status fields. - Removed the no-longer-used `use_json_field=True` argument from wagtail `StreamField`s. -- The user dashboard no longer shows users with unconfirmed email addresses if you have set - `ACCOUNT_EMAIL_VERIFICATION = 'mandatory'`. This helps filter out likely bots from the report. -- The user dashboard now includes sign ups from the current date, by default. -- Better support trialing subscriptions with no payment methods. - The subscription UI will now show the date the trial ends and won't log errors about missing invoices. (Thanks Jarrett for reporting!) +- The admin dashboard no longer shows users with unconfirmed email addresses if you have set `ACCOUNT_EMAIL_VERIFICATION = 'mandatory'`. +- The admin dashboard now includes sign ups from the current date, by default. - Changed behavior when team role checks fail from raising a `TeamPermissionError` to returning a 403 response, and updated affected tests. One side effect of this is that the stack traces are removed from successful test runs. - Secret keys should no longer change every time you build your Pegasus project. @@ -79,29 +108,28 @@ TODO docs - Updated the default OpenAI chat model to gpt-4o. - Upgraded the openapi client generator to version 7.5.0 and also pinned the version used by `make build-api-client` to the same one. -- **Celerybeat now uses the `django-celery-beat` library to store tasks in the database instead of on the filesystem.** - This improves support for celerybeat on Docker-based platforms. (Thanks Peter and Artem for the suggestion!) - - Also added a migration to save the default scheduled tasks in the database. -- Make Team IDs optional on the create team page (HTMX builds only). +- Team IDs are now optional on the create team page (HTMX builds only). - Add clearer error message when charts are broken due to api config issue. (Thanks Yngve for reporting!) - Added `assume_scheme="https"` to form `URLField`s to be compatible with Django 6 behavior. - Added `FORMS_URLFIELD_ASSUME_HTTPS = True` to be compatible with Django 6 behavior. - Set `ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = False` by default, so that "forgot password" emails do not get sent to unknown accounts. This can help prevent spam bots. -### Removed +#### Removed - Removed `black` and `isort` from dev-requirements, since they have been replaced by `ruff`. - Removed `llm` library and associated code, since it has been replaced by `litellm`. - Removed no longer used `TeamPermissionError` class. -### Standalone front end +#### Standalone front end The following changes affect the experimental [standalone front end](./experimental/react-front-end.md): -- The standalone React front end now supports two-factor-authentication. +- **The standalone React front end now supports two-factor-authentication.** - Improve the UI when you have login issues in the standalone React front end. +*June 5, 2024* + ## Version 2024.5.3 From 4fd7a3dadb68e812a760d45b29d2e2beae5c3826 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 5 Jun 2024 10:34:52 +0200 Subject: [PATCH 18/44] tweaks --- release-notes.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/release-notes.md b/release-notes.md index 18fffe1..7772cab 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,7 +5,7 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. ## Version 2024.6 -This is a feature release with a few bigger updates. +This is a feature release with a few big updates and a lot of smaller ones. ### AI model changes @@ -17,7 +17,7 @@ to [`litellm`](https://docs.litellm.ai/docs/). Reasons for this change include: - The `llm` library is more targeted for the command line use-case, whereas `litellm` offers similar functionality as a native Python library with a cleaner API. -Litellm can still be used with all common AI models, including OpenAI, Anthropic/Claude, and Meta/Llama models +Litellm can still be used with all common AI models, including OpenAI, Anthropic/Claude, and local models (via ollama). For details on getting started with `litellm` see the updated [AI documentation](./ai.md). ### Formatting and linting now use Ruff @@ -56,7 +56,7 @@ Below is the complete set of changes in this release. #### Added - **Added configurable captcha support on sign up pages, using [Cloudflare turnstile](https://www.cloudflare.com/products/turnstile/).** - See [the turnstile documentation](./configuration.md#turnstile) for more information on setting this up. + See [the turnstile documentation](./configuration.md#turnstile) for more information on setting this up. (Thanks Troy, Jacob, Robert and others for suggesting.) - Added API views for two-factor authentication, and to change the logged-in user's password. (Thanks Finbar for suggesting!) - Add UI to tell users they need a verified email address prior to setting up two-factor auth. - Also added a `has_verified_email` helper class to the `CustomUser` model. @@ -89,7 +89,7 @@ Below is the complete set of changes in this release. - **Upgraded all Python packages to the latest versions.** - **Upgraded all JavaScript packages to the latest versions.** -- **Non-OpenAI builds now use `litellm` instead of `llm`.** See above. +- **Non-OpenAI builds now use `litellm` instead of `llm`.** See above. (Thanks Sarthak for the suggestion!) - **Changed the formatter/linter from `black` and `isort` to [ruff](https://github.com/astral-sh/ruff).** See above. - Also addressed a handful of minor linting errors that came up as a result of this change. - Codebase linting is now substantially faster. From 7b23f8d1544603060a193b67f5804db224b5f629 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Thu, 6 Jun 2024 11:32:16 +0200 Subject: [PATCH 19/44] 2026.1 release --- release-notes.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/release-notes.md b/release-notes.md index 7772cab..6db5e5a 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,16 @@ Version History and Release Notes Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus.com/) are documented here. +## Version 2024.6.1 + +This is hotfix release that fixes an issue with tailwind builds where app styles were being +purged during the Docker build process. +This resulted in not all styles being properly rendered on Docker-based deployments. + +Thanks Steve for reporting this. + +*June 6, 2024* + ## Version 2024.6 This is a feature release with a few big updates and a lot of smaller ones. From cf268a92ade193b21fc587eafc9fc7a2313d5805 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Thu, 6 Jun 2024 11:54:20 +0200 Subject: [PATCH 20/44] add another fix --- release-notes.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/release-notes.md b/release-notes.md index 6db5e5a..b0c06da 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,11 +5,13 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. ## Version 2024.6.1 -This is hotfix release that fixes an issue with tailwind builds where app styles were being -purged during the Docker build process. -This resulted in not all styles being properly rendered on Docker-based deployments. +This is hotfix release that addresses two issues from yesterday's update: -Thanks Steve for reporting this. +- Fix app styles accidentally being purged during the Docker build process. + This caused styling on Docker-based deployments for tailwind builds. +- Moved channels url import to after Django initialization. (Thanks Steve for reporting!) + This fixes an `AppRegistryNotReady` error when deploying asynchronous apps with the AI chat app enabled. + (Thanks Roman for reporting!) *June 6, 2024* From 16441e7af6f9df71848f0ccf74fb949ffb700e04 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Thu, 6 Jun 2024 16:29:34 +0200 Subject: [PATCH 21/44] update one more fix --- release-notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index b0c06da..983b7a8 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,13 +5,14 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. ## Version 2024.6.1 -This is hotfix release that addresses two issues from yesterday's update: +This is hotfix release that addresses a few issues from yesterday's update: - Fix app styles accidentally being purged during the Docker build process. This caused styling on Docker-based deployments for tailwind builds. - Moved channels url import to after Django initialization. (Thanks Steve for reporting!) This fixes an `AppRegistryNotReady` error when deploying asynchronous apps with the AI chat app enabled. (Thanks Roman for reporting!) +- Don't create the periodic task to sync subscriptions unless per-unit billing is enabled. *June 6, 2024* From 4afe9cc6a31714ced813ed4a163b59514b013986 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Thu, 6 Jun 2024 16:32:33 +0200 Subject: [PATCH 22/44] fix location of thanks --- release-notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release-notes.md b/release-notes.md index 983b7a8..06ee850 100644 --- a/release-notes.md +++ b/release-notes.md @@ -8,8 +8,8 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. This is hotfix release that addresses a few issues from yesterday's update: - Fix app styles accidentally being purged during the Docker build process. - This caused styling on Docker-based deployments for tailwind builds. -- Moved channels url import to after Django initialization. (Thanks Steve for reporting!) + This caused styling on Docker-based deployments for tailwind builds. (Thanks Steve for reporting!) +- Moved channels url import to after Django initialization. This fixes an `AppRegistryNotReady` error when deploying asynchronous apps with the AI chat app enabled. (Thanks Roman for reporting!) - Don't create the periodic task to sync subscriptions unless per-unit billing is enabled. From 1f6efe3292566074e52dea60b43730f34dbeabdd Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 10 Jun 2024 11:32:38 +0200 Subject: [PATCH 23/44] add hetzner affiliate link --- deployment/kamal.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deployment/kamal.md b/deployment/kamal.md index 37687c8..086038d 100644 --- a/deployment/kamal.md +++ b/deployment/kamal.md @@ -40,10 +40,9 @@ We'll walk through these in more detail in order below. The first step is to provision a server were you will host your application. Some popular choices include: -1. Digital Ocean Droplets (you can sign up with [this link](https://m.do.co/c/432e3abb37f3) to get $100 credit -and help support Pegasus). -2. [Linode](https://www.linode.com/). -3. [Hetzner](https://www.hetzner.com/). +1. Hetzner (get €20 credit and support Pegasus with [this link](https://hetzner.cloud/?ref=49vhF1w3TIyB)). +2. Digital Ocean Droplets (get $100 credit and support Pegasus with [this link](https://m.do.co/c/432e3abb37f3)). +3. [Linode](https://www.linode.com/). 4. [AWS](https://aws.amazon.com/) (Lightsail or EC2). 5. [Google Cloud](https://cloud.google.com/). 6. [Microsoft Azure](https://azure.microsoft.com/en-us). From 95366e461703046eab0661d3c1dbd095ae5c444f Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 11 Jun 2024 14:16:24 +0200 Subject: [PATCH 24/44] cookbook for changing site domain --- deployment/kamal.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/deployment/kamal.md b/deployment/kamal.md index 086038d..6269c3b 100644 --- a/deployment/kamal.md +++ b/deployment/kamal.md @@ -473,3 +473,17 @@ ALLOWED_HOSTS = [ It is recommended to read [the security documentation](https://docs.djangoproject.com/en/5.0/topics/security/#host-headers-virtual-hosting) for this feature to understand the implications of it being included. + +### Cookbooks + +#### Changing your site URL + +To change your site's URL, do the following: + +1. Set up a new DNS endpoint as outlined above. +2. Change all ``Host(`example.com`)`` values in your traefik configuration in `deploy.yml` to the new domain. +3. Update your `ALLOWED_HOSTS` setting / environment variable as needed. +4. Run `kamal traefik reboot`. +4. Run `kamal deploy` + +Your app should now be running on your new domain. From 65a09efeaeef2bbc9ca50bd40533c341732c0936 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Fri, 21 Jun 2024 11:32:21 +0200 Subject: [PATCH 25/44] add flowbite installation instructions --- css/tailwind.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/css/tailwind.md b/css/tailwind.md index 70088c6..364a9e8 100644 --- a/css/tailwind.md +++ b/css/tailwind.md @@ -87,6 +87,28 @@ daisyui: { ## Other products / themes +### Flowbite + +[Flowbite](https://flowbite.com/) is a library with many great UI components---most of which are free and open source. + +Flowbite can easily be added to a Pegasus project by installing it via `npm` and adding it to your global `site.js` and +`tailwind.config.js` files. + +You can use [this git patch file](https://gist.github.com/czue/73cec7ff562aff0943e55538fe9b4550#file-flowbite-patch) +as a starting point and apply it to your project by running: + +``` +git apply flowbite.patch +``` + +This demonstrates basic installation and enabling the [datepicker plugin](https://flowbite.com/docs/plugins/datepicker/). + +After applying the patch you will need to run `npm install` and `npm run dev-watch` to enable it on all pages. + +If you build with the Pegasus examples, you should be able to see the datepicker at [http://localhost:8000/pegasus/forms/](http://localhost:8000/pegasus/forms/). + +### Tailwind UI + [Tailwind UI](https://tailwindui.com/) is a great product for building more complex pages, including marketing sites and app UIs. It another great option for getting help with UI components and pages, and should integrate seamlessly with the current Pegasus templates. From 17eaaced83348e46db7edf1010afb0647dde86d3 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 3 Jul 2024 08:24:36 -0400 Subject: [PATCH 26/44] emphasize portal --- subscriptions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subscriptions.md b/subscriptions.md index f4ae75e..6316d5a 100644 --- a/subscriptions.md +++ b/subscriptions.md @@ -146,7 +146,8 @@ for subscription management after subscription creation. To set up the portal, it's recommended you follow along with [Stripe's integration guide](https://stripe.com/docs/billing/subscriptions/integrating-customer-portal). -To use the portal you will also need to set up webhooks as per below. +**To use the portal you will also need to set up webhooks as per below. +Updates made in the portal will not show up if webhooks are not running.** Pegasus ships with webhooks to handle some common actions taken in the billing portal, including: From cdb9512183fd86a01951d4da27b9efc91cf1b042 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 5 Aug 2024 15:40:50 +0200 Subject: [PATCH 27/44] current release notes draft --- release-notes.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/release-notes.md b/release-notes.md index b0c06da..4efc352 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,31 @@ Version History and Release Notes Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus.com/) are documented here. +## Version 2024.8 + +### Added + +- Added a test that will fail if your project is missing any database migrations. + [More on this concept here](https://adamj.eu/tech/2024/06/23/django-test-pending-migrations/). +- Added an example landing page to Tailwind builds, based off Scriv's landing page. + +### Changed + +- **The example landing pages are now used as the project's landing page instead of being listed in the examples**. +- **Team invitation emails are now better styled, matching the same format as account emails.** (Thanks EJ for the suggestion!) +- The `EMAIL_BACKEND` setting is now configurable via an environment variable. + Also, added a commented-out example of how to set email settings for a production email provider (Mailgun). +- Apt and pip packages are now cached across Docker builds, which should result in faster build times after the first build. + +### Fixed + +- Fixed a bug where the formatting `make` targets were still calling `black` and `isort` instead of `ruff`. + `make black` is now `make ruff-format` and `make isort` is now `make ruff-lint`. +- Fixed a bug where the sign up view tests would fail in your environment if `settings.TURNSTILE_SECRET` was set. +- Fixed translations on the user profile form field names. +- Removed `svg` as an option for profile picture uploads, to prevent the possibility of using it as an XSS attack vector. + ([More info on this threat here](https://medium.com/@rdillon73/hacktrick-stored-xss-via-a-svg-image-3def20968d9)). + ## Version 2024.6.1 This is hotfix release that addresses two issues from yesterday's update: From 7a45f347f4ba6d3305f4e54f7cdb72cd56c63897 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 5 Aug 2024 17:33:12 +0200 Subject: [PATCH 28/44] fix grammar error --- front-end.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end.md b/front-end.md index 9d5ba94..016922c 100644 --- a/front-end.md +++ b/front-end.md @@ -120,7 +120,7 @@ Pegasus has a few patterns for dealing with this. There are two "site-wide" JavaScript files used in Pegasus. The `site.js` file contains code that you want loaded *on every page*. -It's bundle file (`site-bundle.js`) is included in your `base.html`. +Its bundle file (`site-bundle.js`) is included in your `base.html`. This is a good place to put global code, library imports, etc. which should always be available. The `app.js` file contains code that you want loaded *on some pages---typically after login. From 425f7e0d40d6ba1694d7bdd8f9a2e073bcb68503 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Thu, 6 Jun 2024 16:29:34 +0200 Subject: [PATCH 29/44] update one more fix --- release-notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index 4efc352..2ac94cf 100644 --- a/release-notes.md +++ b/release-notes.md @@ -30,13 +30,14 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. ## Version 2024.6.1 -This is hotfix release that addresses two issues from yesterday's update: +This is hotfix release that addresses a few issues from yesterday's update: - Fix app styles accidentally being purged during the Docker build process. This caused styling on Docker-based deployments for tailwind builds. - Moved channels url import to after Django initialization. (Thanks Steve for reporting!) This fixes an `AppRegistryNotReady` error when deploying asynchronous apps with the AI chat app enabled. (Thanks Roman for reporting!) +- Don't create the periodic task to sync subscriptions unless per-unit billing is enabled. *June 6, 2024* From 246f2fd18f524f5b6264c7d3206f706bc51e795b Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Thu, 6 Jun 2024 16:32:33 +0200 Subject: [PATCH 30/44] fix location of thanks --- release-notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release-notes.md b/release-notes.md index 2ac94cf..cedbb70 100644 --- a/release-notes.md +++ b/release-notes.md @@ -33,8 +33,8 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. This is hotfix release that addresses a few issues from yesterday's update: - Fix app styles accidentally being purged during the Docker build process. - This caused styling on Docker-based deployments for tailwind builds. -- Moved channels url import to after Django initialization. (Thanks Steve for reporting!) + This caused styling on Docker-based deployments for tailwind builds. (Thanks Steve for reporting!) +- Moved channels url import to after Django initialization. This fixes an `AppRegistryNotReady` error when deploying asynchronous apps with the AI chat app enabled. (Thanks Roman for reporting!) - Don't create the periodic task to sync subscriptions unless per-unit billing is enabled. From 4cb65f7c85669f83a8c0f0fafdd892ab391a3dd0 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 10 Jun 2024 11:32:38 +0200 Subject: [PATCH 31/44] add hetzner affiliate link --- deployment/kamal.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/deployment/kamal.md b/deployment/kamal.md index 37687c8..086038d 100644 --- a/deployment/kamal.md +++ b/deployment/kamal.md @@ -40,10 +40,9 @@ We'll walk through these in more detail in order below. The first step is to provision a server were you will host your application. Some popular choices include: -1. Digital Ocean Droplets (you can sign up with [this link](https://m.do.co/c/432e3abb37f3) to get $100 credit -and help support Pegasus). -2. [Linode](https://www.linode.com/). -3. [Hetzner](https://www.hetzner.com/). +1. Hetzner (get €20 credit and support Pegasus with [this link](https://hetzner.cloud/?ref=49vhF1w3TIyB)). +2. Digital Ocean Droplets (get $100 credit and support Pegasus with [this link](https://m.do.co/c/432e3abb37f3)). +3. [Linode](https://www.linode.com/). 4. [AWS](https://aws.amazon.com/) (Lightsail or EC2). 5. [Google Cloud](https://cloud.google.com/). 6. [Microsoft Azure](https://azure.microsoft.com/en-us). From df26c4f6fe007b1d4865503e882871554b3d91af Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 11 Jun 2024 14:16:24 +0200 Subject: [PATCH 32/44] cookbook for changing site domain --- deployment/kamal.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/deployment/kamal.md b/deployment/kamal.md index 086038d..6269c3b 100644 --- a/deployment/kamal.md +++ b/deployment/kamal.md @@ -473,3 +473,17 @@ ALLOWED_HOSTS = [ It is recommended to read [the security documentation](https://docs.djangoproject.com/en/5.0/topics/security/#host-headers-virtual-hosting) for this feature to understand the implications of it being included. + +### Cookbooks + +#### Changing your site URL + +To change your site's URL, do the following: + +1. Set up a new DNS endpoint as outlined above. +2. Change all ``Host(`example.com`)`` values in your traefik configuration in `deploy.yml` to the new domain. +3. Update your `ALLOWED_HOSTS` setting / environment variable as needed. +4. Run `kamal traefik reboot`. +4. Run `kamal deploy` + +Your app should now be running on your new domain. From c2393d52e489709e419751ec986e299049050242 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Fri, 21 Jun 2024 11:32:21 +0200 Subject: [PATCH 33/44] add flowbite installation instructions --- css/tailwind.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/css/tailwind.md b/css/tailwind.md index 70088c6..364a9e8 100644 --- a/css/tailwind.md +++ b/css/tailwind.md @@ -87,6 +87,28 @@ daisyui: { ## Other products / themes +### Flowbite + +[Flowbite](https://flowbite.com/) is a library with many great UI components---most of which are free and open source. + +Flowbite can easily be added to a Pegasus project by installing it via `npm` and adding it to your global `site.js` and +`tailwind.config.js` files. + +You can use [this git patch file](https://gist.github.com/czue/73cec7ff562aff0943e55538fe9b4550#file-flowbite-patch) +as a starting point and apply it to your project by running: + +``` +git apply flowbite.patch +``` + +This demonstrates basic installation and enabling the [datepicker plugin](https://flowbite.com/docs/plugins/datepicker/). + +After applying the patch you will need to run `npm install` and `npm run dev-watch` to enable it on all pages. + +If you build with the Pegasus examples, you should be able to see the datepicker at [http://localhost:8000/pegasus/forms/](http://localhost:8000/pegasus/forms/). + +### Tailwind UI + [Tailwind UI](https://tailwindui.com/) is a great product for building more complex pages, including marketing sites and app UIs. It another great option for getting help with UI components and pages, and should integrate seamlessly with the current Pegasus templates. From 120551b8e772459f108a00357fa29b1e6839eab8 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 3 Jul 2024 08:24:36 -0400 Subject: [PATCH 34/44] emphasize portal --- subscriptions.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subscriptions.md b/subscriptions.md index f4ae75e..6316d5a 100644 --- a/subscriptions.md +++ b/subscriptions.md @@ -146,7 +146,8 @@ for subscription management after subscription creation. To set up the portal, it's recommended you follow along with [Stripe's integration guide](https://stripe.com/docs/billing/subscriptions/integrating-customer-portal). -To use the portal you will also need to set up webhooks as per below. +**To use the portal you will also need to set up webhooks as per below. +Updates made in the portal will not show up if webhooks are not running.** Pegasus ships with webhooks to handle some common actions taken in the billing portal, including: From 4ef53cfebbafeb42fc929e3b5ec1020250097d97 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 5 Aug 2024 17:33:12 +0200 Subject: [PATCH 35/44] fix grammar error --- front-end.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end.md b/front-end.md index 9d5ba94..016922c 100644 --- a/front-end.md +++ b/front-end.md @@ -120,7 +120,7 @@ Pegasus has a few patterns for dealing with this. There are two "site-wide" JavaScript files used in Pegasus. The `site.js` file contains code that you want loaded *on every page*. -It's bundle file (`site-bundle.js`) is included in your `base.html`. +Its bundle file (`site-bundle.js`) is included in your `base.html`. This is a good place to put global code, library imports, etc. which should always be available. The `app.js` file contains code that you want loaded *on some pages---typically after login. From 9ebc94518b156fbc4c327cd297eb81e109edfa19 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 5 Aug 2024 15:43:48 +0200 Subject: [PATCH 36/44] add turnstile env --- release-notes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release-notes.md b/release-notes.md index cedbb70..cb914a9 100644 --- a/release-notes.md +++ b/release-notes.md @@ -10,6 +10,8 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - Added a test that will fail if your project is missing any database migrations. [More on this concept here](https://adamj.eu/tech/2024/06/23/django-test-pending-migrations/). - Added an example landing page to Tailwind builds, based off Scriv's landing page. +- Added `TURNSTILE_KEY` and `TURNSTILE_SECRET` to Kamal's default secrets. + ### Changed From 98f55824634805eba0b6d7574d38899d91134c45 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Mon, 5 Aug 2024 17:33:03 +0200 Subject: [PATCH 37/44] more release notes --- release-notes.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index cb914a9..125b374 100644 --- a/release-notes.md +++ b/release-notes.md @@ -20,6 +20,9 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - The `EMAIL_BACKEND` setting is now configurable via an environment variable. Also, added a commented-out example of how to set email settings for a production email provider (Mailgun). - Apt and pip packages are now cached across Docker builds, which should result in faster build times after the first build. +- Improved the display format of "role" in the team invitation list. (thanks Andy for the suggestion!) +- Change `user/` to `YOUR_GITHUB_USERNAME/` in the Digital Ocean `app-spec.yml` file to make it more obvious that + it should be edited. (Thanks Stephen for suggesting!) ### Fixed @@ -29,7 +32,10 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - Fixed translations on the user profile form field names. - Removed `svg` as an option for profile picture uploads, to prevent the possibility of using it as an XSS attack vector. ([More info on this threat here](https://medium.com/@rdillon73/hacktrick-stored-xss-via-a-svg-image-3def20968d9)). - +- Disable debug toolbar in tests, which fixes test failures under certain conditions. +- Bumped the Postgres version used by Digital Ocean deployments from 12 to 16. + Digital Ocean has deprecated support for version 12. (Thanks Stephen for reporting!) + ## Version 2024.6.1 This is hotfix release that addresses a few issues from yesterday's update: From 2089411f0775be54091a5328b456acd565dc647c Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 6 Aug 2024 10:31:32 +0200 Subject: [PATCH 38/44] add a note on static files --- deployment/production-checklist.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/deployment/production-checklist.md b/deployment/production-checklist.md index e6d9e35..bdd77b1 100644 --- a/deployment/production-checklist.md +++ b/deployment/production-checklist.md @@ -78,6 +78,21 @@ There is guidance on configuring media files in the [settings and configuration The most common choice of external storage is [Amazon S3](https://aws.amazon.com/s3/), though many cloud providers have their own S3-compatible options, e.g. [Digital Ocean Spaces](https://www.digitalocean.com/products/spaces). +## Check your static file setup + +By default, Pegasus uses [whitenoise](https://whitenoise.readthedocs.io/en/stable/index.html) for static files. +**If you keep the default setup, you do not need to change anything.** +Static files will be built and collected as part of the build process of your Docker container and should be available +on your production site. + +If you decide to switch to serving files externally, for example, using Amazon S3, +then you may need to modify your static file set up for some platforms. +This is because production secrets necessary to save files to S3 may not be available during the Docker container build. + +If this is the case, you should modify your deployment set up so that `python manage.py collectstatic --noinput` is run +at the same time as Django database migrations, so that the necessary secrets are available to the application. +The exact way to do this will vary by deployment platform. + ## Optimize your front end The front-end files that ship with Pegasus are the developer-friendly versions. From b3687b1ec7aaf1b872b2a4d9b893d5763e982a89 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 6 Aug 2024 10:31:45 +0200 Subject: [PATCH 39/44] add release notes --- release-notes.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index 125b374..4242fb1 100644 --- a/release-notes.md +++ b/release-notes.md @@ -23,6 +23,8 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - Improved the display format of "role" in the team invitation list. (thanks Andy for the suggestion!) - Change `user/` to `YOUR_GITHUB_USERNAME/` in the Digital Ocean `app-spec.yml` file to make it more obvious that it should be edited. (Thanks Stephen for suggesting!) +- Changed the UI of social logins on the "sign in" page to match that of the "sign up" page on the Material Bootstrap theme. + This makes the implementation more extensible and more consistent with other CSS frameworks. ### Fixed @@ -35,7 +37,9 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. - Disable debug toolbar in tests, which fixes test failures under certain conditions. - Bumped the Postgres version used by Digital Ocean deployments from 12 to 16. Digital Ocean has deprecated support for version 12. (Thanks Stephen for reporting!) - +- Simplified how the list of social login buttons is rendered, and make social login buttons work when + configuring social applications in settings (previously buttons only showed up if you configured apps in the database). + ## Version 2024.6.1 This is hotfix release that addresses a few issues from yesterday's update: From 0068b1121f8d72cece589773c01ff0b563a07383 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Tue, 6 Aug 2024 10:42:16 +0200 Subject: [PATCH 40/44] update github merge instructions --- upgrading.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/upgrading.md b/upgrading.md index c7138a7..08b9b48 100644 --- a/upgrading.md +++ b/upgrading.md @@ -20,6 +20,9 @@ You can watch a demo of this set up here: +Note: Whenever you merge Pegasus pull requests you should **use the Github option to "Create a merge commit"**. +Do NOT use "Squash and merge" or "Rebase and merge", as they could prevent future updates from merging cleanly +into your project. ## Manually, using branches From b6189ce59b5168db655711e7b245ce209155ab1f Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 7 Aug 2024 09:11:07 +0200 Subject: [PATCH 41/44] final draft of release notes --- release-notes.md | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/release-notes.md b/release-notes.md index 4242fb1..e2bf33a 100644 --- a/release-notes.md +++ b/release-notes.md @@ -5,17 +5,22 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. ## Version 2024.8 +This is largely a maintenance release with many smaller updates and fixes. + ### Added +- **Added test cases for subscription decorators, feature gating, and views.** + These can be extended/adapted to test custom subscription logic. + Also added utility functions to create test products, subscriptions and mock requests. - Added a test that will fail if your project is missing any database migrations. [More on this concept here](https://adamj.eu/tech/2024/06/23/django-test-pending-migrations/). -- Added an example landing page to Tailwind builds, based off Scriv's landing page. +- **Added an example landing page to Tailwind builds, based largely on [Scriv's landing page](https://scriv.ai/).** - Added `TURNSTILE_KEY` and `TURNSTILE_SECRET` to Kamal's default secrets. - ### Changed - **The example landing pages are now used as the project's landing page instead of being listed in the examples**. + (Bulma and Tailwind builds only.) - **Team invitation emails are now better styled, matching the same format as account emails.** (Thanks EJ for the suggestion!) - The `EMAIL_BACKEND` setting is now configurable via an environment variable. Also, added a commented-out example of how to set email settings for a production email provider (Mailgun). @@ -25,12 +30,14 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. it should be edited. (Thanks Stephen for suggesting!) - Changed the UI of social logins on the "sign in" page to match that of the "sign up" page on the Material Bootstrap theme. This makes the implementation more extensible and more consistent with other CSS frameworks. +- **Upgraded all Python packages to the latest versions.** ### Fixed - Fixed a bug where the formatting `make` targets were still calling `black` and `isort` instead of `ruff`. `make black` is now `make ruff-format` and `make isort` is now `make ruff-lint`. - Fixed a bug where the sign up view tests would fail in your environment if `settings.TURNSTILE_SECRET` was set. + (Thanks Finbar for reporting!) - Fixed translations on the user profile form field names. - Removed `svg` as an option for profile picture uploads, to prevent the possibility of using it as an XSS attack vector. ([More info on this threat here](https://medium.com/@rdillon73/hacktrick-stored-xss-via-a-svg-image-3def20968d9)). @@ -39,6 +46,19 @@ Releases of [SaaS Pegasus: The Django SaaS Boilerplate](https://www.saaspegasus. Digital Ocean has deprecated support for version 12. (Thanks Stephen for reporting!) - Simplified how the list of social login buttons is rendered, and make social login buttons work when configuring social applications in settings (previously buttons only showed up if you configured apps in the database). + See upgrade note below. + +### Removed + +- Deleted the "sticky header" html and CSS code that was only used on the example landing pages. + +### Upgrade Notes + +If you had previously configured allauth social applications in the database *and* in your settings file, +you may see a duplicate "Login with XXX" button on the sign up and login pages. +To fix this, remove the social application from either your settings or the database. + +*August, 7, 2024* ## Version 2024.6.1 From ef6bdcfe2656263f28d8b238e77ae8f212cbdb1b Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 7 Aug 2024 09:15:41 +0200 Subject: [PATCH 42/44] static file config --- release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release-notes.md b/release-notes.md index e2bf33a..ca0a0a2 100644 --- a/release-notes.md +++ b/release-notes.md @@ -16,6 +16,7 @@ This is largely a maintenance release with many smaller updates and fixes. [More on this concept here](https://adamj.eu/tech/2024/06/23/django-test-pending-migrations/). - **Added an example landing page to Tailwind builds, based largely on [Scriv's landing page](https://scriv.ai/).** - Added `TURNSTILE_KEY` and `TURNSTILE_SECRET` to Kamal's default secrets. +- Added a section on configuring static files to the [production checklist](./deployment/production-checklist.md). ### Changed From 681a04f98f60c6bc3af6c38e9455ea5efb2b7cea Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 7 Aug 2024 09:37:36 +0200 Subject: [PATCH 43/44] autoformat notes --- release-notes.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/release-notes.md b/release-notes.md index ca0a0a2..8c623b9 100644 --- a/release-notes.md +++ b/release-notes.md @@ -20,6 +20,10 @@ This is largely a maintenance release with many smaller updates and fixes. ### Changed +- **Code is now automatically formatted for all projects.** + The "Autoformat code" check box has been renamed to "Enable linting and formatting" and now only controls whether + `ruff` and the pre-commit hooks are included in the project download. + Projects that had already enabled auto-formatting are unaffected by this change. (See upgrade notes below.) - **The example landing pages are now used as the project's landing page instead of being listed in the examples**. (Bulma and Tailwind builds only.) - **Team invitation emails are now better styled, matching the same format as account emails.** (Thanks EJ for the suggestion!) @@ -55,7 +59,11 @@ This is largely a maintenance release with many smaller updates and fixes. ### Upgrade Notes -If you had previously configured allauth social applications in the database *and* in your settings file, +- If you had **not** been using auto-formatting until now, you should first follow the instructions for +[migrating to auto-formatted code](./cookbooks.md#migrating-to-auto-formatted-code) prior to upgrading to this release. +Otherwise you will likely get a lot of formatting-related merge conflicts when trying to upgrade. + - If you already enabled auto-formatting (most projects), you don't need to do anything. +- If you had previously configured allauth social applications in the database *and* in your settings file, you may see a duplicate "Login with XXX" button on the sign up and login pages. To fix this, remove the social application from either your settings or the database. From 2e6005ea630ca79c599333c675b523fe59ac49b5 Mon Sep 17 00:00:00 2001 From: Cory Zue Date: Wed, 7 Aug 2024 09:48:30 +0200 Subject: [PATCH 44/44] add thank you --- release-notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release-notes.md b/release-notes.md index 8c623b9..f17ece3 100644 --- a/release-notes.md +++ b/release-notes.md @@ -30,6 +30,7 @@ This is largely a maintenance release with many smaller updates and fixes. - The `EMAIL_BACKEND` setting is now configurable via an environment variable. Also, added a commented-out example of how to set email settings for a production email provider (Mailgun). - Apt and pip packages are now cached across Docker builds, which should result in faster build times after the first build. + (Thanks Tobias for the suggestion!) - Improved the display format of "role" in the team invitation list. (thanks Andy for the suggestion!) - Change `user/` to `YOUR_GITHUB_USERNAME/` in the Digital Ocean `app-spec.yml` file to make it more obvious that it should be edited. (Thanks Stephen for suggesting!)