Skip to content

Commit 8d742fa

Browse files
authored
Deployment script feature changes port to Release Branch (#3725)
1 parent 7cebca7 commit 8d742fa

File tree

8 files changed

+378
-59
lines changed

8 files changed

+378
-59
lines changed

Tasks/AzureRmWebAppDeployment/Strings/resources.resjson/en-US/resources.resjson

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
"loc.input.help.AdditionalArguments": "Additional Web Deploy arguments following the syntax -key:value .<br />These will be applied when deploying the Azure App Service. Example: -disableLink:AppPoolExtension -disableLink:ContentExtension.<br />For more examples of Web Deploy operation settings, refer to [this](https://go.microsoft.com/fwlink/?linkid=838471).",
3737
"loc.input.label.RenameFilesFlag": "Rename locked files",
3838
"loc.input.help.RenameFilesFlag": "Select the option to enable msdeploy flag MSDEPLOY_RENAME_FILES_FLAG in Azure App Service application settings. The option if set enables msdeploy to rename locked files that are locked during app deployment",
39+
"loc.input.label.ScriptType": "Deployment script type",
40+
"loc.input.help.ScriptType": "Customize the deployment by providing a script that will run on the Azure App service. For example restore packages for Node, PHP, Python applications. [Learn more](https://go.microsoft.com/fwlink/?linkid=843471).",
41+
"loc.input.label.InlineScript": "Inline Script",
42+
"loc.input.label.ScriptPath": "Deployment script path",
3943
"loc.input.label.XmlTransformation": "XML transformation",
4044
"loc.input.help.XmlTransformation": "The config transfoms will be run for `*.Release.config` and `*.<EnvironmentName>.config` on the `*.config file`.<br/> Config transforms will be run prior to the Variable Substitution.<br/>XML transformations are supported only for Windows platform.",
4145
"loc.input.label.XmlVariableSubstitution": "XML variable substitution",
@@ -57,8 +61,8 @@
5761
"loc.messages.Unabletoretrievewebappsettings": "Unable to retrieve App Service application settings. [Status Code: '%s', Error Message: '%s']",
5862
"loc.messages.Unabletoupdatewebappsettings": "Unable to update App service application settings. [Status Code: '%s', Error Message: '%s']",
5963
"loc.messages.CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved": "Cannot update deployment status : Unique Deployment ID cannot be retrieved",
60-
"loc.messages.WebappsuccessfullypublishedatUrl0": "App Service successfully deployed at url %s",
61-
"loc.messages.Failedtodeploywebsite": "Failed to deploy website.",
64+
"loc.messages.PackageDeploymentSuccess": "Successfully deployed web package to App Service.",
65+
"loc.messages.PackageDeploymentFailed": "Failed to deploy web package to App Service.",
6266
"loc.messages.Runningcommand": "Running command: %s",
6367
"loc.messages.Deployingwebapplicationatvirtualpathandphysicalpath": "Deploying web package : %s at virtual path (physical path) : %s (%s)",
6468
"loc.messages.Successfullydeployedpackageusingkuduserviceat": "Successfully deployed package %s using kudu service at %s",
@@ -96,5 +100,19 @@
96100
"loc.messages.VirtualApplicationDoesNotExist": "Virtual application doesn't exists : %s",
97101
"loc.messages.JSONParseError": "Unable to parse JSON file: %s. Error: %s",
98102
"loc.messages.JSONvariablesubstitutionappliedsuccessfully": "JSON variable substitution applied successfully.",
99-
"loc.messages.XMLvariablesubstitutionappliedsuccessfully": "XML variable substitution applied successfully."
103+
"loc.messages.XMLvariablesubstitutionappliedsuccessfully": "XML variable substitution applied successfully.",
104+
"loc.messages.failedtoUploadFileToKudu": "Unable to upload file: %s to Kudu (%s). Status Code: %s (%s)",
105+
"loc.messages.failedtoUploadFileToKuduError": "Unable to upload file: %s to Kudu (%s). Error: %s",
106+
"loc.messages.ExecuteScriptOnKudu": "Executing given script on Kudu: %s",
107+
"loc.messages.FailedToRunScriptOnKuduError": "Unable to run the script on Kudu: %s. Error: %s",
108+
"loc.messages.FailedToRunScriptOnKudu": "Unable to run the script on Kudu: %s. Status Code: %s (%s)",
109+
"loc.messages.SciptExecutionOnKuduSuccess": "Successfully executed script on Kudu.",
110+
"loc.messages.SciptExecutionOnKuduFailed": "Executed script returned '%s' as return code. Error: %s",
111+
"loc.messages.FailedtoDeleteFileFromKudu": "Unable to delete file: %s from Kudu (%s). Status Code: %s (%s)",
112+
"loc.messages.FailedtoDeleteFileFromKuduError": "Unable to delete file: %s from Kudu (%s). Error: %s",
113+
"loc.messages.ScriptFileNotFound": "Script file '%s' not found.",
114+
"loc.messages.InvalidScriptFile": "Invalid script file '%s' provided. Valid extensions are .bat and .cmd",
115+
"loc.messages.RetryForTimeoutIssue": "Script execution failed with timeout issue. Retrying once again.",
116+
"loc.messages.stdoutFromScript": "Standard output from script: ",
117+
"loc.messages.stderrFromScript": "Standard error from script: "
100118
}

