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);