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
180 stars 79 forks source link

When working with extension tags internal contribution references are broken #172

Open FlexiGit opened 4 years ago

FlexiGit commented 4 years ago

If you are working with extension tags for different release stages of your extension, internal contribution references are broken. For example you could use a feature contribution to enable/disable some other contributions on project level. Unfortunately the references only work with the full extension id. So when using the extension tags this reference is broken.

The original manifest:

{
    "id": "someextid",
    "publisher": "somepub",
...
    "contributions": [
        {
            "id": "page",
            "type": "ms.vss-work-web.work-item-form-page",
            "description": "A page for the work item form",
            "targets": [
                "ms.vss-work-web.work-item-form"
            ],
            "properties": {
                "name": "Page name",
                "uri": "pages/Page.html"
            },
            "constraints": [
                {
                    "name": "Feature",
                    "properties": {
                        "featureId": "somepub.someextid.feature"
                    }
                }
            ]
        },
        {
            "id": "feature",
            "type": "ms.vss-web.feature",
            "description": "A feature toggle to enable/disable the extension on project level",
            "targets": [ "ms.vss-web.managed-features" ],
            "properties": {
                "name": "Feature name",
                "userConfigurable": false,
                "hostConfigurable": true,
                "hostScopes": [ "project" ],
                "defaultState": true
            }
        }
    ]
}

With applied extension tag:

{
    "id": "someextid-tag",
    "publisher": "somepub",
...
    "contributions": [
        {
            "id": "page",
            "type": "ms.vss-work-web.work-item-form-page",
            "description": "A page for the work item form",
            "targets": [
                "ms.vss-work-web.work-item-form"
            ],
            "properties": {
                "name": "Page name",
                "uri": "pages/Page.html"
            },
            "constraints": [
                {
                    "name": "Feature",
                    "properties": {
                        "featureId": "somepub.someextid.feature"
                    }
                }
            ]
        },
        {
            "id": "feature",
            "type": "ms.vss-web.feature",
            "description": "A feature toggle to enable/disable the extension on project level",
            "targets": [ "ms.vss-web.managed-features" ],
            "properties": {
                "name": "Feature name",
                "userConfigurable": false,
                "hostConfigurable": true,
                "hostScopes": [ "project" ],
                "defaultState": true
            }
        }
    ]
}

This doesn't work, because the page still uses the the untagged feature id.

Expectation: The extensions tasks transform the internal references as well.

jessehouwing commented 4 years ago

Does this work when publishing from Source?

I can see that this would fail when publishing from VSIX, as this extension does much of the patching manually.

PS: I consider this a bug, all references should be local to the current publisher/extension when no specified. That would be an implementation issue in the way feature toggles are referenced. I'll report that to the Azure DevOps Team.

jessehouwing commented 4 years ago

The issue is very similar to https://github.com/microsoft/azure-devops-extension-tasks/pull/167

I'd accept a PR on this to fix if the product team considers this not a bug.

FlexiGit commented 4 years ago

Does this work when publishing from Source?

No. Publishing from source works only with the fully qualified extension id, too.

jessehouwing commented 4 years ago

Then it's primarily a bug in tfx-cli and/or a bug in Azure DevOps itself.

jessehouwing commented 4 years ago

Can you report it here: https://github.com/microsoft/tfs-cli, we primarily just call tfx and it should handle as much of the override logic as possible. Though we may need to mimic what they do for the publish a vsix codepath.

FlexiGit commented 4 years ago

Thanks for the hint. For reference: https://github.com/microsoft/tfs-cli/issues/352

jessehouwing commented 3 years ago

I'll close it here. I still believe it's a bug in the extensibility. The base rule is that when an extension omits a specific scope the contribution targets self. The manifest should honor that contract.

MarioMajcicaAtABNAMRO commented 3 months ago

I do think this is still an issue of the extension. Once we define a feature, to reference it in a contribution we need to use the "full feature name", in form of publiserId.extensionId.featureId. In case that we get to use tags in the task, extensionId changes, but it the feature reference is not adjusted. e.g.

"contributions": [
{
    "id": "governed-repository-action",
    "type": "ms.vss-web.external-content",
    "properties": {
        "uri": "dist/governed-repository/index.html"
    },
    "constraints": [
        {
            "name": "Feature",
            "properties": {
                "featureId": "my-extensions.self-service-resource-management.compliant-repo-visibility"
            }
        }
    ]
},

As you can see, in the "featureId": "my-extensions.self-service-resource-management.compliant-repo-visibility" we have the "full name" of the feature.

Now, if we use extensionTag: '-test', that field is not adjusted to the new extension id.

Let me see if I can explain myself better with a PR.

MarioMajcicaAtABNAMRO commented 3 months ago

I do think this is still an issue of the extension. Once we define a feature, to reference it in a contribution we need to use the "full feature name", in form of publiserId.extensionId.featureId. In case that we get to use tags in the task, extensionId changes, but it the feature reference is not adjusted. e.g.

"contributions": [
{
  "id": "governed-repository-action",
  "type": "ms.vss-web.external-content",
  "properties": {
      "uri": "dist/governed-repository/index.html"
  },
  "constraints": [
      {
          "name": "Feature",
          "properties": {
              "featureId": "my-extensions.self-service-resource-management.compliant-repo-visibility"
          }
      }
  ]
},

As you can see, in the "featureId": "my-extensions.self-service-resource-management.compliant-repo-visibility" we have the "full name" of the feature.

Now, if we use extensionTag: '-test', that field is not adjusted to the new extension id.

Let me see if I can explain myself better with a PR.

As nothing said, I see now in the code that you are not modifying the extension manifest but just using the --extension-id parameter of tfs-cli

Thus indeed this should be something for https://github.com/microsoft/tfs-cli

Sorry for the confusion.

jessehouwing commented 3 months ago

If you ask me the extension manifest should never have contained the publisher and extension it for this, but that ship has sailed.

MarioMajcicaAtABNAMRO commented 3 months ago

If you ask me the extension manifest should never have contained the publisher and extension it for this, but that ship has sailed.

I do agree completely. If anyone else is searching for the solution, I have kind of a workaround, not too elegant, but it works.

On the contributions, under the constraints, specify all of your 'versions' of the extension feature and separate them with groups (and this one is necessary as they are evaluated with an OR in this case, ContributionConstraint interface )

"constraints": [
    {
        "name": "Feature",
        "group": 1,
        "properties": {
            "featureId": "publisherId.extensionID-test.compliant-repo-project-visibility"
        }
    },
    {
        "name": "Feature",
        "group": 2,
        "properties": {
            "featureId": "publisherId.extensionID.compliant-repo-project-visibility"
        }
    }
]
jessehouwing commented 3 months ago

It wouldn't be impossible to fix this, but it would require overwriting the vss-extension.json during packaging and publication. There's already similar logic in the vsixEditor.ts:

https://github.com/microsoft/azure-devops-extension-tasks/blob/main/BuildTasks/PublishExtension/v5/vsixeditor.ts

jessehouwing commented 3 months ago

I'd accept a PR in this direction.

mmajcica commented 3 months ago

@jessehouwing I gave it a try, check if I'm on the right path with what you had in mind and if so, I would would wrap this PR up, test it and then we can review it.

Cheers