GoogleCloudPlatform / cloud-code-vscode

Cloud Code for Visual Studio Code: Issues, Documentation and more
Other
415 stars 111 forks source link

Implement an option to re-attach the debugger after file sync and application restart #849

Open ipeychev opened 1 year ago

ipeychev commented 1 year ago

Hello,

Use case Cloud Code works well, but there is a missing feature which really bugs the dev process - the file sync workflow seems incomplete:

  1. I have a NodeJS app, running on GKE (remote Kubernetes). The debugging session works fine.
  2. I have setup file sync, which works fine too.
  3. Once Cloud Code finishes the sync up, nodemon(or node --watch) restarts my application - to load the new changes.
  4. However, after that debugging doesn't work anymore - it doesn't stop on any breakpoint. I guess the problem is the new process - debugger doesn't re-attach to the new process (restarted application).

If this cannot be done automatically, is there a way to execute e.g., a command to re-attach the debugger to the new process?

I looked at the hooks/lifecycle events, but I can't find a way to re-attach the debugger.

Please note - I don't want to stop the whole debugging session and run it again, because this will rebuild and redeploy the whole image, kill the old and create a new pod, etc., which is very slow. Or, maybe there is a way to avoid the re-build and re-deploy step?

Feature Maybe a way to re-attach the debugger to the to the new process - either manually, or after Skaffold's After Sync hook? Or, just automatically?

Thank you!

ipeychev commented 1 year ago

The issue is easily reproducible with any of the skaffold examples, for example here or here. Steps to reproduce:

  1. Deploy the example using Cloud Code onVSCode to a k8s cluster in debug mode. Personally, I did it on GCP.
  2. Set a breakpoint and hit the REST route, e.g., curl 0.0.0.0:3000. The debugger will stop on the breakpoint.
  3. Modify the source. Cloud Code will sync it up successfully.
  4. Hit the REST route again. VSCode will not stop on the breakpoint.

The developer will need to restart the whole session to make it work again.

glouischandra commented 1 year ago

Thank you for the bug report @ipeychev currently investigating this issue.

glouischandra commented 1 year ago

Hi @ipeychev,

I'm still looking at the skaffold example repro, meanwhile can you send us your launch.json config? This should be generated when you run "Cloud Code: Debug on Kubernetes" in Cloud Code. Usually this is our setting to ensure watch is working correctly:

{
    "version": "0.2.0",
    "configurations": [
      {
        "name": "Run on Kubernetes",
        "type": "cloudcode.kubernetes",
        "request": "launch",
        "skaffoldConfig": "${workspaceFolder}/skaffold.yaml",
        "watch": true,
        "cleanUp": true,
        "portForward": true,
        "imageRegistry": "gcr.io/<container>",
        "debug": [
          {
            "image": "nodejs-hello-world",
            "containerName": "server",
            "sourceFileMap": {
              "${workspaceFolder}": "/hello-world"
            }
          }
        ]
      }
    ]
}

Taken from: https://github.com/GoogleCloudPlatform/cloud-code-samples/blob/v1/nodejs/nodejs-hello-world/.vscode/launch.json.

Also when you start debugging, what profile do you choose, Is it the "Dev"? Can you retry debugging with "Default Profile"

ipeychev commented 1 year ago

Hey @glouischandra , thank you for getting back to me. Here it is:

  1. Maybe you are right, and this is indeed only a bug which appears when sync in skaffold.yaml is enabled. I thought it was a missing feature (not entirely implemented workflow).
  2. To prove it, I took this skaffold example. It is simple and it has sync enabled. I only slightly modified Dockerfile (use node instead node-slim - to get bash), and the index.js file - to be able to set a breakpoint. I'll attach it here.
  3. The watch is set to true, yes.
  4. With the default profile it redeploys and kills the pod, then starts a new one. In this situation, it works.
  5. I'm attaching two things:
  1. In the screencast, you can see that once the source code is synched, debugging stops to work.

Best, Iliyan

ipeychev commented 1 year ago

Hey @glouischandra, could I ask if everything is clear now, please? Have you had success in reproducing and resolving the issue?

j-windsor commented 11 months ago

Hello. Yes, I was able to get a repro using the code that you sent. Thanks for the detailed repro!

Apologies for the late reply. @glouischandra is on vacation.

ipeychev commented 10 months ago

Hey guys, is there any progress?

marango25 commented 10 months ago

I have the same problem, with 5 services that need each other, when I make a change it actually takes it, but it disconnects from the debugger and does not reconnect until I stop the entire debugger. Also when I am managing the logs, I see that when I save a change, only that pod appears and the others are no longer there, but it says that it is still running and also when I return I make a change, the log disappears, and I don't have any errors on console or anything.

This is the launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Kubernetes: Run/Debug",
      "type": "cloudcode.kubernetes",
      "request": "launch",
      "skaffoldConfig": "${workspaceFolder}/skaffold-node.yaml",
      "watch": true,
      "cleanUp": true,
      "portForward": true,
      "debug":  [
        {
          "image": "xxxx/x",
          "containerName": "installer",
          "sourceFileMap": {
            "${workspaceFolder}/installer": "/app"
          }
        },
        {
          "image": "xxxx/x",
          "containerName": "x",
          "sourceFileMap": {
            "${workspaceFolder}/x": "/app"
          }
        },
        {
          "image": "xxxx/x",
          "containerName": "x",
          "sourceFileMap": {
            "${workspaceFolder}/x": "/app"
          }
        },
        {
          "image": "xxxx/x",
          "containerName": "x",
          "sourceFileMap": {
            "${workspaceFolder}/x": "/app"
          }
        },
        {
          "image": "xxxx/x",
          "containerName": "x",
          "sourceFileMap": {
            "${workspaceFolder}/x": "/app"
          }
        }
      ]
    }
  ]
}

File skaffold

apiVersion: skaffold/v2beta17
kind: Config
build:
  artifacts:
    - image: x/x
      context: x
      sync:
        manual:
          - src: src/**/*.ts
            dest: .
      docker:
        dockerfile: Dockerfile
    - image: x/x
      context: x
      sync:
        manual:
          - src: src/**/*.ts
            dest: .
      docker:
        dockerfile: Dockerfile
    - image: x/x
      context: x
      sync:
        manual:
          - src: src/**/*.ts
            dest: .
      docker:
        dockerfile: Dockerfile
    - image: x/x
      context: x
      sync:
        manual:
          - src: src/**/*.ts
            dest: .
      docker:
        dockerfile: Dockerfile
    - image: x/x
      context: x
      sync:
        manual:
          - src: src/**/*.ts
            dest: .
      docker:
        dockerfile: Dockerfile
  local:
    push: false
    # useDockerCLI: true
deploy:
  kubectl:
    manifests:
      - ./infra/k8s/*

I share a video with you, I apologize for the quality, but I hope it helps you understand a little better

https://github.com/GoogleCloudPlatform/cloud-code-vscode/assets/66284775/6b67dd58-cf69-4aaf-8299-3ce3673d4161

Note: a collaborator told me that this does not happen in phpStorm or intelliJ, I was researching until late in the morning about this and in phpStorm or intelliJ (they are practically the same, just for a different language) they had the same problem but they solved it in their IDE .

ipeychev commented 6 months ago

What happened with this issue @glouischandra ? Could I ask if there are plans to fix it, please?