Tasks/AzureRmWebAppDeployment/Tests/L0.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,4 +467,16 @@ describe('AzureRmWebAppDeployment Suite', function() {
467467
assert(tr.stdout.search('## mkdir Successful ##') >= 0, 'should have created dir including dest folder');
468468
done();
469469
});
470+
471+
it('Validate webdepoyment-common.utility.runPostDeploymentScript()', (done:MochaDone) => {
472+
let tp = path.join(__dirname, "..", "node_modules", "webdeployment-common", "Tests", 'L0RunPostDeploymentScript.js');
473+
let tr : ttm.MockTestRunner = new ttm.MockTestRunner(tp);
474+
tr.run();
475+
476+
assert(tr.succeeded, 'task should have succeeded');
477+
assert(tr.stdout.search('PUT:https://mytestappKuduUrl/api/vfs//site/wwwroot/kuduPostDeploymentScript.cmd') >= 0, 'should have uploaded file');
478+
assert(tr.stdout.search('POST:https://mytestappKuduUrl/api/command') >= 0, 'should have executed script');
479+
assert(tr.stdout.search('DELETED:https://mytestappKuduUrl/api/vfs//site/wwwroot/kuduPostDeploymentScript.cmd') >= 0, 'should have removed file');
480+
done();
481+
});
470482
});

