Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resolving multiple tasks with type npm and same script fails #93001

Open
Strandinator opened this issue Mar 19, 2020 · 13 comments
Open

resolving multiple tasks with type npm and same script fails #93001

Strandinator opened this issue Mar 19, 2020 · 13 comments
Assignees
Labels
bug Issue identified by VS Code Team member as probable bug polish Cleanup and polish issue tasks Task system issues
Milestone

Comments

@Strandinator
Copy link

Issue Type: Bug

Create 2 tasks with "type": "npm" and same "script"

Expected both tasks to be resolved by their label

  • VsCode will list only one of those tasks when listing available tasks with "Tasks: Run Task".
  • Depending tasks will fail with "Couldn't resolve dependent task 'x' in workspace folder 'y'" in the "Tasks" output.

tasks.json:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "start_both",
            "type": "shell",
            "dependsOn": [
                "start_nr_1",
                "start_nr_2"
            ],
            "problemMatcher": []
        },
        {
            "label": "start_nr_1",
            "type": "npm",
            "script": "start",
            "problemMatcher": []
        },
        {
            "label": "start_nr_2",
            "type": "npm",
            "script": "start",
            "options": {
                "env": {
                    "SOME": "option"
                }
            },
            "problemMatcher": []
        },
    ]
}

package.json:

{
  "scripts": {
    "start": "echo running 'start' script"
  }
}

VS Code version: Code 1.43.1 (fe22a96, 2020-03-18T07:01:20.184Z)
OS version: Windows_NT x64 10.0.19041

System Info
Item Value
CPUs Intel(R) Core(TM) i7-4790 CPU @ 3.60GHz (8 x 3592)
GPU Status 2d_canvas: enabled
flash_3d: enabled
flash_stage3d: enabled
flash_stage3d_baseline: enabled
gpu_compositing: enabled
multiple_raster_threads: enabled_on
oop_rasterization: disabled_off
protected_video_decode: unavailable_off
rasterization: enabled
skia_renderer: disabled_off_ok
video_decode: enabled
viz_display_compositor: enabled_on
viz_hit_test_surface_layer: disabled_off_ok
webgl: enabled
webgl2: enabled
Load (avg) undefined
Memory (System) 15.92GB (8.47GB free)
Process Argv
Screen Reader no
VM 0%
Extensions: none
@vscodebot
Copy link

vscodebot bot commented Mar 19, 2020

@Strandinator Strandinator changed the title resolving multiple tasks with type npm and same path fails resolving multiple tasks with type npm and same script fails Mar 19, 2020
@Strandinator
Copy link
Author

Workaround would be to simply define a separate script in package.json for each task

@alexr00
Copy link
Member

alexr00 commented Mar 19, 2020

This is by design. An extension provided task, such as a task of "type": "npm" is identified by it task-type-specific properties (for npm tasks, this is script). Tasks are not identified by label, a label is just a nice human readable string.

Since this is very easily worked around by having a separate npm script in your package.json I wouldn't make any changes in the behavior. However, it is not nice that the first time you learn that you can't have two of the same task is when you try to run a task that depends on it. I will add an error earlier, so that it's clear what's happening when the task list shows.

@alexr00 alexr00 added polish Cleanup and polish issue tasks Task system issues labels Mar 19, 2020
@alexr00 alexr00 added this to the On Deck milestone Mar 19, 2020
@GordonSmith
Copy link

@alexr00 I just hit this today as well, in my situation both script calls had different working directories:

		{
			"label": "server tsc watch",
			"type": "npm",
			"script": "compile-watch",
			"options": {
				"cwd": "web/server"
			},
			"problemMatcher": [
				"$tsc-watch"
			],
			"presentation": {
				"group": "group-build"
			}
		},
		{
			"label": "client tsc watch",
			"type": "npm",
			"script": "compile-watch",
			"options": {
				"cwd": "web/client"
			},
			"problemMatcher": [
				"$tsc-watch"
			],
			"presentation": {
				"group": "group-build"
			}
		},

In my case I don't really have ownership of the web/client and web/server package.json files, so renaming or adding script sections is not an option...

