Handle output path and configuration in .sqlproj (#20426)

* Revert "Revert "Fix sql projects not using OutputPath in sqlproj for publishing (#19987)" (#20127)"

This reverts commit dc7522c661.

* read configuration from sqlproj

* Add more tests

* use last OutputPath in sqlproj
This commit is contained in:
Kim Santiago
2022-08-25 10:25:12 -07:00
committed by GitHub
parent f86d02e753
commit 06a3bf6718
9 changed files with 597 additions and 2 deletions

View File

@@ -20,6 +20,15 @@ import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings, IProjectRef
import { TelemetryActions, TelemetryReporter, TelemetryViews } from '../common/telemetry';
import { DacpacReferenceProjectEntry, FileProjectEntry, ProjectEntry, SqlCmdVariableProjectEntry, SqlProjectReferenceProjectEntry, SystemDatabase, SystemDatabaseReferenceProjectEntry } from './projectEntry';
/**
* Represents the configuration based on the Configuration property in the sqlproj
*/
enum Configuration {
Debug = 'Debug', // default used if the Configuration property is not specified
Release = 'Release',
Output = 'Output' // if a string besides debug or release is used, then Output is used as the configuration
}
/**
* Class representing a Project, and providing functions for operating on it
*/
@@ -36,9 +45,11 @@ export class Project implements ISqlProject {
private _postDeployScripts: FileProjectEntry[] = [];
private _noneDeployScripts: FileProjectEntry[] = [];
private _isSdkStyleProject: boolean = false; // https://docs.microsoft.com/en-us/dotnet/core/project-sdk/overview
private _outputPath: string = '';
private _configuration: Configuration = Configuration.Debug;
public get dacpacOutputPath(): string {
return path.join(this.projectFolderPath, 'bin', 'Debug', `${this._projectFileName}.dacpac`);
return path.join(this.outputPath, `${this._projectFileName}.dacpac`);
}
public get projectFolderPath() {
@@ -93,6 +104,14 @@ export class Project implements ISqlProject {
return this._isSdkStyleProject;
}
public get outputPath(): string {
return this._outputPath;
}
public get configuration(): Configuration {
return this._configuration;
}
private projFileXmlDoc: Document | undefined = undefined;
constructor(projectFilePath: string) {
@@ -155,6 +174,67 @@ export class Project implements ISqlProject {
this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.PropertyGroup)[0]?.appendChild(newProjectGuidNode);
await this.serializeToProjFile(this.projFileXmlDoc);
}
// get configuration
const configurationNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.Configuration);
if (configurationNodes.length > 0) {
const configuration = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.Configuration)[0].childNodes[0].nodeValue!;
switch (configuration.toLowerCase()) {
case Configuration.Debug.toString().toLowerCase():
this._configuration = Configuration.Debug;
break;
case Configuration.Release.toString().toLowerCase():
this._configuration = Configuration.Release;
break;
default:
// if the configuration doesn't match release or debug, the dacpac will get created in ./bin/Output
this._configuration = Configuration.Output;
}
} else {
// If configuration isn't specified in .sqlproj, set it to the default debug
this._configuration = Configuration.Debug;
}
// get platform
const platformNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.Platform);
let platform = '';
if (platformNodes.length > 0) {
for (let i = 0; i < platformNodes.length; i++) {
const condition = platformNodes[i].getAttribute(constants.Condition);
if (condition?.trim() === constants.EmptyPlatformCondition.trim()) {
platform = platformNodes[i].childNodes[0].nodeValue ?? '';
break;
}
}
} else {
platform = constants.AnyCPU;
}
// get output path
let outputPath;
const outputPathNodes = this.projFileXmlDoc!.documentElement.getElementsByTagName(constants.OutputPath);
if (outputPathNodes.length > 0) {
// go through all the OutputPath nodes and use the last one in the .sqlproj that the condition matches
for (let i = 0; i < outputPathNodes.length; i++) {
// check if parent has a condition
const parent = outputPathNodes[i].parentNode as Element;
const condition = parent?.getAttribute(constants.Condition);
// only handle the default conditions format that are there when creating a sqlproj in VS or ADS
if (condition?.toLowerCase().trim() === constants.ConfigurationPlatformCondition(this.configuration.toString(), platform).toLowerCase()) {
outputPath = outputPathNodes[i].childNodes[0].nodeValue;
} else if (!condition) {
outputPath = outputPathNodes[i].childNodes[0].nodeValue;
}
}
}
if (outputPath) {
this._outputPath = path.join(utils.getPlatformSafeFileEntryPath(this.projectFolderPath), utils.getPlatformSafeFileEntryPath(outputPath));
} else {
// If output path isn't specified in .sqlproj, set it to the default output path .\bin\Debug\
this._outputPath = path.join(utils.getPlatformSafeFileEntryPath(this.projectFolderPath), utils.getPlatformSafeFileEntryPath(constants.defaultOutputPath(this.configuration.toString())));
}
}
/**
@@ -539,6 +619,8 @@ export class Project implements ISqlProject {
this._postDeployScripts = [];
this._noneDeployScripts = [];
this.projFileXmlDoc = undefined;
this._outputPath = '';
this._configuration = Configuration.Debug;
}
/**