Skip to content

Upgrade to Winter 33 and call setup after route discovery - #7

Merged
mofr merged 6 commits into
masterfrom
winter-33
Oct 13, 2026
Merged

mofr merged 6 commits into
masterfrom
winter-33

Conversation

@mofr

@mofr mofr commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

The example was pinned to Winter 22 and tested on Python 3.8 to 3.10, which Winter no longer supports. This brings it to Winter 33.

Setup order bug. Setup was called from settings.py, before Django imported the URL module and with it the API modules. winter.web.setup() registers handlers only for @problem exceptions that are already imported, so any such exception returned 500. The example had none, so the bug was invisible. Setup now runs in AppConfig.ready() right after importing the URLs, and a comment there says why. A @problem endpoint with a test proved the fix (500 before the move, 400 after) and was then removed to keep the first example one endpoint long.

Other changes:

  • Winter 33 import paths, Swagger UI returns winter.web.Response instead of a Django response.
  • Flat layout: simple_api/api.py and simple_api/openapi.py, and route discovery scans exactly these two modules. Scanning the whole simple_api package would import wsgi.py from inside ready() and break manage.py check. Tests move to tests/.
  • Fresh Django 5.2 project files, Python 3.11 to 3.13 in CI, Poetry 2.5.1, current action versions, manage.py check in CI.
  • Dockerfile on python:3.13-slim installs only runtime dependencies.
  • README: fixed paths and gunicorn module name, explained the setup order, removed the Heroku section.

Requires Winter 33.1. It contains WinterFramework/winter#340 (33.0.0 failed at setup without pytz) and WinterFramework/winter#341 (route discovery accepts a module, which the flat layout uses). poetry.lock is regenerated with Poetry 2.5.1 and pins Winter 33.1.0. Tested in a clean environment from the lock, without pytz: 4 tests pass, manage.py check is clean. Earlier, gunicorn served the greeting, the problem response, Swagger UI and the spec. The Docker image was not built locally.

Includes #8: the dead GKE deployment is replaced by Azure Container Apps, and CI checks that the Docker image starts and answers.

🤖 Generated with Claude Code

- Winter 33 import paths: winter.web, winter.django, winter.openapi, winter.application.
- Setup moves from settings.py to AppConfig.ready(), after the URL module is imported.
  Called from settings.py, it ran before the API modules were imported, so exceptions
  marked with @problem got no handler and returned 500.
- An endpoint with a @problem exception shows and tests RFC 7807 responses.
- Route discovery scans only simple_api.api and simple_api.docs; tests move to tests/.
- Fresh Django 5.2 project files, Python 3.11 to 3.13, Poetry 2, current GitHub Actions.
- Dockerfile uses python:3.13-slim and installs only runtime dependencies.
- README: correct paths and gunicorn module, setup order explained, Heroku section removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Winter 33.1 discovers routes in a single module, so the api and docs subpackages
are no longer needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mofr
mofr requested a review from andrey-berenda October 13, 2026 09:54
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mofr
mofr marked this pull request as ready for review October 13, 2026 11:40
poetry lock kept versions from the old lock, including greenlet 3.0.3, which
has no Python 3.13 wheels and does not build from source there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread simple_api/api.py Outdated

@winter.web.route_get('greeting/{name}/')
@winter.web.raises(NameTooLongException)
def personal_greeting(self, name: str) -> str:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

a single exception usage turned a simple example (which is ideally 1 line) into 22 LOC, hesitating

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed: api.py is back to the single greeting endpoint, and the RFC 7807 test and README part are gone. The setup order stays explained in apps.py.

mofr and others added 2 commits October 13, 2026 17:49
The @problem endpoint made the first example 22 lines long. The setup order stays
explained in apps.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n CI (#8)

* Deploy to Azure Container Apps instead of GKE; smoke-test the image in CI

The GKE deployment last succeeded before July 2024 and pushed to gcr.io, which stopped
accepting images in March 2025. A Kubernetes cluster with a load balancer also costs money
when idle.

- docker.yml builds the image, runs it and checks the responses on every push.
- azure.yml deploys to Azure Container Apps on demand and monthly, then runs the same checks
  against the deployed app. The image lives on GitHub Container Registry, and GitHub Actions
  signs in to Azure with OpenID Connect, so there is no long-lived secret to expire.
- smoke_test.sh holds the response checks used by both workflows.
- README documents the one-time Azure and GitHub setup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Check the container and the deployment with curl instead of a shell test script

The pytest suite already tests the responses. CI only needs to know that the image starts
and the deployment answers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@mofr
mofr merged commit ac9342b into master Oct 13, 2026
10 checks passed
@mofr
mofr deleted the winter-33 branch October 13, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant