rioj7 / command-variable

Visual Studio Code extension for variable substitution via ${command:commandID}
47 stars 8 forks source link

Can ${input:fileContent} be used with configurations.connect.host in a launch.json configuration? #86

Open LoggerMN opened 2 weeks ago

LoggerMN commented 2 weeks ago

I'm trying to build a launch configuration that will,

  1. submit a python script to be ran on a server farm,
  2. wait for an indication that the script has started a debugpy server, and is listening for connections,
  3. ascertain the machine that is now listening for a debug client connection, and
  4. proceed to connect the debugger client to the remote server.

I have coded this solution as follows:

  1. launch.json runs a preLaunchTask called launchTest, that uses a shell script to,
    1. submit the job to run on the farm.
    2. waits for a file to exist that contains what machine the job is running on, and also indicates the debug server is now listening.
  2. launch.json also defines the host to connect to as ${input:debugpyLauncHost}
    • input:debugpyLauncHost uses extension.commandvariable.file.content to get the value from the file.

It appears that the launch configuration evaluates the value of ${input:debugpyLauncHost}, before running the preLaunchTask. Because, while launchTest starts the server and the file is created with the machine name, ${input:debugpyLauncHost} returns nothing, and the host connection fails.

I experimented with added delays after the file exists, but regardless of the length it doesn't matter. If on the other hand, I pre-populate the file before running the launch configuration ( and forcing the job to run on that specific machine ), ${input:debugpyLauncHost} successfully returns the machine name from the file and the client connects to the server.

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Py Debugger",
            "type": "debugpy",
            "preLaunchTask": "launchTest",
            "request": "attach",
            "connect": {
                "host": "${input:debugpyLaunchHost}",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "${workspaceFolder}"
                }
            ],
            "postDebugTask": "delete DebugpyLaunchHost.tmp"
        }
    ],
    "inputs": [
        {
            "id": "debugpyLaunchHost",
            "type": "command",
            "command": "extension.commandvariable.file.content",
            "args": {
                "fileName": "${workspaceFolder}/.vscode/debugpyLaunchHost.tmp"
            }
        }
    ]
}

tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "launchTest",
            "type": "shell",
            "command": "proj_env",
            "args": [
                "${workspaceFolder}/trunk/script/launch_test.sh"
            ],  
            "problemMatcher": []
        },
        {
            "label": "delete DebugpyLaunchHost.tmp",
            "type": "shell",
            "command": "rm",
            "args": [
                "${workspaceFolder}/.vscode/debugpyLaunchHost.tmp"
            ],  
            "problemMatcher": []
        }
    ]
}

The details of launch_test.sh aren't important, but it's working as expected.

Is there another way to leverage this extension to accomplish my goal?

rioj7 commented 1 week ago

@LoggerMN Other users have also found this problem with launch configs.

I have mentioned this in issue microsoft/vscode#215905 at the vscode repo in comment


I have found a workaround by using a couple of extensions:

You can define a key binding that will run the preLaunchTask and then launch a named launch config.

VSC has the command runCommands but it does not wait till the task is finished and you can't add a delay between commands. The extension multi-command is an alternative with delay option.

I have chosen to define shift+F5 to start this sequence:

keybindings.json

  {
    "key": "shift+f5",
    "command": "extension.multiCommand.execute",
    "args": {
      "interval": 6000,
      "sequence": [
        {
          "command": "workbench.action.tasks.runTask",
          "args": "getServer"
        },
        "launches.PythonCurrentArgs"
      ]
    },
    "when": "editorTextFocus"
  }

The preLaunchTask is called getServer:

.vscode/tasks.json

    {
      "label": "getServer",
      "type": "shell",
      "command": "c:\\Python312\\python.exe ${workspaceFolder}/getServer.py ${workspaceFolder}/.vscode/debugServer.tmp",
      "problemMatcher": []
    }

getServer.py

import sys
import time

time.sleep(2) # sim some wait time

with open(sys.argv[1], "w") as file:
  file.write('apricot')

Define the launch config to use:

.vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Python Debugger: Current File with Arguments",
      "type": "debugpy",
      "request": "launch",
      "program": "${file}",
      "console": "integratedTerminal",
      "args": "${input:getServername}"
    }
  ],
  "inputs": [
    {
      "id": "getServername",
      "type": "command",
      "command": "extension.commandvariable.file.content",
      "args": { "fileName": "${workspaceFolder}/.vscode/debugServer.tmp" }
    }
  ]
}

In .vscode/settings.json define a name to launch a config with a command.

.vscode/settings.json

  "launches": {
    "PythonCurrentArgs": "Python Debugger: Current File with Arguments (Workspacename)"
  }

You make the file you want to debug current and press shift+F5.

You need to adjust:

The file I used for testing is:

test-launch.py

import sys

print('Use server:', sys.argv[1])
print()

Maybe we can add a feature request to add a conditional wait till a file is found/modified to multi-command. But the last update was 2 years ago.