diff --git a/BuildTasks/Common/v5/Common.ts b/BuildTasks/Common/v5/Common.ts index 7d33cb95..398efabf 100644 --- a/BuildTasks/Common/v5/Common.ts +++ b/BuildTasks/Common/v5/Common.ts @@ -7,6 +7,7 @@ import { AzureRMEndpoint } from "azure-pipelines-tasks-azure-arm-rest/azure-arm- import fse from "fs-extra"; import uuidv5 from "uuidv5"; import tmp from "tmp"; +import { forEach } from "core-js/core/array"; function writeBuildTempFile(taskName: string, data: any): string { const tempDir = tl.getVariable("Agent.TempDirectory"); @@ -378,6 +379,35 @@ function updateExtensionManifestTaskIds(manifest: any, originalTaskId: string, n return manifest; } +function updateExtensionManifestsFeatureConstrains(manifest: any): unknown { + if (!manifest.contributions) { + tl.debug(`No contributions found`); + return manifest; + } + + const extensionTag = tl.getInput("extensionTag", false) || ""; + const extensionId = `${(tl.getInput("extensionId", false) || manifest.id)}${extensionTag}`; + + manifest.contributions + .filter((c: any) => c.constraints && c.constraints.length > 0) + .forEach((c: any) => { + c.constraints.forEach((constraint: any) => { + if (constraint.properties?.featureId) { + tl.debug(`Extension manifest featureId before: ${constraint.properties.featureId}`); + + const parts = constraint.properties.featureId.split("."); + parts[1] = extensionId; + const newFeatureId = parts.join("."); + constraint.properties.featureId = newFeatureId; + + tl.debug(`Extension manifest featureId after: ${newFeatureId}`); + } + }); + }); + + return manifest; +} + function updateTaskVersion(manifest: any, extensionVersionString: string, extensionVersionType: string): unknown { const versionParts = extensionVersionString.split("."); if (versionParts.length > 3) { @@ -414,6 +444,8 @@ function updateTaskVersion(manifest: any, extensionVersionString: string, extens export async function updateManifests(manifestPaths: string[]): Promise { const updateTasksVersion = tl.getBoolInput("updateTasksVersion", false); const updateTasksId = tl.getBoolInput("updateTasksId", false); + const extensionTag = tl.getInput("extensionTag", false); + const updateFeatureConstraints = tl.getBoolInput("updateFeatureConstraints", false); if (updateTasksVersion || updateTasksId) { if (!(manifestPaths && manifestPaths.length)) { @@ -423,7 +455,17 @@ export async function updateManifests(manifestPaths: string[]): Promise { tl.debug(`Found manifests: ${manifestPaths.join(", ")}`); const tasksIds = await updateTaskManifests(manifestPaths, updateTasksId, updateTasksVersion); - await updateExtensionManifests(manifestPaths, tasksIds); + await updateExtensionManifestsTaskIds(manifestPaths, tasksIds); + } + + if (extensionTag && updateFeatureConstraints) { + if (!(manifestPaths && manifestPaths.length)) { + manifestPaths = getExtensionManifestPaths(); + } + + tl.debug(`Found manifests: ${manifestPaths.join(", ")}`); + + await updateExtensionManifestsFeatureConstrains(manifestPaths); } } @@ -475,7 +517,7 @@ async function updateTaskManifests(manifestPaths: string[], updateTasksId: boole return tasksIds; } -async function updateExtensionManifests(manifestPaths: string[], updatedTaskIds: [string, string][]): Promise { +async function updateExtensionManifestsTaskIds(manifestPaths: string[], updatedTaskIds: [string, string][]): Promise { await Promise.all(manifestPaths.map(async (path) => { tl.debug(`Patching: ${path}.`); let originalManifest = await getManifest(path); diff --git a/BuildTasks/PublishExtension/v5/PublishExtension.ts b/BuildTasks/PublishExtension/v5/PublishExtension.ts index e8f20eb5..1686c6f8 100644 --- a/BuildTasks/PublishExtension/v5/PublishExtension.ts +++ b/BuildTasks/PublishExtension/v5/PublishExtension.ts @@ -59,6 +59,7 @@ await common.runTfx(async tfx => { const extensionVersion = common.getExtensionVersion(); const updateTasksId = tl.getBoolInput("updateTasksId", false); const updateTasksVersion = tl.getBoolInput("updateTasksVersion", false); + const updateFeatureConstraints = tl.getBoolInput("updateFeatureConstraints", false); if (publisher || extensionId @@ -67,7 +68,8 @@ await common.runTfx(async tfx => { || (extensionPricing && extensionPricing !== "default") || (extensionVisibility && extensionVisibility !== "default") || extensionVersion - || updateTasksId) { + || updateTasksId + || updateFeatureConstraints) { tl.debug("Start editing of VSIX"); const ve = new VsixEditor(vsixFile, vsixOutput); @@ -77,6 +79,7 @@ await common.runTfx(async tfx => { if (extensionId) { ve.editId(extensionId); } if (extensionTag) { ve.editIdTag(extensionTag); } if (extensionName) { ve.editExtensionName(extensionName); } + if (updateFeatureConstraints) { ve.editUpdateFeatureConstraints(updateFeatureConstraints); } if (extensionVisibility) { ve.editExtensionVisibility(extensionVisibility); } if (extensionPricing) { ve.editExtensionPricing(extensionPricing); } if (extensionVersion) { diff --git a/BuildTasks/PublishExtension/v5/task.json b/BuildTasks/PublishExtension/v5/task.json index c40be950..81defccd 100644 --- a/BuildTasks/PublishExtension/v5/task.json +++ b/BuildTasks/PublishExtension/v5/task.json @@ -176,6 +176,15 @@ "required": false, "groupName": "manifest" }, + { + "name": "updateFeatureConstraints", + "type": "boolean", + "label": "Override feature Id", + "defaultValue": "false", + "required": false, + "helpMarkDown": "Search for feature constraints in extension manifests and updates the featureId to match the actual extension id.", + "groupName": "manifest" + }, { "name": "updateTasksVersion", "type": "boolean", diff --git a/BuildTasks/PublishExtension/v5/vsixeditor.ts b/BuildTasks/PublishExtension/v5/vsixeditor.ts index 7a6d66ab..6301efb7 100644 --- a/BuildTasks/PublishExtension/v5/vsixeditor.ts +++ b/BuildTasks/PublishExtension/v5/vsixeditor.ts @@ -109,6 +109,7 @@ export default class VSIXEditor { private extensionPricing: string = null; private updateTasksVersion = true; private updateTasksId = true; + private updateFeatureConstraints = false; constructor( public inputFile: string, @@ -203,7 +204,9 @@ export default class VSIXEditor { tl.debug("Extracting files to " + dirPath); await this.extractArchive(this.inputFile, dirPath); - if (this.versionNumber && this.updateTasksVersion || this.updateTasksId) { + + if (this.versionNumber && this.updateTasksVersion || this.updateTasksId || + this.editIdTag && this.editUpdateFeatureConstraints) { tl.debug("Look for build tasks manifest"); const extensionManifest = path.join(dirPath, "extension.vsomanifest"); await common.checkUpdateTasksManifests(extensionManifest); @@ -344,6 +347,11 @@ export default class VSIXEditor { this.updateTasksId = updateTasksId; } + public editUpdateFeatureConstraints(updateFeatureConstraints: boolean) { + this.validateEditMode(); + this.updateFeatureConstraints = updateFeatureConstraints; + } + private validateEditMode() : void { if (!this.edit) { throw new Error("Editing is not started"); } }