azure-pipelines-tasks-webdeployment-common 4.230.2 → 4.230.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,5 +29,8 @@
29
29
  "loc.messages.VariableSubstitutionInitiated": "Initiated variable substitution in config file : %s",
30
30
  "loc.messages.ConfigFileUpdated": "Config file : %s updated.",
31
31
  "loc.messages.SkippedUpdatingFile": "Skipped Updating file: %s",
32
- "loc.messages.PwshNotAvailable": "##WARNING##:PowerShell Core (pwsh.exe) is not available on agent machine. Falling back to using Windows PowerShell (powershell.exe). This can cause reduced performance. Please install the newer version of PowerShell for improved performance."
32
+ "loc.messages.PwshNotAvailable": "##WARNING##:PowerShell Core (pwsh.exe) is not available on agent machine. Falling back to using Windows PowerShell (powershell.exe). This can cause reduced performance. Please install the newer version of PowerShell for improved performance.",
33
+ "loc.messages.UnabletofindthelocationofMSDeployfromregistryonmachineError": "Unable to find the location of MSDeploy from registry. Error: %s",
34
+ "loc.messages.MissingMSDeployInstallPathRegistryKey": "Missing MSDeploy InstallPath registry key.",
35
+ "loc.messages.UnsupportedinstalledversionfoundforMSDeployversionshouldbeatleast3orabove": "Unsupported installed version: %s found for MSDeploy. Version should be at least 3 or above."
33
36
  }
package/Tests/L0.js CHANGED
@@ -9,6 +9,7 @@ const L1JSONVarSubWithComments_1 = require("./L1JSONVarSubWithComments");
9
9
  const L1JsonVarSub_1 = require("./L1JsonVarSub");
10
10
  const L1JsonVarSubV2_1 = require("./L1JsonVarSubV2");
11
11
  const L1ValidateFileEncoding_1 = require("./L1ValidateFileEncoding");