Tasks/AzureRmWebAppDeployment/azurermwebappdeployment.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ async function run() {
3232
var xmlTransformation: boolean = tl.getBoolInput('XmlTransformation', false);
3333
var JSONFiles = tl.getDelimitedInput('JSONFiles', '\n', false);
3434
var xmlVariableSubstitution: boolean = tl.getBoolInput('XmlVariableSubstitution', false);
35+
var scriptType: string = tl.getInput('ScriptType', false);
36+
var inlineScript: string = tl.getInput('InlineScript', false);
37+
var scriptPath: string = tl.getPathInput('ScriptPath', false);
3538
var endPointAuthCreds = tl.getEndpointAuthorization(connectedServiceName, true);
36-
3739
var isDeploymentSuccess: boolean = true;
3840
var tempPackagePath = null;
3941

@@ -126,6 +128,9 @@ async function run() {
126128
await DeployUsingKuduDeploy(webDeployPkg, azureWebAppDetails, publishingProfile, virtualApplication, isFolderBasedDeployment, takeAppOfflineFlag);
127129

128130
}
131+
if(scriptType) {
132+
await kuduUtility.runPostDeploymentScript(publishingProfile, scriptType, inlineScript, scriptPath, takeAppOfflineFlag);
133+
}
129134
await updateScmType(endPoint, webAppName, resourceGroupName, deployToSlotFlag, slotName);
130135

131136
} catch (error) {
@@ -187,10 +192,10 @@ async function DeployUsingKuduDeploy(webDeployPkg, azureWebAppDetails, publishin
187192
}
188193
}
189194
await kuduUtility.deployWebAppPackage(webAppZipFile, publishingProfile, virtualPath, physicalPath, takeAppOfflineFlag);
190-
console.log(tl.loc('WebappsuccessfullypublishedatUrl0', publishingProfile.destinationAppUrl));
195+
console.log(tl.loc('PackageDeploymentSuccess'));
191196
}
192197
catch(error) {
193-
tl.error(tl.loc('Failedtodeploywebsite'));
198+
tl.error(tl.loc('PackageDeploymentFailed'));
194199
throw Error(error);
195200
}
196201
finally {

Tasks/AzureRmWebAppDeployment/task.json

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
"author": "Microsoft Corporation",
1616
"version": {
1717
"Major": 3,
18-
"Minor": 0,
19-
"Patch": 9
18+
"Minor": 1,
19+
"Patch": 0
2020
},
2121
"preview": "true",
2222
"releaseNotes": "What's new in Version 3.0: <br/>&nbsp;&nbsp;Supports File Transformations (XDT) <br/>&nbsp;&nbsp;Supports Variable Substitutions(XML, JSON) <br/>Click [here](https://aka.ms/azurermwebdeployreadme) for more Information.",
@@ -183,6 +183,40 @@
183183
"groupName": "AdditionalDeploymentOptions",
184184
"helpMarkDown": "Select the option to enable msdeploy flag MSDEPLOY_RENAME_FILES_FLAG in Azure App Service application settings. The option if set enables msdeploy to rename locked files that are locked during app deployment"
185185
},
186+
{
187+
"name": "ScriptType",
188+
"type": "pickList",
189+
"label": "Deployment script type",
190+
"defaultValue": "",
191+
"options": {
192+
"": "Select deployment script type",
193+
"Inline Script": "Inline Script",
194+
"File Path": "Script File Path"
195+
},
196+
"groupName": "AdditionalDeploymentOptions",
197+
"helpMarkDown": "Customize the deployment by providing a script that will run on the Azure App service. For example restore packages for Node, PHP, Python applications. [Learn more](https://go.microsoft.com/fwlink/?linkid=843471)."
198+
},
199+
{
200+
"name": "InlineScript",
201+
"type": "multiLine",
202+
"label": "Inline Script",
203+
"defaultValue": ":: You can provide your deployment commands here. One command per line.",
204+
"groupName": "AdditionalDeploymentOptions",
205+
"visibleRule": "ScriptType == Inline Script",
206+
"properties": {
207+
"resizable": "true",
208+
"rows": "10",
209+
"maxLength": "500"
210+
}
211+
},
212+
{
213+
"name": "ScriptPath",
214+
"type": "filePath",
215+
"label": "Deployment script path",
216+
"required": true,
217+
"groupName": "AdditionalDeploymentOptions",
218+
"visibleRule": "ScriptType == File Path"
219+
},
186220
{
187221
"name": "XmlTransformation",
188222
"type": "boolean",
@@ -258,8 +292,8 @@
258292
"Unabletoretrievewebappsettings": "Unable to retrieve App Service application settings. [Status Code: '%s', Error Message: '%s']",
259293
"Unabletoupdatewebappsettings": "Unable to update App service application settings. [Status Code: '%s', Error Message: '%s']",
260294
"CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved": "Cannot update deployment status : Unique Deployment ID cannot be retrieved",
261-
"WebappsuccessfullypublishedatUrl0": "App Service successfully deployed at url %s",
262-
"Failedtodeploywebsite": "Failed to deploy website.",
295+
"PackageDeploymentSuccess": "Successfully deployed web package to App Service.",
296+
"PackageDeploymentFailed": "Failed to deploy web package to App Service.",
263297
"Runningcommand": "Running command: %s",
264298
"Deployingwebapplicationatvirtualpathandphysicalpath": "Deploying web package : %s at virtual path (physical path) : %s (%s)",
265299
"Successfullydeployedpackageusingkuduserviceat": "Successfully deployed package %s using kudu service at %s",
@@ -297,6 +331,20 @@
297331
"VirtualApplicationDoesNotExist": "Virtual application doesn't exists : %s",
298332
"JSONParseError": "Unable to parse JSON file: %s. Error: %s",
299333
"JSONvariablesubstitutionappliedsuccessfully": "JSON variable substitution applied successfully.",
300-
"XMLvariablesubstitutionappliedsuccessfully": "XML variable substitution applied successfully."
334+
"XMLvariablesubstitutionappliedsuccessfully": "XML variable substitution applied successfully.",
335+
"failedtoUploadFileToKudu": "Unable to upload file: %s to Kudu (%s). Status Code: %s (%s)",
336+
"failedtoUploadFileToKuduError": "Unable to upload file: %s to Kudu (%s). Error: %s",
337+
"ExecuteScriptOnKudu": "Executing given script on Kudu: %s",
338+
"FailedToRunScriptOnKuduError": "Unable to run the script on Kudu: %s. Error: %s",
339+
"FailedToRunScriptOnKudu": "Unable to run the script on Kudu: %s. Status Code: %s (%s)",
340+
"SciptExecutionOnKuduSuccess": "Successfully executed script on Kudu.",
341+
"SciptExecutionOnKuduFailed": "Executed script returned '%s' as return code. Error: %s",
342+
"FailedtoDeleteFileFromKudu": "Unable to delete file: %s from Kudu (%s). Status Code: %s (%s)",
343+
"FailedtoDeleteFileFromKuduError": "Unable to delete file: %s from Kudu (%s). Error: %s",
344+
"ScriptFileNotFound": "Script file '%s' not found.",
345+
"InvalidScriptFile": "Invalid script file '%s' provided. Valid extensions are .bat and .cmd",
346+
"RetryForTimeoutIssue": "Script execution failed with timeout issue. Retrying once again.",
347+
"stdoutFromScript": "Standard output from script: ",
348+
"stderrFromScript": "Standard error from script: "
301349
}
302350
}

