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.
- package/Strings/resources.resjson/en-US/resources.resjson +4 -1
- package/Tests/L0.js +2 -0
- package/Tests/L0.ts +2 -0
- package/Tests/L0MSDeployUtility.ts +0 -2
- package/Tests/L0ParameterParserUtility.d.ts +1 -0
- package/Tests/L0ParameterParserUtility.js +59 -0
- package/Tests/L0ParameterParserUtility.ts +65 -0
- package/Tests/L1JSONVarSubWithComments.js +0 -1
- package/Tests/L1JSONVarSubWithComments.ts +0 -1
- package/deployusingmsdeploy.js +42 -37
- package/module.json +3 -4
- package/msdeployutility.d.ts +3 -0
- package/msdeployutility.js +74 -77
- package/package.json +7 -4
|
@@ -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
|
});
|
|
@@ -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
|
});
|
package/deployusingmsdeploy.js
CHANGED
|
@@ -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
|
|
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
|
|
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 =
|
|
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
|
|
47
|
-
var msDeployCmdArgs =
|
|
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
|
-
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
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
|
}
|
package/msdeployutility.d.ts
CHANGED
|
@@ -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
|
package/msdeployutility.js
CHANGED
|
@@ -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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
217
|
-
|
|
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
|
|
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
|
-
|
|
279
|
+
const minimalSupportedMSDeployVersion = 3;
|
|
280
|
+
const msdeployRegistryPath = "\\SOFTWARE\\Microsoft\\IIS Extensions\\MSDeploy";
|
|
281
|
+
const regKey = new winreg({
|
|
231
282
|
hive: winreg.HKLM,
|
|
232
|
-
key:
|
|
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
|
-
|
|
240
|
-
|
|
290
|
+
tl.debug(`Found ${subRegKeys.length} subkeys under ${msdeployRegistryPath}`);
|
|
291
|
+
let latestKeyVersion = 0;
|
|
292
|
+
let latestSubKey;
|
|
241
293
|
for (var index in subRegKeys) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
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 <
|
|
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.
|
|
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
|
-
"
|
|
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
|
}
|