12
+ const L0ParameterParserUtility_1 = require("./L0ParameterParserUtility");
12
13
  describe('Web deployment common tests', () => {
13
14
  describe('GetMSDeployCmdArgs tests', L0MSDeployUtility_1.runGetMSDeployCmdArgsTests);
14
15
  describe('GetWebDeployErrorCode tests', L0MSDeployUtility_1.runGetWebDeployErrorCodeTests);
@@ -20,4 +21,5 @@ describe('Web deployment common tests', () => {
20
21
  describe("L1JsonVarSub tests", L1JsonVarSub_1.runL1JsonVarSubTests);
21
22
  describe("L1JsonVarSubV2 tests", L1JsonVarSubV2_1.runL1JsonVarSubV2Tests);
22
23
  describe("L1ValidateFileEncoding tests", L1ValidateFileEncoding_1.runL1ValidateFileEncodingTests);
24
+ describe("ParameterParserUtility tests", L0ParameterParserUtility_1.runParameterParserUtilityTests);
23
25
  });
package/Tests/L0.ts CHANGED
@@ -7,6 +7,7 @@ import { runL1JSONVarSubWithCommentsTests } from "./L1JSONVarSubWithComments";
7
7
  import { runL1JsonVarSubTests } from "./L1JsonVarSub";
8
8
  import { runL1JsonVarSubV2Tests } from "./L1JsonVarSubV2";
9
9
  import { runL1ValidateFileEncodingTests } from "./L1ValidateFileEncoding";
10
+ import { runParameterParserUtilityTests } from "./L0ParameterParserUtility";
10
11
 
11
12
  describe('Web deployment common tests', () => {
12
13
  describe('GetMSDeployCmdArgs tests', runGetMSDeployCmdArgsTests);
@@ -19,4 +20,5 @@ describe('Web deployment common tests', () => {
19
20
  describe("L1JsonVarSub tests", runL1JsonVarSubTests);
20
21
  describe("L1JsonVarSubV2 tests", runL1JsonVarSubV2Tests);
21
22
  describe("L1ValidateFileEncoding tests", runL1ValidateFileEncodingTests);
23
+ describe("ParameterParserUtility tests", runParameterParserUtilityTests);
22
24
  });
@@ -1,8 +1,6 @@
1
1
  import assert = require("assert");
2
2
  import { getMSDeployCmdArgs, getWebDeployErrorCode } from "../msdeployutility";
3
3
 
4
-
5
-
6
4
  export function runGetMSDeployCmdArgsTests() {
7
5
 
8
6
  it('Should produce default valid args', () => {
@@ -0,0 +1 @@
1
+ export declare function runParameterParserUtilityTests(): void;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runParameterParserUtilityTests = void 0;
4
+ const assert = require("assert");
5
+ const ParameterParserUtility_1 = require("../ParameterParserUtility");
6
+ function runParameterParserUtilityTests() {
7
+ it("Should parse parameters", () => {
8
+ const paramString = "-port 8080 -Release.ReleaseName Release-1173";
9
+ const expectedJSON = {
10
+ "port": {
11
+ value: "8080"
12
+ },
13
+ "Release.ReleaseName": {
14
+ value: "Release-1173"
15
+ }
16
+ };
17
+ const result = ParameterParserUtility_1.parse(paramString);
18
+ assert.deepStrictEqual(result, expectedJSON);
19
+ });
20
+ it("Should parse parameters with empty values", () => {
21
+ const paramString = "-port 8080 -ErrorCode -ErrorMessage -Release.ReleaseName Release-1173";
22
+ const expectedJSON = {
23
+ "port": {
24
+ value: "8080"
25
+ },
26
+ "ErrorCode": {
27
+ value: ""
28
+ },
29
+ "ErrorMessage": {
30
+ value: ""
31
+ },
32
+ "Release.ReleaseName": {
33
+ value: "Release-1173"
34
+ }
35
+ };
36
+ const result = ParameterParserUtility_1.parse(paramString);
37
+ assert.deepStrictEqual(result, expectedJSON);
38
+ });
39
+ it("Should parse parameters with extra spaces", () => {
40
+ const paramString = "-port 8080 -ErrorCode -ErrorMessage -Release.ReleaseName Release-1173";
41
+ const expectedJSON = {
42
+ "port": {
43
+ value: "8080"
44
+ },
45
+ "ErrorCode": {
46
+ value: ""
47
+ },
48
+ "ErrorMessage": {
49
+ value: ""
50
+ },
51
+ "Release.ReleaseName": {
52
+ value: "Release-1173"
53
+ }
54
+ };
55
+ const result = ParameterParserUtility_1.parse(paramString);
56
+ assert.deepStrictEqual(result, expectedJSON);
57
+ });
58
+ }
59
+ exports.runParameterParserUtilityTests = runParameterParserUtilityTests;
@@ -0,0 +1,65 @@
1
+ import assert = require('assert');
2
+ import { parse } from '../ParameterParserUtility';
3
+
4
+ export function runParameterParserUtilityTests(): void {
5
+
6
+ it("Should parse parameters", () => {
7
+ const paramString = "-port 8080 -Release.ReleaseName Release-1173";
8
+ const expectedJSON = {
9
+ "port": {
10
+ value: "8080"
11
+ },
12
+ "Release.ReleaseName": {
13
+ value: "Release-1173"
14
+ }
15
+ };
16
+
17
+ const result = parse(paramString);
18
+
19
+ assert.deepStrictEqual(result, expectedJSON);
20
+ });
21
+
22
+ it("Should parse parameters with empty values", () => {
23
+ const paramString = "-port 8080 -ErrorCode -ErrorMessage -Release.ReleaseName Release-1173";
24
+ const expectedJSON = {
25
+ "port": {
26
+ value: "8080"
27
+ },
28
+ "ErrorCode": {
29
+ value: ""
30
+ },
31
+ "ErrorMessage": {
32
+ value: ""
33
+ },
34
+ "Release.ReleaseName": {
35
+ value: "Release-1173"
36
+ }
37
+ };
38
+
39
+ const result = parse(paramString);
40
+
41
+ assert.deepStrictEqual(result, expectedJSON);
42
+ });
43
+
44
+ it("Should parse parameters with extra spaces", () => {
45
+ const paramString = "-port 8080 -ErrorCode -ErrorMessage -Release.ReleaseName Release-1173";
46
+ const expectedJSON = {
47
+ "port": {
48
+ value: "8080"
49
+ },
50
+ "ErrorCode": {
51
+ value: ""
52
+ },
53
+ "ErrorMessage": {
54
+ value: ""
55
+ },
56
+ "Release.ReleaseName": {
57
+ value: "Release-1173"
58
+ }
59
+ };
60
+
61
+ const result = parse(paramString);
62
+
63
+ assert.deepStrictEqual(result, expectedJSON);
64
+ });
65
+ }
@@ -28,7 +28,6 @@ function runL1JSONVarSubWithCommentsTests() {
28
28
  it("Should throw exception for invalid JSON with comments", (done) => {
29
29
  const fileContent = fs.readFileSync(path.join(__dirname, 'L1JSONVarSub', 'InvalidJSONWithComments.json'), 'utf-8');
30
30
  const jsonContent = jsonvariablesubstitutionutility_1.stripJsonComments(fileContent);
31
- console.log(jsonContent);
32
31
  assert.throws(() => JSON.parse(jsonContent), "Parse is expected to throw an error");
33
32
  done();
34
33
  });
@@ -33,7 +33,6 @@ export function runL1JSONVarSubWithCommentsTests(): void {
33
33
  it("Should throw exception for invalid JSON with comments", (done: Mocha.Done) => {
34
34
  const fileContent = fs.readFileSync(path.join(__dirname, 'L1JSONVarSub', 'InvalidJSONWithComments.json'), 'utf-8');
35
35
  const jsonContent = stripJsonComments(fileContent);
36
- console.log(jsonContent);
37
36
  assert.throws(() => JSON.parse(jsonContent), "Parse is expected to throw an error");
38
37
  done();
39
38
  });
@@ -13,10 +13,8 @@ exports.executeWebDeploy = exports.DeployUsingMSDeploy = void 0;
13
13
  const tl = require("azure-pipelines-task-lib/task");
14
14
  const fs = require("fs");
15
15
  const path = require("path");
16
- const Q = require("q");
16
+ const utility_1 = require("./utility");
17
17
  const msdeployutility_1 = require("./msdeployutility");
18
- var msDeployUtility = require('./msdeployutility.js');
19
- var utility = require('./utility.js');
20
18
  const DEFAULT_RETRY_COUNT = 3;
21
19
  /**
22
20
  * Executes Web Deploy command
@@ -34,17 +32,17 @@ const DEFAULT_RETRY_COUNT = 3;
34
32
  */
35
33
  function DeployUsingMSDeploy(webDeployPkg, webAppName, publishingProfile, removeAdditionalFilesFlag, excludeFilesFromAppDataFlag, takeAppOfflineFlag, virtualApplication, setParametersFile, additionalArguments, isFolderBasedDeployment, useWebDeploy, authType) {
36
34
  return __awaiter(this, void 0, void 0, function* () {
37
- var msDeployPath = yield msDeployUtility.getMSDeployFullPath();
35
+ var msDeployPath = yield msdeployutility_1.getMSDeployFullPath();
38
36
  var msDeployDirectory = msDeployPath.slice(0, msDeployPath.lastIndexOf('\\') + 1);
39
37
  var pathVar = process.env.PATH;
40
38
  process.env.PATH = msDeployDirectory + ";" + process.env.PATH;
41
- setParametersFile = utility.copySetParamFileIfItExists(setParametersFile);
39
+ setParametersFile = utility_1.copySetParamFileIfItExists(setParametersFile);
42
40
  var setParametersFileName = null;
43
41
  if (setParametersFile != null) {
44
42
  setParametersFileName = setParametersFile.slice(setParametersFile.lastIndexOf('\\') + 1, setParametersFile.length);
45
43
  }
46
- var isParamFilePresentInPackage = isFolderBasedDeployment ? false : yield utility.isMSDeployPackage(webDeployPkg);
47
- var msDeployCmdArgs = msDeployUtility.getMSDeployCmdArgs(webDeployPkg, webAppName, publishingProfile, removeAdditionalFilesFlag, excludeFilesFromAppDataFlag, takeAppOfflineFlag, virtualApplication, setParametersFileName, additionalArguments, isParamFilePresentInPackage, isFolderBasedDeployment, useWebDeploy, authType);
44
+ var isParamFilePresentInPackage = isFolderBasedDeployment ? false : yield utility_1.isMSDeployPackage(webDeployPkg);
45
+ var msDeployCmdArgs = msdeployutility_1.getMSDeployCmdArgs(webDeployPkg, webAppName, publishingProfile, removeAdditionalFilesFlag, excludeFilesFromAppDataFlag, takeAppOfflineFlag, virtualApplication, setParametersFileName, additionalArguments, isParamFilePresentInPackage, isFolderBasedDeployment, useWebDeploy, authType);
48
46
  var retryCountParam = tl.getVariable("appservice.msdeployretrycount");
49
47
  var retryCount = (retryCountParam && !(isNaN(Number(retryCountParam)))) ? Number(retryCountParam) : DEFAULT_RETRY_COUNT;
50
48
  try {
@@ -69,7 +67,7 @@ function DeployUsingMSDeploy(webDeployPkg, webAppName, publishingProfile, remove
69
67
  catch (error) {
70
68
  tl.error(tl.loc('PackageDeploymentFailed'));
71
69
  tl.debug(JSON.stringify(error));
72
- msDeployUtility.redirectMSDeployErrorToConsole();
70
+ msdeployutility_1.redirectMSDeployErrorToConsole();
73
71
  throw Error(error.message);
74
72
  }
75
73
  finally {
@@ -95,6 +93,7 @@ function executeWebDeploy(webDeployArguments) {
95
93
  };
96
94
  }
97
95
  catch (exception) {
96
+ tl.debug(JSON.stringify(exception));
98
97
  const msDeployErrorFilePath = tl.getVariable('System.DefaultWorkingDirectory') + '\\' + 'error.txt';
99
98
  const errorFileContent = tl.exist(msDeployErrorFilePath) ? fs.readFileSync(msDeployErrorFilePath, 'utf-8') : "";
100
99
  return {
@@ -158,36 +157,42 @@ function argStringToArray(argString) {
158
157
  }
159
158
  function executeMSDeploy(msDeployCmdArgs) {
160
159
  return __awaiter(this, void 0, void 0, function* () {
161
- var deferred = Q.defer();
162
- var msDeployError = null;
163
- var errorFile = path.join(tl.getVariable('System.DefaultWorkingDirectory'), "error.txt");
164
- var fd = fs.openSync(errorFile, "w");
165
- var errObj = fs.createWriteStream("", { fd: fd });
166
- errObj.on('finish', () => __awaiter(this, void 0, void 0, function* () {
167
- if (msDeployError) {
168
- deferred.reject(msDeployError);
160
+ return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
161
+ const errorFile = path.join(tl.getVariable('System.DefaultWorkingDirectory'), msdeployutility_1.ERROR_FILE_NAME);
162
+ const fd = fs.openSync(errorFile, "w");
163
+ const errorStream = fs.createWriteStream("", { fd: fd });
164
+ let msDeployError = null;
165
+ errorStream.on('finish', () => __awaiter(this, void 0, void 0, function* () {
166
+ if (msDeployError) {
167
+ reject(msDeployError);
168
+ }
169
+ }));
170
+ try {
171
+ tl.debug("the argument string is:");
172
+ tl.debug(msDeployCmdArgs);
173
+ tl.debug("converting the argument string into an array of arguments");
174
+ const msDeployCmdArgsArray = argStringToArray(msDeployCmdArgs);
175
+ tl.debug("the array of arguments is:");
176
+ for (let i = 0; i < msDeployCmdArgsArray.length; i++) {
177
+ tl.debug("arg#" + i + ": " + msDeployCmdArgsArray[i]);
178
+ }
179
+ // set shell: true because C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe has folder with spaces
180
+ // see https://github.com/microsoft/azure-pipelines-tasks/issues/17634
181
+ const options = {
182
+ failOnStdErr: true,
183
+ errStream: errorStream,
184
+ windowsVerbatimArguments: true,
185
+ shell: true
186
+ };
187
+ yield tl.exec("msdeploy", msDeployCmdArgsArray, options);
188
+ resolve("Azure App service successfully deployed");
169
189
  }
170
- }));
171
- try {
172
- tl.debug("the argument string is:");
173
- tl.debug(msDeployCmdArgs);
174
- tl.debug("converting the argument string into an array of arguments");
175
- msDeployCmdArgs = argStringToArray(msDeployCmdArgs);
176
- tl.debug("the array of arguments is:");
177
- for (var i = 0; i < msDeployCmdArgs.length; i++) {
178
- tl.debug("arg#" + i + ": " + msDeployCmdArgs[i]);
190
+ catch (error) {
191
+ msDeployError = error;
179
192
  }
180
- // set shell: true because C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe has folder with spaces
181
- // see https://github.com/microsoft/azure-pipelines-tasks/issues/17634
182
- yield tl.exec("msdeploy", msDeployCmdArgs, { failOnStdErr: true, errStream: errObj, windowsVerbatimArguments: true, shell: true });
183
- deferred.resolve("Azure App service successfully deployed");
184
- }
185
- catch (error) {
186
- msDeployError = error;
187
- }
188
- finally {
189
- errObj.end();
190
- }
191
- return deferred.promise;
193
+ finally {
194
+ errorStream.end();
195
+ }
196
+ }));
192
197
  });
193
198
  }
package/module.json CHANGED
@@ -32,8 +32,7 @@
32
32
  "SkippedUpdatingFile" : "Skipped Updating file: %s",
33
33
  "PwshNotAvailable": "##WARNING##:PowerShell Core (pwsh.exe) is not available on agent machine. Falling back to using Windows PowerShell (powershell.exe). This can cause reduced performance. Please install the newer version of PowerShell for improved performance.",
34
34
  "UnabletofindthelocationofMSDeployfromregistryonmachineError": "Unable to find the location of MSDeploy from registry. Error: %s",
35
- "MissingMSDeployVersionRegistryKey": "Missing MSDeploy Version registry key.",
36
- "UnsupportedMSDeployVersion": "MSDeploy %s does not support token base authentication. Please upgrade to MSDeploy 9.0.7225.0 or higher.",
37
- "MissingMSDeployInstallPathRegistryKey": "Missing MSDeploy InstallPath registry key."
38
- }
35
+ "MissingMSDeployInstallPathRegistryKey": "Missing MSDeploy InstallPath registry key.",
36
+ "UnsupportedinstalledversionfoundforMSDeployversionshouldbeatleast3orabove": "Unsupported installed version: %s found for MSDeploy. Version should be at least 3 or above."
37
+ }
39
38
  }
@@ -1,4 +1,5 @@
1
1
  import { Package } from './packageUtility';
2
+ export declare const ERROR_FILE_NAME = "error.txt";
2
3
  /**
3
4
  * Constructs argument for MSDeploy command
4
5
  *
@@ -26,6 +27,8 @@ export declare function shouldUseMSDeployTokenAuth(): boolean;
26
27
  * @returns string
27
28
  */
28
29
  export declare function getMSDeployFullPath(): Promise<string>;
30
+ export declare function getInstalledMSDeployVersion(): Promise<string>;
31
+ export declare function installedMSDeployVersionSupportsTokenAuth(): Promise<boolean | undefined>;
29
32
  /**
30
33
  * 1. Checks if msdeploy during execution redirected any error to
31
34
  * error stream ( saved in error.txt) , display error to console
@@ -9,13 +9,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.getWebDeployErrorCode = exports.redirectMSDeployErrorToConsole = exports.getMSDeployFullPath = exports.shouldUseMSDeployTokenAuth = exports.getWebDeployArgumentsString = exports.getMSDeployCmdArgs = void 0;
12
+ exports.getWebDeployErrorCode = exports.redirectMSDeployErrorToConsole = exports.installedMSDeployVersionSupportsTokenAuth = exports.getInstalledMSDeployVersion = exports.getMSDeployFullPath = exports.shouldUseMSDeployTokenAuth = exports.getWebDeployArgumentsString = exports.getMSDeployCmdArgs = exports.ERROR_FILE_NAME = void 0;
13
13
  const tl = require("azure-pipelines-task-lib/task");
14
14
  const fs = require("fs");
15
15
  const path = require("path");
16
- var winreg = require('winreg');
17
- var parseString = require('xml2js').parseString;
18
- const ERROR_FILE_NAME = "error.txt";
16
+ const winreg = require("winreg");
17
+ const semver = require("semver");
18
+ exports.ERROR_FILE_NAME = "error.txt";
19
19
  /**
20
20
  * Constructs argument for MSDeploy command
21
21
  *
@@ -213,9 +213,8 @@ exports.shouldUseMSDeployTokenAuth = shouldUseMSDeployTokenAuth;
213
213
  function getMSDeployFullPath() {
214
214
  return __awaiter(this, void 0, void 0, function* () {
215
215
  try {
216
- const msDeployInstallPathRegKey = "\\SOFTWARE\\Microsoft\\IIS Extensions\\MSDeploy";
217
- const msDeployLatestPathRegKey = yield getMSDeployLatestRegKey(msDeployInstallPathRegKey);
218
- return (yield getMSDeployInstallPath(msDeployLatestPathRegKey)) + "msdeploy.exe";
216
+ const msDeployFolder = yield getMSDeployInstallPath();
217
+ return path.join(msDeployFolder, "msdeploy.exe");
219
218
  }
220
219
  catch (error) {
221
220
  tl.debug(error);
@@ -225,31 +224,84 @@ function getMSDeployFullPath() {
225
224
  });
226
225
  }
227
226
  exports.getMSDeployFullPath = getMSDeployFullPath;
228
- function getMSDeployLatestRegKey(registryKey) {
227
+ function getMSDeployInstallPath() {
228
+ return __awaiter(this, void 0, void 0, function* () {
229
+ const regKey = yield getMSDeployLatestRegKey();
230
+ return new Promise((resolve, reject) => {
231
+ regKey.get("InstallPath", function (err, item) {
232
+ if (err) {
233
+ reject(tl.loc("MissingMSDeployInstallPathRegistryKey"));
234
+ }
235
+ resolve(item.value);
236
+ });
237
+ });
238
+ });
239
+ }
240
+ function getInstalledMSDeployVersion() {
241
+ return __awaiter(this, void 0, void 0, function* () {
242
+ let regKey;
243
+ try {
244
+ regKey = yield getMSDeployLatestRegKey();
245
+ }
246
+ catch (err) {
247
+ tl.debug("An error occured while loading msdeploy registry values: " + err);
248
+ return undefined;
249
+ }
250
+ return new Promise((resolve, _) => {
251
+ regKey.get("Version", function (err, item) {
252
+ if (err) {
253
+ tl.debug("An error occured while loading msdeploy version from registry: " + err);
254
+ resolve(undefined);
255
+ }
256
+ const version = item.value;
257
+ tl.debug(`Installed MSDeploy Version: ${version}`);
258
+ resolve(version);
259
+ });
260
+ });
261
+ });
262
+ }
263
+ exports.getInstalledMSDeployVersion = getInstalledMSDeployVersion;
264
+ function installedMSDeployVersionSupportsTokenAuth() {
265
+ return __awaiter(this, void 0, void 0, function* () {
266
+ // MSDeploy 9.0.7225 is the first product version to support token auth
267
+ const minimalMSDeployVersion = "9.0.7225";
268
+ const msDeployVersion = yield getInstalledMSDeployVersion();
269
+ if (!msDeployVersion) {
270
+ tl.debug('Could not determine MSDeploy version. Assuming it is not installed.');
271
+ return undefined;
272
+ }
273
+ return semver.gte(semver.coerce(msDeployVersion), semver.coerce(minimalMSDeployVersion));
274
+ });
275
+ }
276
+ exports.installedMSDeployVersionSupportsTokenAuth = installedMSDeployVersionSupportsTokenAuth;
277
+ function getMSDeployLatestRegKey() {
229
278
  return new Promise((resolve, reject) => {
230
- var regKey = new winreg({
279
+ const minimalSupportedMSDeployVersion = 3;
280
+ const msdeployRegistryPath = "\\SOFTWARE\\Microsoft\\IIS Extensions\\MSDeploy";
281
+ const regKey = new winreg({
231
282
  hive: winreg.HKLM,
232
- key: registryKey
283
+ key: msdeployRegistryPath
233
284
  });
234
285
  regKey.keys(function (err, subRegKeys) {
235
286
  if (err) {
236
287
  reject(tl.loc("UnabletofindthelocationofMSDeployfromregistryonmachineError", err));
237
288
  return;
238
289
  }
239
- var latestKeyVersion = 0;
240
- var latestSubKey;
290
+ tl.debug(`Found ${subRegKeys.length} subkeys under ${msdeployRegistryPath}`);
291
+ let latestKeyVersion = 0;
292
+ let latestSubKey;
241
293
  for (var index in subRegKeys) {
242
- var subRegKey = subRegKeys[index].key;
243
- var subKeyVersion = subRegKey.substr(subRegKey.lastIndexOf('\\') + 1, subRegKey.length - 1);
244
- if (!isNaN(subKeyVersion)) {
245
- var subKeyVersionNumber = parseFloat(subKeyVersion);
246
- if (subKeyVersionNumber > latestKeyVersion) {
247
- latestKeyVersion = subKeyVersionNumber;
248
- latestSubKey = subRegKey;
249
- }
294
+ const subRegKey = subRegKeys[index].key;
295
+ tl.debug("Found subkey " + subRegKey);
296
+ const subKeyVersion = subRegKey.substring(subRegKey.lastIndexOf("\\") + 1);
297
+ const subKeyVersionNumber = parseFloat(subKeyVersion);
298
+ if (!isNaN(subKeyVersionNumber) && subKeyVersionNumber > latestKeyVersion) {
299
+ latestKeyVersion = subKeyVersionNumber;
300
+ latestSubKey = subRegKeys[index];
250
301
  }
251
302
  }
252
- if (latestKeyVersion < 3) {
303
+ if (latestKeyVersion < minimalSupportedMSDeployVersion) {
304
+ // previous versions are not compatible either with app services or web deployment tasks
253
305
  reject(tl.loc("UnsupportedinstalledversionfoundforMSDeployversionshouldbeatleast3orabove", latestKeyVersion));
254
306
  return;
255
307
  }
@@ -257,68 +309,13 @@ function getMSDeployLatestRegKey(registryKey) {
257
309
  });
258
310
  });
259
311
  }
260
- function getMSDeployInstallPath(registryKey) {
261
- return new Promise((resolve, reject) => {
262
- var regKey = new winreg({
263
- hive: winreg.HKLM,
264
- key: registryKey
265
- });
266
- regKey.values(function (err, items) {
267
- if (err) {
268
- reject(tl.loc("UnabletofindthelocationofMSDeployfromregistryonmachineError", err));
269
- }
270
- if (shouldUseMSDeployTokenAuth()) {
271
- const versionItem = items.find(item => item.name === "Version");
272
- if (!versionItem) {
273
- reject(tl.loc("MissingMSDeployVersionRegistryKey"));
274
- }
275
- const minimalSupportedVersion = "9.0.7225.0";
276
- const version = versionItem.value;
277
- tl.debug(`Installed MSDeploy Version: ${version}`);
278
- // MSDeploy 9.0.7225.0 is the first version to support token auth
279
- if (compareVersions(version, minimalSupportedVersion) < 0) {
280
- reject(tl.loc("UnsupportedMSDeployVersion", version));
281
- }
282
- }
283
- const installPathItem = items.find(item => item.name === "InstallPath");
284
- if (!installPathItem) {
285
- reject(tl.loc("MissingMSDeployInstallPathRegistryKey"));
286
- }
287
- resolve(installPathItem.value);
288
- });
289
- });
290
- }
291
- function compareVersions(version1, version2) {
292
- if (version1 === version2) {
293
- return 0;
294
- }
295
- const separator = ".";
296
- const parts1 = version1.split(separator).map(Number);
297
- const parts2 = version2.split(separator).map(Number);
298
- const length = Math.min(parts1.length, parts2.length);
299
- for (let i = 0; i < length; i++) {
300
- if (parts1[i] > parts2[i]) {
301
- return 1;
302
- }
303
- if (parts1[i] < parts2[i]) {
304
- return -1;
305
- }
306
- }
307
- if (parts1.length > parts2.length) {
308
- return 1;
309
- }
310
- if (parts1.length < parts2.length) {
311
- return -1;
312
- }
313
- return 0;
314
- }
315
312
  /**
316
313
  * 1. Checks if msdeploy during execution redirected any error to
317
314
  * error stream ( saved in error.txt) , display error to console
318
315
  * 2. Checks if there is file in use error , suggest to try app offline.
319
316
  */
320
317
  function redirectMSDeployErrorToConsole() {
321
- var msDeployErrorFilePath = tl.getVariable('System.DefaultWorkingDirectory') + '\\' + ERROR_FILE_NAME;
318
+ var msDeployErrorFilePath = tl.getVariable('System.DefaultWorkingDirectory') + '\\' + exports.ERROR_FILE_NAME;
322
319
  if (tl.exist(msDeployErrorFilePath)) {
323
320
  var errorFileContent = fs.readFileSync(msDeployErrorFilePath).toString();
324
321
  if (errorFileContent !== "") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "azure-pipelines-tasks-webdeployment-common",
3
- "version": "4.230.2",
3
+ "version": "4.230.4",
4
4
  "description": "Common Lib for MSDeploy Utility",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,22 +17,25 @@
17
17
  },
18
18
  "homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme",
19
19
  "dependencies": {
20
+ "@types/ltx": "3.0.6",
20
21
  "@types/mocha": "^5.2.7",
21
22
  "@types/node": "^10.17.0",
22
23
  "@xmldom/xmldom": "git+https://github.com/xmldom/xmldom.git#0.8.6",
23
- "@types/ltx": "3.0.6",
24
24
  "archiver": "1.2.0",
25
25
  "azure-pipelines-task-lib": "^4.2.0",
26
26
  "decompress-zip": "^0.3.3",
27
27
  "ltx": "2.8.0",
28
28
  "node-stream-zip": "^1.15.0",
29
29
  "q": "1.4.1",
30
+ "semver": "^7.5.4",
30
31
  "winreg": "1.2.2",
31
32
  "xml2js": "0.6.2"
32
33
  },
33
34
  "devDependencies": {
34
- "typescript": "4.0.2",
35
+ "@types/semver": "^7.5.4",
36
+ "@types/winreg": "^1.2.34",
35
37
  "mocha": "^6.2.3",
36
- "nyc": "^15.1.0"
38
+ "nyc": "^15.1.0",
39
+ "typescript": "4.0.2"
37
40
  }
38
41
  }