microsoft / azure-devops-extension-tasks

Pipeline tasks for Azure DevOps Extensions
https://marketplace.visualstudio.com/items?itemName=ms-devlabs.vsts-developer-tools-build-tasks
MIT License
175 stars 79 forks source link

PublishExtension cannot derive the ID of a VSIX-packaged extension, so `updateTasksId` doesn't work #205

Open SimonAlling opened 2 years ago

SimonAlling commented 2 years ago

Problem

The updateTasksId input is described like this:

Search for contributed tasks in extension manifests and updates the id specified in each Build and Release task found based on the Publisher, ExtensionId and TaskName.

Note in particular that the ID is claimed to be "based on […] ExtensionId". And sure enough, if the extensionId input is specified, for example

- task: PublishAzureDevOpsExtension@3
  inputs:
    connectTo: VsTeam
    connectedServiceName: some-service-connection
    fileType: vsix
    vsixFile: cool-extension.vsix
    updateTasksId: true
    extensionId: foobar # 👈

then its value affects the generated ID of each task in the extension.

But if extensionId is not specified, then I'd expect that the extension ID be derived from the already packaged VSIX file. However, the extension ID specified when creating the VSIX (e.g. in vss-extension.json) does not affect the generated task ID(s), as evident by the line ##[debug]Task manifest CoolTask id after: 123e4567-e89b-12d3-a456-426614174000 in the pipeline log, which always contains the same UUID (although the one used here is just an example).

Investigation

On line 441 in BuildTasks/Common/Common.ts, we can see that the extension ID effectively used to generate a task ID is

`${(tl.getInput("extensionId", false) || manifest.id)}${extensionTag}`

which, when the extensionId input is not specified, is equivalent to

`${manifest.id}${extensionTag}`

On line 429, manifest is read and parsed as JSON from the file identified by extensionPath, which is an element in manifestPaths, the first argument passed to updateTaskManifests. This function is called on line 420; passed as the first argument is the first parameter of updateManifests (or, under certain conditions, potentially the result of calling getExtensionManifestPaths).

updateManifests in turn is called on line 550 with either a singleton list containing the first argument passed to checkUpdateTasksManifests or the empty list. checkUpdateTasksManifests is called on line 182 in BuildTasks/PublishExtension/vsixeditor.ts; the argument passed to it is a path ending in "extension.vsomanifest".

In other words, it appears that the extension ID of a VSIX-packaged extension is derived from a file named extension.vsomanifest inside it. Here's an example of the contents of that file inside a VSIX file packed by tfx extension create:

📃 Content of extension.vsomanifest ```json { "manifestVersion": 1, "contributions": [ { "id": "cool-contribution", "type": "ms.vss-distributed-task.task", "targets": [ "ms.vss-distributed-task.tasks" ], "properties": { "name": "CoolTask" } } ], "scopes": [], "contributionTypes": [] } ```

The id property of a JSON object parsed from that file is of course undefined, regardless of the actual ID used when packaging the VSIX.

(Inside the VSIX file, there is also a file named extension.vsixmanifest, which does contain the actual extension ID, but it is an XML file, not a JSON one.)

Logs etc

$ tfx version
TFS Cross Platform Command Line Interface v0.9.2
Copyright Microsoft Corporation
Version 0.9.2
📃 Pipeline log ``` ============================================================================== Task : Publish Extension Description : Publish an Azure DevOps extension to the Visual Studio Marketplace Version : 3.1.82 Author : Microsoft Corporation Help : ============================================================================== […] ##[debug]Look for build tasks manifest ##[debug]updateTasksVersion=false ##[debug]updateTasksId=true ##[debug]Found manifests: /tmp/vsixeditor121717-3350-1cg4dgi.fl8h69a4i/extension.vsomanifest ##[debug]Found task: CoolTask ##[debug]localizationRoot=/home/vsts/work/1/s ##[debug]Absolute path for pathSegments: /home/vsts/work/1/s = /home/vsts/work/1/s ##[debug]build.sourcesDirectory=/home/vsts/work/1/s ##[debug]Absolute path for pathSegments: /home/vsts/work/1/s = /home/vsts/work/1/s ##[debug]localizationRootpath supplied :false ##[debug]Found single-task manifest: /tmp/vsixeditor121717-3350-1cg4dgi.fl8h69a4i/CoolTask/task.json ##[debug]Patching: /tmp/vsixeditor121717-3350-1cg4dgi.fl8h69a4i/CoolTask/task.json. ##[debug]Updating Id... ##[debug]publisherId=undefined ##[debug]extensionTag=undefined ##[debug]extensionId=undefined ##[debug]Task manifest CoolTask id before: 00000000-0000-0000-0000-000000000000 ##[debug]Task manifest CoolTask id after: 123e4567-e89b-12d3-a456-426614174000 ##[debug]Updated: /tmp/vsixeditor121717-3350-1cg4dgi.fl8h69a4i/CoolTask/task.json. ##[debug]Patching: /tmp/vsixeditor121717-3350-1cg4dgi.fl8h69a4i/extension.vsomanifest. ##[debug]Updating: 00000000-0000-0000-0000-000000000000 => 123e4567-e89b-12d3-a456-426614174000. ##[debug]Editing VSIX manifest ```
jessehouwing commented 2 years ago

Good find. Would love to take a pull request to fix that. My current bandwidth is very low. As a workaround, specify the ExtensionID on the task.