@alexr00 alexr00 added the bug Issue identified by VS Code Team member as probable bug label Nov 9, 2020
@nelisbijl
Copy link

Workaround: add a path property and use '.', or './.' or '././.' etc.

@joyceerhl
Copy link
Contributor

@alexr00 would it be possible to include the options (particularly cwd) in the unique identification of a task? I just ran into this while trying to configure build tasks in an npm workspace where the sub-workspaces had identically named scripts with different cwds. As you note, it's easy to work around this, but it was definitely surprising behavior and I wasted time trying to figure out what I'd misconfigured.

@alexr00
Copy link
Member

alexr00 commented Jan 18, 2022

It's not possible with the way that the tasks system is currently implemented. The npm extension already provides a way to do this without renaming scrips using the path property too.

@clshortfuse
Copy link

clshortfuse commented Feb 7, 2022

My workaround is to just add spaces to the script name:

script": "debug" => script": "debug " => script": " debug "

Also, on @alexr00 point:

Tasks are not identified by label, a label is just a nice human readable string.

That's not entirely true. launch.json specifically picks tasks by label. This is how I found this issue in the first place. preLaunchTask expects a label. So it's strange launch.json can "see" labels, but tasks.json can't.

I also don't think this is a "polish" issue. Having to add spaces is a sloppy workaround, and it's confusing trying to integrate launch.json, where when it's clearly defined in tasks.json, but refuses to work.

@clshortfuse
Copy link

clshortfuse commented Feb 7, 2022

After a lot of digging, it seems npm tasks aren't considered CustomTask objects, so it uses the TaskRegistry to build the identifier. If it was a CustomTask, then it works by label.

identifier = { type: 'npm', script: customize.substring(npm.length + 4) };

Basically, it creates an identifier, and then a keyed one based on its properties:

let taskIdentifier: Tasks.KeyedTaskIdentifier | undefined = Tasks.TaskDefinition.createTaskIdentifier(identifier, context.problemReporter);

Since the fields passed aren't unique enough, the key is duplicated and only the last entry will persist when it eventually moves to a Map. One solution is to move to entry tuples (eg: [key, value][]), or increase uniqueness by uses more fields in the npm identifier. I think just including options property is enough.

It also seems this bug isn't just npm, but grunt, jake, gulp, and typescript as well.

Edit: Oh, I think I'm wrong about some of that. Basically, createTaskIdentifier will build a unique key around required parameters. Because options isn't required, it won't be included when creating a unique identifier.

@clshortfuse
Copy link

Workaround of using spaces no longer works as of v1.66.2 :(

@alexr00 alexr00 assigned meganrogge and unassigned alexr00 Jun 30, 2022
@jakebailey
Copy link
Member

I just hit this in the TS repo, where I'm changing our build but leaving some tasks behind for backwards compat. I had:

        {
            "label": "npm: build:tests",
            "type": "npm",
            "script": "build:tests",
            "group": "build",
            "problemMatcher": [
                "$tsc"
            ]
        },
        {
            "label": "gulp: tests",
            "type": "npm",
            "script": "build:tests",
            "group": "build",
            "hide": true,
            "problemMatcher": [
                "$tsc"
            ]
        },

We don't commit launch.json, but we do commit tasks.json, so I was leaving an old task behind as to not cause breakage for the people on my team with old launch configs. But, when I opened the task menu, I only saw the latter open.

The "fix" for me was to move the deprecated gulp task to the top (with a big explanatory comment), as the last use of a script is the one that appears to win. Obviously, this only works because I am content with just one of the scripts showing up, and we don't set cwd or anything.

@starball5
Copy link

Related on Stack Overflow: Why does only the last NPM task in VS Code of several that only vary by label and options (and not the script) get picked up?

@golf1052
Copy link
Member

golf1052 commented Feb 6, 2024

@alexr00 @meganrogge If an external contributor wanted to try and fix this what would be the next steps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue identified by VS Code Team member as probable bug polish Cleanup and polish issue tasks Task system issues
Projects
None yet
Development

No branches or pull requests

10 participants