diff --git a/.gitignore b/.gitignore index 8f85b558..da19423f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ BuildTasks/*Extension*/common.ts *.vsix /.vs -*.sqlite \ No newline at end of file +*.sqlite +/slnx.VC.VC.opendb +/slnx.VC.db diff --git a/BuildTasks/Common/Common.ts b/BuildTasks/Common/Common.ts index 9693949d..1553971b 100644 --- a/BuildTasks/Common/Common.ts +++ b/BuildTasks/Common/Common.ts @@ -79,7 +79,25 @@ export function setTfxManifestArguments(tfx: ToolRunner): (() => void) { const isPreview = extensionVisibility.indexOf("preview") >= 0; jsonOverrides.public = isPublic; - if (isPreview) { jsonOverrides.galleryFlags = ["Preview"]; }; + + if (isPreview) { + jsonOverrides.galleryFlags = jsonOverrides.galleryFlags || []; + jsonOverrides.galleryFlags.Push("Preview"); + }; + } + + const extensionPricing = tl.getInput("extensionPricing", false); + if (extensionPricing && extensionPricing !== "default") { + tl.debug(`Overriding extension pricing to: ${extensionPricing}`); + jsonOverrides = (jsonOverrides || {}); + + const isFree = extensionPricing.indexOf("free") >= 0; + const isPaid = extensionPricing.indexOf("paid") >= 0; + + if (isPaid) { + jsonOverrides.galleryFlags = jsonOverrides.galleryFlags || []; + jsonOverrides.galleryFlags.Push("Paid"); + } } let extensionVersion = getExtensionVersion(); diff --git a/BuildTasks/PackageExtension/PackageExtension.ts b/BuildTasks/PackageExtension/PackageExtension.ts index 13537638..9ea38842 100644 --- a/BuildTasks/PackageExtension/PackageExtension.ts +++ b/BuildTasks/PackageExtension/PackageExtension.ts @@ -41,5 +41,4 @@ common.runTfx(tfx => { }).fail(err => { tl.setResult(tl.TaskResult.Failed, `Error occurred while updating tasks version: ${err}`); }); -}); - +}); \ No newline at end of file diff --git a/BuildTasks/PackageExtension/task.json b/BuildTasks/PackageExtension/task.json index 310f5d8a..7dd36cab 100644 --- a/BuildTasks/PackageExtension/task.json +++ b/BuildTasks/PackageExtension/task.json @@ -32,136 +32,150 @@ } ], "instanceNameFormat": "Package Extension: $(rootFolder)", - "inputs": [ - { - "name": "rootFolder", - "type": "filePath", - "label": "Root manifests folder", - "defaultValue": "", - "required": false, - "helpMarkDown": "Root folder from which the manifests are searched." - }, - { - "name": "localizationRoot", - "type": "filePath", - "label": "Localization Root folder", - "defaultValue": "", - "required": false, - "helpMarkDown": "Folder where localization file(s) exist." - }, - { - "name": "patternManifest", - "type": "string", - "label": "Manifest file", - "defaultValue": "vss-extension.json", - "required": false, - "helpMarkDown": "Specify the pattern for manifest files to join." - }, - { - "name": "outputPath", - "type": "filePath", - "label": "Package output file", - "defaultValue": "", - "required": false, - "helpMarkDown": "Specify the path and file name of the generated vsix." - }, - { - "name": "outputVariable", - "type": "string", - "label": "Output Variable", - "defaultValue": "Extension.OutputPath", - "required": false, - "helpMarkDown": "The variable name to assign the location of the generated package to." - }, - { - "name": "publisherId", - "type": "string", - "label": "Publisher ID", - "defaultValue": "", - "required": false, - "helpMarkDown": "Extension publisher ID. If not specified, the publisher specified in the manifest will be used.", - "groupName": "overrides" - }, - { - "name": "extensionId", - "type": "string", - "label": "Extension ID", - "defaultValue": "", - "helpMarkDown": "Overrides extension ID. If not specified, the extension ID specified in the manifest will be used", - "required": false, - "groupName": "overrides" - }, - { - "name": "extensionTag", - "type": "string", - "label": "Extension Tag", - "defaultValue": "", - "helpMarkDown": "Extension Tag to append to the extension ID", - "required": false, - "groupName": "overrides" - }, - { - "name": "extensionName", - "type": "string", - "label": "Extension name", - "defaultValue": "", - "helpMarkDown": "Overrides extension name. If not specified, the extension name specified in the manifest will be used", - "required": false, - "groupName": "overrides" - }, - { - "name": "extensionVersion", - "type": "string", - "label": "Extension version", - "defaultValue": "", - "helpMarkDown": "Overrides extension version. If not specified, the extension version specified in the manifest will be used", - "required": false, - "groupName": "overrides" - }, - { - "name": "updateTasksVersion", - "type": "boolean", - "label": "Override tasks version", - "defaultValue": "true", - "required": false, - "helpMarkDown": "Search for contributed tasks in extension manifests and updates the version specified in each Build and Release task found.", - "groupName": "overrides" - }, - { - "name": "extensionVisibility", - "type": "pickList", - "label": "Extension visibility", - "defaultValue": "", - "helpMarkDown": "Overrides extension visibility (Public vs Private) and optionally adds the Preview flag. If not specified, the extension visibility specified in the manifest will be used", - "required": false, - "groupName": "overrides", - "options": { - "default": "Not set", - "private": "Private", - "private_preview": "Private Preview", - "public_preview": "Public Preview", - "public": "Public" - } - }, - { - "name": "arguments", - "type": "string", - "label": "Arguments", - "defaultValue": "", - "helpMarkDown": "Additional arguments passed to tfx.", - "required": false, - "groupName": "advanced" - }, - { - "name": "cwd", - "type": "filePath", - "label": "Working Directory", - "defaultValue": "", - "required": false, - "helpMarkDown": "Current working directory when tfx is run. Defaults to the folder where the manifest is located.", - "groupName": "advanced" - } - ], + "inputs": [ + { + "name": "rootFolder", + "type": "filePath", + "label": "Root manifests folder", + "defaultValue": "", + "required": false, + "helpMarkDown": "Root folder from which the manifests are searched." + }, + { + "name": "localizationRoot", + "type": "filePath", + "label": "Localization Root folder", + "defaultValue": "", + "required": false, + "helpMarkDown": "Folder where localization file(s) exist." + }, + { + "name": "patternManifest", + "type": "string", + "label": "Manifest file", + "defaultValue": "vss-extension.json", + "required": false, + "helpMarkDown": "Specify the pattern for manifest files to join." + }, + { + "name": "outputPath", + "type": "filePath", + "label": "Package output file", + "defaultValue": "", + "required": false, + "helpMarkDown": "Specify the path and file name of the generated vsix." + }, + { + "name": "outputVariable", + "type": "string", + "label": "Output Variable", + "defaultValue": "Extension.OutputPath", + "required": false, + "helpMarkDown": "The variable name to assign the location of the generated package to." + }, + { + "name": "publisherId", + "type": "string", + "label": "Publisher ID", + "defaultValue": "", + "required": false, + "helpMarkDown": "Extension publisher ID. If not specified, the publisher specified in the manifest will be used.", + "groupName": "overrides" + }, + { + "name": "extensionId", + "type": "string", + "label": "Extension ID", + "defaultValue": "", + "helpMarkDown": "Overrides extension ID. If not specified, the extension ID specified in the manifest will be used", + "required": false, + "groupName": "overrides" + }, + { + "name": "extensionTag", + "type": "string", + "label": "Extension Tag", + "defaultValue": "", + "helpMarkDown": "Extension Tag to append to the extension ID", + "required": false, + "groupName": "overrides" + }, + { + "name": "extensionName", + "type": "string", + "label": "Extension name", + "defaultValue": "", + "helpMarkDown": "Overrides extension name. If not specified, the extension name specified in the manifest will be used", + "required": false, + "groupName": "overrides" + }, + { + "name": "extensionVersion", + "type": "string", + "label": "Extension version", + "defaultValue": "", + "helpMarkDown": "Overrides extension version. If not specified, the extension version specified in the manifest will be used", + "required": false, + "groupName": "overrides" + }, + { + "name": "updateTasksVersion", + "type": "boolean", + "label": "Override tasks version", + "defaultValue": "true", + "required": false, + "helpMarkDown": "Search for contributed tasks in extension manifests and updates the version specified in each Build and Release task found.", + "groupName": "overrides" + }, + { + "name": "extensionVisibility", + "type": "pickList", + "label": "Extension visibility", + "defaultValue": "default", + "helpMarkDown": "Overrides extension visibility (Public vs Private) and optionally adds the Preview flag. If not specified, the extension visibility specified in the manifest will be used", + "required": false, + "groupName": "overrides", + "options": { + "default": "Not set", + "private": "Private", + "private_preview": "Private Preview", + "public_preview": "Public Preview", + "public": "Public" + } + }, + { + "name": "extensionPricing", + "type": "pickList", + "label": "Extension pricing", + "defaultValue": "default", + "helpMarkDown": "Overrides extension pricing (Free vs Paid). If not specified, the extension pricing specified in the manifest will be used", + "required": false, + "groupName": "overrides", + "options": { + "default": "Not set", + "free": "Free", + "paid": "Paid" + } + }, + { + "name": "arguments", + "type": "string", + "label": "Arguments", + "defaultValue": "", + "helpMarkDown": "Additional arguments passed to tfx.", + "required": false, + "groupName": "advanced" + }, + { + "name": "cwd", + "type": "filePath", + "label": "Working Directory", + "defaultValue": "", + "required": false, + "helpMarkDown": "Current working directory when tfx is run. Defaults to the folder where the manifest is located.", + "groupName": "advanced" + } + ], "execution": { "Node": { "target": "PackageExtension.js", diff --git a/BuildTasks/PublishExtension/PublishExtension.ts b/BuildTasks/PublishExtension/PublishExtension.ts index 7bf49d9c..b593eb6b 100644 --- a/BuildTasks/PublishExtension/PublishExtension.ts +++ b/BuildTasks/PublishExtension/PublishExtension.ts @@ -30,23 +30,21 @@ common.runTfx(tfx => { const publisher = tl.getInput("publisherId", false); - let extensionId = tl.getInput("extensionId", false); + const extensionId = tl.getInput("extensionId", false); const extensionTag = tl.getInput("extensionTag", false); - if (extensionId && extensionTag) { - extensionId += extensionTag; - tl.debug(`Overriding extension id to: ${extensionId}`); - } - const extensionName = tl.getInput("extensionName", false); const extensionVisibility = tl.getInput("extensionVisibility", false); + const extensionPricing = tl.getInput("extensionPricing", false); const extensionVersion = common.getExtensionVersion(); const updateTasksVersion = tl.getBoolInput("updateTasksVersion", false); if (publisher || extensionId + || extensionTag || extensionName + || (extensionPricing && extensionPricing !== "default") || (extensionVisibility && extensionVisibility !== "default") || extensionVersion) { @@ -56,8 +54,10 @@ common.runTfx(tfx => { if (publisher) { ve.editPublisher(publisher); } if (extensionId) { ve.editId(extensionId); } + if (extensionTag) { ve.editIdTag(extensionTag); } if (extensionName) { ve.editExtensionName(extensionName); } if (extensionVisibility) { ve.editExtensionVisibility(extensionVisibility); } + if (extensionPricing) { ve.editExtensionPricing(extensionPricing); } if (extensionVersion) { ve.editVersion(extensionVersion); ve.editUpdateTasksVersion(updateTasksVersion); diff --git a/BuildTasks/PublishExtension/task.json b/BuildTasks/PublishExtension/task.json index 634508f8..328ba67b 100644 --- a/BuildTasks/PublishExtension/task.json +++ b/BuildTasks/PublishExtension/task.json @@ -183,6 +183,20 @@ }, "groupName": "manifest" }, + { + "name": "extensionPricing", + "type": "pickList", + "label": "Extension pricing", + "defaultValue": "default", + "helpMarkDown": "Overrides extension pricing (Free vs Paid). If not specified, the extension pricing specified in the manifest will be used", + "required": false, + "groupName": "manifest", + "options": { + "default": "Not set", + "free": "Free", + "paid": "Paid" + } + }, { "name": "outputVariable", "type": "string", diff --git a/BuildTasks/PublishExtension/vsixeditor.ts b/BuildTasks/PublishExtension/vsixeditor.ts index 10d0ed6a..3ae47bc3 100644 --- a/BuildTasks/PublishExtension/vsixeditor.ts +++ b/BuildTasks/PublishExtension/vsixeditor.ts @@ -13,9 +13,11 @@ export class VSIXEditor { private versionNumber: string = null; private id: string = null; + private idTag: string = null; private publisher: string = null; private extensionName: string = null; private extensionVisibility: string = null; + private extensionPricing: string = null; private updateTasksVersion: boolean = true; constructor(public inputFile: string, @@ -110,10 +112,11 @@ export class VSIXEditor { if (this.versionNumber) { identity._Version = this.versionNumber; } if (this.id) { identity._Id = this.id; } + if (this.idTag) { identity._Id += this.idTag; } if (this.publisher) { identity._Publisher = this.publisher; } if (this.extensionName) { vsixmanifest.PackageManifest.Metadata.DisplayName = this.extensionName; } if (this.extensionVisibility && this.extensionVisibility !== "default") { - let flagsEditor = new GalleryFlagsEditor(vsixmanifest.PackageManifest.Metadata.GalleryFlags); + const flagsEditor = new GalleryFlagsEditor(vsixmanifest.PackageManifest.Metadata.GalleryFlags); const isPublic = this.extensionVisibility.indexOf("public") >= 0; const isPreview = this.extensionVisibility.indexOf("preview") >= 0; @@ -134,12 +137,29 @@ export class VSIXEditor { vsixmanifest.PackageManifest.Metadata.GalleryFlags = flagsEditor.toString(); } + if (this.extensionPricing && this.extensionPricing !== "default") { + const flagsEditor = new GalleryFlagsEditor(vsixmanifest.PackageManifest.Metadata.GalleryFlags); + + const isFree = this.extensionPricing.indexOf("free") >= 0; + const isPaid = this.extensionPricing.indexOf("paid") >= 0; + + if (isFree) { + flagsEditor.removePaidFlag(); + } + + if (isPaid) { + flagsEditor.addPaidFlag(); + } + + vsixmanifest.PackageManifest.Metadata.GalleryFlags = flagsEditor.toString(); + } vsixManifestData = x2js.js2xml(vsixmanifest); let manifestData = new ManifestData(identity._Version, identity._Id, identity._Publisher, this.extensionVisibility, + this.extensionPricing, vsixmanifest.PackageManifest.Metadata.DisplayName, dirPath); @@ -154,9 +174,11 @@ export class VSIXEditor { public hasEdits(): boolean { return (this.versionNumber || this.id + || this.idTag || this.publisher || this.extensionName - || (this.extensionVisibility && this.extensionVisibility !== "default")); + || (this.extensionVisibility && this.extensionVisibility !== "default") + || (this.extensionPricing && this.extensionPricing !== "default")); } public editVersion(version: string) { @@ -174,11 +196,21 @@ export class VSIXEditor { this.extensionVisibility = visibility; } + public editExtensionPricing(pricing: string) { + this.validateEditMode(); + this.extensionPricing = pricing; + } + public editId(id: string) { this.validateEditMode(); this.id = id; } + public editIdTag(tag: string) { + this.validateEditMode(); + this.idTag = tag; + } + public editPublisher(publisher: string) { this.validateEditMode(); this.publisher = publisher; @@ -200,6 +232,7 @@ class ManifestData { public id: string, public publisher: string, public visibility: string, + public pricing: string, public name: string, public dirPath: string) { } @@ -253,6 +286,14 @@ class GalleryFlagsEditor { this.removeFlag("Public"); } + removePaidFlag() { + this.removeFlag("Paid"); + } + + addPaidFlag() { + this.addFlag("Paid"); + } + addPreviewFlag() { this.addFlag("Preview"); }