Tasks/AzureRmWebAppDeployment/task.loc.json

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
"author": "Microsoft Corporation",
1616
"version": {
1717
"Major": 3,
18-
"Minor": 0,
19-
"Patch": 9
18+
"Minor": 1,
19+
"Patch": 0
2020
},
2121
"preview": "true",
2222
"releaseNotes": "What's new in Version 3.0: <br/>&nbsp;&nbsp;Supports File Transformations (XDT) <br/>&nbsp;&nbsp;Supports Variable Substitutions(XML, JSON) <br/>Click [here](https://aka.ms/azurermwebdeployreadme) for more Information.",
@@ -183,6 +183,40 @@
183183
"groupName": "AdditionalDeploymentOptions",
184184
"helpMarkDown": "ms-resource:loc.input.help.RenameFilesFlag"
185185
},
186+
{
187+
"name": "ScriptType",
188+
"type": "pickList",
189+
"label": "ms-resource:loc.input.label.ScriptType",
190+
"defaultValue": "",
191+
"options": {
192+
"": "Select deployment script type",
193+
"Inline Script": "Inline Script",
194+
"File Path": "Script File Path"
195+
},
196+
"groupName": "AdditionalDeploymentOptions",
197+
"helpMarkDown": "ms-resource:loc.input.help.ScriptType"
198+
},
199+
{
200+
"name": "InlineScript",
201+
"type": "multiLine",
202+
"label": "ms-resource:loc.input.label.InlineScript",
203+
"defaultValue": ":: You can provide your deployment commands here. One command per line.",
204+
"groupName": "AdditionalDeploymentOptions",
205+
"visibleRule": "ScriptType == Inline Script",
206+
"properties": {
207+
"resizable": "true",
208+
"rows": "10",
209+
"maxLength": "500"
210+
}
211+
},
212+
{
213+
"name": "ScriptPath",
214+
"type": "filePath",
215+
"label": "ms-resource:loc.input.label.ScriptPath",
216+
"required": true,
217+
"groupName": "AdditionalDeploymentOptions",
218+
"visibleRule": "ScriptType == File Path"
219+
},
186220
{
187221
"name": "XmlTransformation",
188222
"type": "boolean",
@@ -258,8 +292,8 @@
258292
"Unabletoretrievewebappsettings": "ms-resource:loc.messages.Unabletoretrievewebappsettings",
259293
"Unabletoupdatewebappsettings": "ms-resource:loc.messages.Unabletoupdatewebappsettings",
260294
"CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved": "ms-resource:loc.messages.CannotupdatedeploymentstatusuniquedeploymentIdCannotBeRetrieved",
261-
"WebappsuccessfullypublishedatUrl0": "ms-resource:loc.messages.WebappsuccessfullypublishedatUrl0",
262-
"Failedtodeploywebsite": "ms-resource:loc.messages.Failedtodeploywebsite",
295+
"PackageDeploymentSuccess": "ms-resource:loc.messages.PackageDeploymentSuccess",
296+
"PackageDeploymentFailed": "ms-resource:loc.messages.PackageDeploymentFailed",
263297
"Runningcommand": "ms-resource:loc.messages.Runningcommand",
264298
"Deployingwebapplicationatvirtualpathandphysicalpath": "ms-resource:loc.messages.Deployingwebapplicationatvirtualpathandphysicalpath",
265299
"Successfullydeployedpackageusingkuduserviceat": "ms-resource:loc.messages.Successfullydeployedpackageusingkuduserviceat",
@@ -297,6 +331,20 @@
297331
"VirtualApplicationDoesNotExist": "ms-resource:loc.messages.VirtualApplicationDoesNotExist",
298332
"JSONParseError": "ms-resource:loc.messages.JSONParseError",
299333
"JSONvariablesubstitutionappliedsuccessfully": "ms-resource:loc.messages.JSONvariablesubstitutionappliedsuccessfully",
300-
"XMLvariablesubstitutionappliedsuccessfully": "ms-resource:loc.messages.XMLvariablesubstitutionappliedsuccessfully"
334+
"XMLvariablesubstitutionappliedsuccessfully": "ms-resource:loc.messages.XMLvariablesubstitutionappliedsuccessfully",
335+
"failedtoUploadFileToKudu": "ms-resource:loc.messages.failedtoUploadFileToKudu",
336+
"failedtoUploadFileToKuduError": "ms-resource:loc.messages.failedtoUploadFileToKuduError",
337+
"ExecuteScriptOnKudu": "ms-resource:loc.messages.ExecuteScriptOnKudu",
338+
"FailedToRunScriptOnKuduError": "ms-resource:loc.messages.FailedToRunScriptOnKuduError",
339+
"FailedToRunScriptOnKudu": "ms-resource:loc.messages.FailedToRunScriptOnKudu",
340+
"SciptExecutionOnKuduSuccess": "ms-resource:loc.messages.SciptExecutionOnKuduSuccess",
341+
"SciptExecutionOnKuduFailed": "ms-resource:loc.messages.SciptExecutionOnKuduFailed",
342+
"FailedtoDeleteFileFromKudu": "ms-resource:loc.messages.FailedtoDeleteFileFromKudu",
343+
"FailedtoDeleteFileFromKuduError": "ms-resource:loc.messages.FailedtoDeleteFileFromKuduError",
344+
"ScriptFileNotFound": "ms-resource:loc.messages.ScriptFileNotFound",
345+
"InvalidScriptFile": "ms-resource:loc.messages.InvalidScriptFile",
346+
"RetryForTimeoutIssue": "ms-resource:loc.messages.RetryForTimeoutIssue",
347+
"stdoutFromScript": "ms-resource:loc.messages.stdoutFromScript",
348+
"stderrFromScript": "ms-resource:loc.messages.stderrFromScript"
301349
}
302350
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
var mockery = require('mockery');
2+
mockery.enable({
3+
useCleanCache: true,
4+
warnOnReplace: false,
5+
warnOnUnregistered: false
6+
});
7+
8+
mockery.registerMock('vso-node-api/HttpClient', {
9+
HttpCallbackClient: function () {
10+
return {
11+
send: function (verb, url) {
12+
if(verb == 'POST' && url == 'https://mytestappKuduUrl/api/command') {
13+
console.log('POST:https://mytestappKuduUrl/api/command');
14+
return;
15+
}
16+
throw Error('Unknown verb or URL - SEND');
17+
},
18+
sendStream: function (verb, url) {
19+
if(verb == 'PUT' && url == 'https://mytestappKuduUrl/api/vfs//site/wwwroot/kuduPostDeploymentScript.cmd') {
20+
console.log('PUT:https://mytestappKuduUrl/api/vfs//site/wwwroot/kuduPostDeploymentScript.cmd');
21+
return;
22+
}
23+
throw Error('Unknown verb or URL - sendStream');
24+
},
25+
get: function(verb, url) {
26+
if(verb == 'DELETE' && url == 'https://mytestappKuduUrl/api/vfs//site/wwwroot/kuduPostDeploymentScript.cmd') {
27+
console.log("DELETED:https://mytestappKuduUrl/api/vfs//site/wwwroot/kuduPostDeploymentScript.cmd");
28+
return;
29+
}
30+
throw Error('Unknown verb or URL - GET');
31+
}
32+
};
33+
}
34+
});
35+
36+
mockery.registerMock('vsts-task-lib/task', {
37+
exist: function() {
38+
return true;
39+
},
40+
getVariable: function() {
41+
return 'workigDirectory';
42+
},
43+
debug: function(message) {
44+
console.log('##debug : ' + message);
45+
},
46+
loc: function(message, argument) {
47+
console.log('##LOC: ' + message + ' : ' + argument);
48+
}
49+
50+
});
51+
mockery.registerMock('q', {
52+
'defer': function() {
53+
return {
54+
promise: 'promise'
55+
}
56+
}
57+
});
58+
59+
var fs = require('fs');
60+
mockery.registerMock('fs', {
61+
'createReadStream': function() {
62+
return '';
63+
},
64+
statSync: fs.statSync,
65+
writeFileSync: fs.writeFileSync
66+
})
67+
var mockPublishProfile = {
68+
profileName: 'mytestapp - Web Deploy',
69+
publishMethod: 'MSDeploy',
70+
publishUrl: 'mytestappKuduUrl',
71+
msdeploySite: 'mytestapp',
72+
userName: '$mytestapp',
73+
userPWD: 'mytestappPwd',
74+
destinationAppUrl: 'mytestappUrl',
75+
SQLServerDBConnectionString: '',
76+
mySQLDBConnectionString: '',
77+
hostingProviderForumLink: '',
78+
controlPanelLink: '',
79+
webSystem: 'WebSites'
80+
};
81+
82+
var kuduUtility = require('webdeployment-common/kuduutility.js');
83+
kuduUtility.runPostDeploymentScript(mockPublishProfile, "File Path", null, 'myscript.cmd', false);

0 commit comments

Comments
 (0)