From 11ae32555ab782372ddf42c8a9ba17b9c4a79034 Mon Sep 17 00:00:00 2001 From: Daniel Lindsley Date: Wed, 10 Sep 2025 14:53:57 -0500 Subject: [PATCH 1/3] feat: Added VS Code debugging support. --- .../utils/debugger.py | 5 +- template/docs/debug.md | 61 +++++++++++++++++-- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/template/backend/{{copier__project_slug}}/utils/debugger.py b/template/backend/{{copier__project_slug}}/utils/debugger.py index 957bc41..fba2e23 100644 --- a/template/backend/{{copier__project_slug}}/utils/debugger.py +++ b/template/backend/{{copier__project_slug}}/utils/debugger.py @@ -18,4 +18,7 @@ def pycharm_debugger(): def vscode_debugger(): - raise NotImplementedError("VSCode debugger not implemented") + logger.info("Debugpy connecting...") + import debugpy + host_ip = os.getenv("DOCKER_GATEWAY_IP") + debugpy.listen((host_ip, 5678)) diff --git a/template/docs/debug.md b/template/docs/debug.md index 96ea6e7..fa85b65 100644 --- a/template/docs/debug.md +++ b/template/docs/debug.md @@ -1,8 +1,14 @@ # :bug: How to debug the application -The steps below describe how to set up interactive debugging with PyCharm. +The steps below describe how to set up interactive debugging. Scaf supports + +* PyCharm +* VS Code + +## PyCharm Debugging + +### Setup -## PyCharm Debugging Setup Update `k8s/base/app.configmap.yaml` with `data` field `PYTHONBREAKPOINT: "utils.pycharm_debugger"` In PyCharm: @@ -19,11 +25,58 @@ In PyCharm: ![debug__debug_configuration.png](images/debug__debug_configuration.png) -## Debugging in development +### Debugging in development Before the code you want to debug, add the following: ```python breakpoint() ``` -You must then set break points in your IDE and call the code as usual to hit them. +You must then set break points in PyCharm, and call the code as usual to hit them. + +## VS Code Debugging + +### Setup + +Update `k8s/base/app.configmap.yaml` with `data` field `PYTHONBREAKPOINT: "utils.vscode_debugger"` + +In VS Code: + +1. Go to 'Run & Debug` tab +2. Click on 'create a launch.json file' +3. Choose 'Python Debugger' +4. Choose 'Remote Attach' +5. Set the host to `0.0.0.0` +6. Set the port to `5678` +7. VS Code will create a `.vscode/launch.json` with your configuration. Make any desired further changes, then save. The file should something look like: + +```json +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "name": "Python Debugger: Remote Attach", + "type": "debugpy", + "request": "attach", + "connect": { + "host": "0.0.0.0", + "port": 5678 + }, + "pathMappings": [ + { + "localRoot": "${workspaceFolder}", + "remoteRoot": "." + } + ] + } + ] +} +``` + +### Debugging in development + +You can set break points in VS Code as normal, and call the code as usual to hit them. From 2235bbee9e84b3b5303264604ccc5ae5a882ce5b Mon Sep 17 00:00:00 2001 From: Daniel Lindsley Date: Thu, 11 Sep 2025 10:26:56 -0500 Subject: [PATCH 2/3] Further tweaks to fully-enable VS Code debugging. --- template/Tiltfile | 1 + .../{{copier__project_slug}}/utils/debugger.py | 6 ++++-- template/docs/debug.md | 17 +++++++++++------ template/k8s/base/app.configmap.yaml | 3 ++- template/k8s/base/django.yaml | 7 +++++++ 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/template/Tiltfile b/template/Tiltfile index 98f0a07..05ab22c 100644 --- a/template/Tiltfile +++ b/template/Tiltfile @@ -55,6 +55,7 @@ syncback( {% if copier__create_nextjs_frontend %} k8s_resource(workload='frontend', port_forwards=3000) {% endif %} +k8s_resource(workload='backend', port_forwards=5678) k8s_resource(workload='backend', port_forwards=8000) k8s_resource(workload='mailhog', port_forwards=8025) k8s_resource(workload='postgres', port_forwards=5432) diff --git a/template/backend/{{copier__project_slug}}/utils/debugger.py b/template/backend/{{copier__project_slug}}/utils/debugger.py index fba2e23..7705449 100644 --- a/template/backend/{{copier__project_slug}}/utils/debugger.py +++ b/template/backend/{{copier__project_slug}}/utils/debugger.py @@ -8,9 +8,10 @@ def pycharm_debugger(): logger.info("Pycharm pydevd connecting...") import pydevd_pycharm host_ip = os.getenv("DOCKER_GATEWAY_IP") + debug_port = int(os.getenv("DEBUGGER_PORT", default=6400)) try: pydevd_pycharm.settrace( - host_ip, port=6400, stdoutToServer=True, stderrToServer=True, suspend=False + host_ip, port=debug_port, stdoutToServer=True, stderrToServer=True, suspend=False ) except ConnectionRefusedError: msg = "Debugger connection failed. Check IDE debugger is running and try again. Continuing without debugger." @@ -21,4 +22,5 @@ def vscode_debugger(): logger.info("Debugpy connecting...") import debugpy host_ip = os.getenv("DOCKER_GATEWAY_IP") - debugpy.listen((host_ip, 5678)) + debug_port = int(os.getenv("DEBUGGER_PORT", default=5678)) + debugpy.listen(("0.0.0.0", debug_port)) diff --git a/template/docs/debug.md b/template/docs/debug.md index fa85b65..820e606 100644 --- a/template/docs/debug.md +++ b/template/docs/debug.md @@ -9,7 +9,9 @@ The steps below describe how to set up interactive debugging. Scaf supports ### Setup -Update `k8s/base/app.configmap.yaml` with `data` field `PYTHONBREAKPOINT: "utils.pycharm_debugger"` +Update `k8s/base/app.configmap.yaml` with: +* `data` field `PYTHONBREAKPOINT: "utils.pycharm_debugger"` +* `data` field `DEBUGGER_PORT: "6400"` In PyCharm: @@ -38,7 +40,9 @@ You must then set break points in PyCharm, and call the code as usual to hit the ### Setup -Update `k8s/base/app.configmap.yaml` with `data` field `PYTHONBREAKPOINT: "utils.vscode_debugger"` +Update `k8s/base/app.configmap.yaml` with: +* `data` field `PYTHONBREAKPOINT: "utils.vscode_debugger"` +* `data` field `DEBUGGER_PORT: "5678"` In VS Code: @@ -48,7 +52,9 @@ In VS Code: 4. Choose 'Remote Attach' 5. Set the host to `0.0.0.0` 6. Set the port to `5678` -7. VS Code will create a `.vscode/launch.json` with your configuration. Make any desired further changes, then save. The file should something look like: +7. VS Code will create a `.vscode/launch.json` with your configuration. +8. You'll need to update the `pathMappings` slightly. See the example below. +9. Make any desired further changes, then save. The file should something look like: ```json { @@ -57,7 +63,6 @@ In VS Code: // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ - { "name": "Python Debugger: Remote Attach", "type": "debugpy", @@ -68,8 +73,8 @@ In VS Code: }, "pathMappings": [ { - "localRoot": "${workspaceFolder}", - "remoteRoot": "." + "localRoot": "${workspaceFolder}/backend", + "remoteRoot": "/app/src" } ] } diff --git a/template/k8s/base/app.configmap.yaml b/template/k8s/base/app.configmap.yaml index 685be10..ac7f1db 100644 --- a/template/k8s/base/app.configmap.yaml +++ b/template/k8s/base/app.configmap.yaml @@ -22,7 +22,8 @@ data: # Also probably need to add cython to local.in in that case. PYDEVD_USE_CYTHON: "NO" PYDEVD_USE_FRAME_EVAL: "NO" - PYTHONBREAKPOINT: "" # "utils.pycharm_debugger" for pycharm + PYTHONBREAKPOINT: "" # "utils.pycharm_debugger" for pycharm, "utils.vscode_debugger" for VS Code + DEBUGGER_PORT: "" # "6400" for pycharm, "5678" for VS Code {%- if copier__mail_service == 'Mailgun' %} MAILGUN_DOMAIN: "{{ copier__domain_name }}" MAILGUN_API_URL: "https://api.mailgun.net/v3"{%- endif %} diff --git a/template/k8s/base/django.yaml b/template/k8s/base/django.yaml index f445f95..62de3ee 100644 --- a/template/k8s/base/django.yaml +++ b/template/k8s/base/django.yaml @@ -11,6 +11,10 @@ spec: ports: - port: 8000 targetPort: http-server + name: wsgi + - port: 5678 + targetPort: 5678 + name: debug --- apiVersion: apps/v1 kind: Deployment @@ -33,9 +37,12 @@ spec: - name: backend image: backend:latest command: ["python", "manage.py", "runserver", "0.0.0.0:8000"] + # command: ["python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "manage.py", "runserver", "0.0.0.0:8000"] ports: - name: http-server containerPort: 8000 + - name: debug + containerPort: 5678 envFrom: - configMapRef: name: app-config From 0f755940827a6c459e8770d6cd6d35969ce5a281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roch=C3=A9=20Compaan?= Date: Fri, 12 Sep 2025 10:38:55 +0200 Subject: [PATCH 3/3] refactor: use tilt to patch debugpy port into k8s/local --- template/Tiltfile | 16 ++++++++++---- .../utils/debugger.py | 3 +-- template/docs/debug.md | 19 +++++++++++++--- template/k8s/base/django.yaml | 6 ----- template/k8s/local/enable-debugpy.sh | 22 +++++++++++++++++++ 5 files changed, 51 insertions(+), 15 deletions(-) create mode 100755 template/k8s/local/enable-debugpy.sh diff --git a/template/Tiltfile b/template/Tiltfile index 05ab22c..cd18f4f 100644 --- a/template/Tiltfile +++ b/template/Tiltfile @@ -9,6 +9,11 @@ print( load("ext://syncback", "syncback") +# Check for --debugpy argument +config.define_bool("debugpy", False, "Enable debugpy debugging support") +cfg = config.parse() +enable_debugpy = cfg.get("debugpy", False) + docker_build( "backend", context="backend", @@ -29,9 +34,11 @@ docker_build( ) {% endif %} -k8s_yaml( - kustomize("./k8s/local/") -) +# Load kubernetes configuration +if enable_debugpy: + k8s_yaml(local('./k8s/local/enable-debugpy.sh')) +else: + k8s_yaml(kustomize("./k8s/local/")) syncback( "backend-sync", @@ -55,7 +62,8 @@ syncback( {% if copier__create_nextjs_frontend %} k8s_resource(workload='frontend', port_forwards=3000) {% endif %} -k8s_resource(workload='backend', port_forwards=5678) +if enable_debugpy: + k8s_resource(workload='backend', port_forwards=5678) k8s_resource(workload='backend', port_forwards=8000) k8s_resource(workload='mailhog', port_forwards=8025) k8s_resource(workload='postgres', port_forwards=5432) diff --git a/template/backend/{{copier__project_slug}}/utils/debugger.py b/template/backend/{{copier__project_slug}}/utils/debugger.py index 7705449..54671b2 100644 --- a/template/backend/{{copier__project_slug}}/utils/debugger.py +++ b/template/backend/{{copier__project_slug}}/utils/debugger.py @@ -21,6 +21,5 @@ def pycharm_debugger(): def vscode_debugger(): logger.info("Debugpy connecting...") import debugpy - host_ip = os.getenv("DOCKER_GATEWAY_IP") debug_port = int(os.getenv("DEBUGGER_PORT", default=5678)) - debugpy.listen(("0.0.0.0", debug_port)) + debugpy.listen(("0.0.0.0", debug_port)) # nosec B104 diff --git a/template/docs/debug.md b/template/docs/debug.md index 820e606..8e0b8eb 100644 --- a/template/docs/debug.md +++ b/template/docs/debug.md @@ -5,6 +5,21 @@ The steps below describe how to set up interactive debugging. Scaf supports * PyCharm * VS Code +## Starting Tilt with Debugging Support + +To enable debugging, start Tilt with the `--debugpy` flag: + +```bash +tilt up -- --debugpy +``` + +This will: +* Add the debug port (5678) to the backend service +* Modify the Django container to use debugpy +* Enable port forwarding for the debug port + +Without the `--debugpy` flag, Tilt will run normally without debugging support. + ## PyCharm Debugging ### Setup @@ -40,9 +55,7 @@ You must then set break points in PyCharm, and call the code as usual to hit the ### Setup -Update `k8s/base/app.configmap.yaml` with: -* `data` field `PYTHONBREAKPOINT: "utils.vscode_debugger"` -* `data` field `DEBUGGER_PORT: "5678"` +Make sure you have started Tilt with the `--debugpy` flag as described above. In VS Code: diff --git a/template/k8s/base/django.yaml b/template/k8s/base/django.yaml index 62de3ee..41af67b 100644 --- a/template/k8s/base/django.yaml +++ b/template/k8s/base/django.yaml @@ -12,9 +12,6 @@ spec: - port: 8000 targetPort: http-server name: wsgi - - port: 5678 - targetPort: 5678 - name: debug --- apiVersion: apps/v1 kind: Deployment @@ -37,12 +34,9 @@ spec: - name: backend image: backend:latest command: ["python", "manage.py", "runserver", "0.0.0.0:8000"] - # command: ["python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "manage.py", "runserver", "0.0.0.0:8000"] ports: - name: http-server containerPort: 8000 - - name: debug - containerPort: 5678 envFrom: - configMapRef: name: app-config diff --git a/template/k8s/local/enable-debugpy.sh b/template/k8s/local/enable-debugpy.sh new file mode 100755 index 0000000..bfea41e --- /dev/null +++ b/template/k8s/local/enable-debugpy.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +# Generate base YAML and patch with debugpy support +kubectl kustomize ./k8s/local/ | yq --yaml-output ' + if (.kind == "Service" and .metadata.name == "backend") then + .spec.ports += [{ + "port": 5678, + "targetPort": 5678, + "name": "debug" + }] + elif (.kind == "Deployment" and .metadata.name == "backend") then + .spec.template.spec.containers[0].command = [ + "python", "-m", "debugpy", "--listen", "0.0.0.0:5678", "manage.py", "runserver", "0.0.0.0:8000" + ] | + .spec.template.spec.containers[0].ports += [{ + "name": "debug", + "containerPort": 5678 + }] + else + . + end +'