From b260edcec35d6c22e0246566a50498a3382df02f Mon Sep 17 00:00:00 2001 From: Sakshi Sharma <57200045+SakshiS-harma@users.noreply.github.com> Date: Mon, 15 May 2023 16:14:07 -0700 Subject: [PATCH] Add ability to create publish profile from project context (#23110) * Ability to add publish profile from project context * Add/update test + fix Build vs None addition to sqlproj file --- extensions/sql-database-projects/package.json | 14 ++++++++++++++ extensions/sql-database-projects/package.nls.json | 1 + .../newPublishProfileTemplate.publish.xml | 14 ++++++++++++++ .../sql-database-projects/src/common/constants.ts | 1 + .../src/controllers/mainController.ts | 1 + .../src/controllers/projectController.ts | 12 +++++++++--- .../sql-database-projects/src/sqldbproj.d.ts | 9 ++++++++- .../src/templates/templates.ts | 3 ++- .../src/test/projectController.test.ts | 13 +++++++++++++ .../src/test/templates.test.ts | 2 +- 10 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 extensions/sql-database-projects/resources/templates/newPublishProfileTemplate.publish.xml diff --git a/extensions/sql-database-projects/package.json b/extensions/sql-database-projects/package.json index 564885b8b9..a7d979b526 100644 --- a/extensions/sql-database-projects/package.json +++ b/extensions/sql-database-projects/package.json @@ -207,6 +207,11 @@ "command": "sqlDatabaseProjects.rename", "title": "%sqlDatabaseProjects.rename%", "category": "%sqlDatabaseProjects.displayName%" + }, + { + "command": "sqlDatabaseProjects.newPublishProfile", + "title": "%sqlDatabaseProjects.newPublishProfile%", + "category": "%sqlDatabaseProjects.displayName%" } ], "menus": { @@ -334,6 +339,10 @@ { "command": "sqlDatabaseProjects.rename", "when": "false" + }, + { + "command": "sqlDatabaseProjects.newPublishProfile", + "when": "false" } ], "view/item/context": [ @@ -402,6 +411,11 @@ "when": "view == dataworkspace.views.main && viewItem =~ /^(databaseProject.itemType.project|databaseProject.itemType.legacyProject)$/ || viewItem == databaseProject.itemType.folder", "group": "3_dbProjects_newItem@9" }, + { + "command": "sqlDatabaseProjects.newPublishProfile", + "when": "view == dataworkspace.views.main && viewItem =~ /^(databaseProject.itemType.project|databaseProject.itemType.legacyProject)$/ || viewItem == databaseProject.itemType.folder", + "group": "3_dbProjects_newItem@10" + }, { "command": "sqlDatabaseProjects.addDatabaseReference", "when": "view == dataworkspace.views.main && viewItem == databaseProject.itemType.referencesRoot", diff --git a/extensions/sql-database-projects/package.nls.json b/extensions/sql-database-projects/package.nls.json index 4beced28f6..60973d5242 100644 --- a/extensions/sql-database-projects/package.nls.json +++ b/extensions/sql-database-projects/package.nls.json @@ -28,6 +28,7 @@ "sqlDatabaseProjects.newItem": "Add Item...", "sqlDatabaseProjects.addExistingItem": "Add Existing Item...", "sqlDatabaseProjects.newFolder": "Add Folder", + "sqlDatabaseProjects.newPublishProfile": "Add Publish Profile", "sqlDatabaseProjects.addDatabaseReference": "Add Database Reference", "sqlDatabaseProjects.addSqlCmdVariable": "Add SQLCMD Variable", diff --git a/extensions/sql-database-projects/resources/templates/newPublishProfileTemplate.publish.xml b/extensions/sql-database-projects/resources/templates/newPublishProfileTemplate.publish.xml new file mode 100644 index 0000000000..818466670b --- /dev/null +++ b/extensions/sql-database-projects/resources/templates/newPublishProfileTemplate.publish.xml @@ -0,0 +1,14 @@ + + + + @@PROJECT_NAME@@ + True + True + True + True + False + False + True + 1 + + diff --git a/extensions/sql-database-projects/src/common/constants.ts b/extensions/sql-database-projects/src/common/constants.ts index 2f9fed76a4..8373d9bd89 100644 --- a/extensions/sql-database-projects/src/common/constants.ts +++ b/extensions/sql-database-projects/src/common/constants.ts @@ -456,6 +456,7 @@ export const externalStreamFriendlyName = localize('externalStream', "External S export const externalStreamingJobFriendlyName = localize('externalStreamingJobFriendlyName', "External Streaming Job"); export const preDeployScriptFriendlyName = localize('preDeployScriptFriendlyName', "Script.PreDeployment"); export const postDeployScriptFriendlyName = localize('postDeployScriptFriendlyName', "Script.PostDeployment"); +export const publishProfileFriendlyName = localize('publishProfileFriendlyName', "Publish Profile"); //#endregion diff --git a/extensions/sql-database-projects/src/controllers/mainController.ts b/extensions/sql-database-projects/src/controllers/mainController.ts index a9b018ce93..6180254789 100644 --- a/extensions/sql-database-projects/src/controllers/mainController.ts +++ b/extensions/sql-database-projects/src/controllers/mainController.ts @@ -78,6 +78,7 @@ export default class MainController implements vscode.Disposable { this.context.subscriptions.push(vscode.commands.registerCommand('sqlDatabaseProjects.newItem', async (node: WorkspaceTreeItem) => { return this.projectsController.addItemPromptFromNode(node); })); this.context.subscriptions.push(vscode.commands.registerCommand('sqlDatabaseProjects.addExistingItem', async (node: WorkspaceTreeItem) => { return this.projectsController.addExistingItemPrompt(node); })); this.context.subscriptions.push(vscode.commands.registerCommand('sqlDatabaseProjects.newFolder', async (node: WorkspaceTreeItem) => { return this.projectsController.addFolderPrompt(node); })); + this.context.subscriptions.push(vscode.commands.registerCommand('sqlDatabaseProjects.newPublishProfile', async (node: WorkspaceTreeItem) => { return this.projectsController.addItemPromptFromNode(node, ItemType.publishProfile); })); this.context.subscriptions.push(vscode.commands.registerCommand('sqlDatabaseProjects.addDatabaseReference', async (node: WorkspaceTreeItem) => { return this.projectsController.addDatabaseReference(node); })); this.context.subscriptions.push(vscode.commands.registerCommand('sqlDatabaseProjects.openContainingFolder', async (node: WorkspaceTreeItem) => { return this.projectsController.openContainingFolder(node); })); diff --git a/extensions/sql-database-projects/src/controllers/projectController.ts b/extensions/sql-database-projects/src/controllers/projectController.ts index 011b3a1290..ed538b00f5 100644 --- a/extensions/sql-database-projects/src/controllers/projectController.ts +++ b/extensions/sql-database-projects/src/controllers/projectController.ts @@ -246,6 +246,9 @@ export class ProjectsController { case ItemType.postDeployScript: await project.addPostDeploymentScript(relativePath); break; + case ItemType.publishProfile: + await project.addNoneItem(relativePath); + break; default: // a normal SQL object script await project.addSqlObjectScript(relativePath); break; @@ -729,7 +732,10 @@ export class ProjectsController { const itemType = templates.get(itemTypeName); const absolutePathToParent = path.join(project.projectFolderPath, relativePath); - let itemObjectName = await this.promptForNewObjectName(itemType, project, absolutePathToParent, constants.sqlFileExtension, options?.defaultName); + const isItemTypePublishProfile = itemTypeName === constants.publishProfileFriendlyName || itemTypeName === ItemType.publishProfile; + const fileExtension = isItemTypePublishProfile ? constants.publishProfileExtension : constants.sqlFileExtension; + const defaultName = isItemTypePublishProfile ? `${project.projectFileName}_` : options?.defaultName; + let itemObjectName = await this.promptForNewObjectName(itemType, project, absolutePathToParent, fileExtension, defaultName); itemObjectName = itemObjectName?.trim(); @@ -737,7 +743,7 @@ export class ProjectsController { return; // user cancelled } - const relativeFilePath = path.join(relativePath, itemObjectName + constants.sqlFileExtension); + const relativeFilePath = path.join(relativePath, itemObjectName + fileExtension); const telemetryProps: Record = { itemType: itemType.type }; const telemetryMeasurements: Record = {}; @@ -749,7 +755,7 @@ export class ProjectsController { } try { - const absolutePath = await this.addFileToProjectFromTemplate(project, itemType, relativeFilePath, new Map([['OBJECT_NAME', itemObjectName]])); + const absolutePath = await this.addFileToProjectFromTemplate(project, itemType, relativeFilePath, new Map([['OBJECT_NAME', itemObjectName], ['PROJECT_NAME', project.projectFileName]])); TelemetryReporter.createActionEvent(TelemetryViews.ProjectTree, TelemetryActions.addItemFromTree) .withAdditionalProperties(telemetryProps) diff --git a/extensions/sql-database-projects/src/sqldbproj.d.ts b/extensions/sql-database-projects/src/sqldbproj.d.ts index c6a0433699..dfd939fb5a 100644 --- a/extensions/sql-database-projects/src/sqldbproj.d.ts +++ b/extensions/sql-database-projects/src/sqldbproj.d.ts @@ -104,7 +104,8 @@ declare module 'sqldbproj' { externalStreamingJob = 'externalStreamingJob', folder = 'folder', preDeployScript = 'preDeployScript', - postDeployScript = 'postDeployScript' + postDeployScript = 'postDeployScript', + publishProfile = 'publishProfile' } /** @@ -152,6 +153,12 @@ declare module 'sqldbproj' { */ addPostDeploymentScript(relativePath: string): Promise; + /** + * Adds a none item that is not included in "Build" + * @param relativePath + */ + addNoneItem(relativePath: string): Promise; + /** * Add a SQL object script that will be included in the schema * @param relativePath diff --git a/extensions/sql-database-projects/src/templates/templates.ts b/extensions/sql-database-projects/src/templates/templates.ts index 492e8f9dc5..8cfb984750 100644 --- a/extensions/sql-database-projects/src/templates/templates.ts +++ b/extensions/sql-database-projects/src/templates/templates.ts @@ -48,7 +48,8 @@ export async function loadTemplates(templateFolderPath: string) { loadObjectTypeInfo(ItemType.dataSource, constants.dataSourceFriendlyName, templateFolderPath, 'newTsqlDataSourceTemplate.sql'), loadObjectTypeInfo(ItemType.fileFormat, constants.fileFormatFriendlyName, templateFolderPath, 'newTsqlFileFormatTemplate.sql'), loadObjectTypeInfo(ItemType.externalStream, constants.externalStreamFriendlyName, templateFolderPath, 'newTsqlExternalStreamTemplate.sql'), - loadObjectTypeInfo(ItemType.externalStreamingJob, constants.externalStreamingJobFriendlyName, templateFolderPath, 'newTsqlExternalStreamingJobTemplate.sql') + loadObjectTypeInfo(ItemType.externalStreamingJob, constants.externalStreamingJobFriendlyName, templateFolderPath, 'newTsqlExternalStreamingJobTemplate.sql'), + loadObjectTypeInfo(ItemType.publishProfile, constants.publishProfileFriendlyName, templateFolderPath, 'newPublishProfileTemplate.publish.xml') ]); for (const scriptType of scriptTypes) { diff --git a/extensions/sql-database-projects/src/test/projectController.test.ts b/extensions/sql-database-projects/src/test/projectController.test.ts index 15cf1ce79d..9905c89cdc 100644 --- a/extensions/sql-database-projects/src/test/projectController.test.ts +++ b/extensions/sql-database-projects/src/test/projectController.test.ts @@ -429,6 +429,19 @@ describe('ProjectsController', function (): void { should(project.postDeployScripts.length).equal(1, 'Post deploy script should be successfully added'); }); + it('Should be able to add publish profile', async function (): Promise { + const publishProfileName = 'profile.publish.xml'; + + const projController = new ProjectsController(testContext.outputChannel); + const project = await testUtils.createTestProject(this.test, baselines.newProjectFileBaseline); + + sinon.stub(vscode.window, 'showInputBox').resolves(publishProfileName); + sinon.stub(utils, 'sanitizeStringForFilename').returns(publishProfileName); + should(project.publishProfiles.length).equal(0, 'There should be no publish profiles'); + await projController.addItemPrompt(project, '', { itemType: ItemType.publishProfile }); + should(project.publishProfiles.length).equal(1, 'Publish profile should be successfully added.'); + }); + it('Should change target platform', async function (): Promise { sinon.stub(vscode.window, 'showQuickPick').resolves({ label: SqlTargetPlatform.sqlAzure }); diff --git a/extensions/sql-database-projects/src/test/templates.test.ts b/extensions/sql-database-projects/src/test/templates.test.ts index 71f505647b..10043227a5 100644 --- a/extensions/sql-database-projects/src/test/templates.test.ts +++ b/extensions/sql-database-projects/src/test/templates.test.ts @@ -23,7 +23,7 @@ describe('Templates: loading templates from disk', function (): void { // check expected counts - const numScriptObjectTypes = 10; + const numScriptObjectTypes = 11; should(templates.projectScriptTypes().length).equal(numScriptObjectTypes); should(Object.keys(templates.projectScriptTypes()).length).equal(numScriptObjectTypes);