How to deploy to Azure Resource Group using VSTS release management - asp.net

I am new to Visual Studio Team Services Release Management. My goal is to automate a deployment of an ASP.NET MVC application to the Azure App Service.
Trying different approaches, I created a Service Endpoint that is certificate based and one that uses a service principal (SPN). My build definition already builds a web deploy package, and the release definition is linked against that and can use this artifact.
Success 1:
A deployment of the app using the Azure Web App Deployment Task already succeeded - almost.
Shortcoming 1: I do not understand how I can specify the correct Resource Group using this task. This uses the certificate based endpoint, and for this task I cannot use the other (SPN) endpoint.
Success 2:
Using the Azure Resource Group Deployment task, I was able to use a JSON ARM template to create a new resource group with a web app in it. This way I can specify the resource group, addressing Shortcoming 1
Shortcoming 2: But now I don't understand how I can actually deploy the binaries of the build definition that has been linked against my release definition. The web application that gets created by the resource group deployment is empty, and a subsequent Web App Deployment Task seemingly cannot target this newly created web app, since it is probably not ARM based.
I get the feeling that I am missing something obvious here - any help is appreciated.
Update 1
Thanks to #bmoore-msft, I got a deployment working using the child resource extension example he linked to. Essentially, the corresponding snippet of my ARM template now looks like this:
"resources": [
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('fullEnvName')]",
"location": "[parameters('siteLocation')]",
"properties": {
"name": "[variables('fullEnvName')]"
},
"resources": [
{
"apiVersion": "2014-06-01",
"name": "MSDeploy",
"type": "Extensions",
"dependsOn": [
"[concat('Microsoft.Web/Sites/', variables('fullEnvName'))]"
],
"properties": {
"packageUri": "https://dl.dropboxusercontent.com/u/<myId>/<WebDeploymentPackage>.zip",
"dbType": "None",
"connectionString": "",
"mode": "Complete"
}
}
]
}
]
But the problem is that this places a static link into my template - as you can see, I used Dropbox as temporary solution. But of course I don't want to upload my web deployment package to Dropbox, neither manually nor automatically. I want to link to the artifact created by my build definition, which unfortunately is dynamic and I can't find any information on how to construct this link. For example, build 1 is located at the following path
https://<tenant>.visualstudio.com/DefaultCollection/_apis/resources/Containers/800850?itemPath=<PathToWebDeploymentPackage>.zip
while build 2 is available here
https://<tenant>.visualstudio.com/DefaultCollection/_apis/resources/Containers/801968?itemPath=<PathToWebDeploymentPackage>.zip
So there is a number changing inside the link which means the link I refer to in my template must be dynamic which means I need to understand where to get that number from, which I don't.
Maybe there is another way of referencing artifact uploads?

Take a look at this sample:
https://github.com/Azure/azure-quickstart-templates/blob/75d0588fbd2702288bd35ed24cb00e43dcf980c2/wordpress-mysql-replication/website.json
The website in that template resource has a child resource extension named "MSDeploy". This will deploy a package to the web site during deployment. So in your task that does the deployment you can create the web app, and deploy the package all in the one deployment task in RM.
You will need to use user or SPN authn for anything using ARM (no certs).
Update: Staging the Package
Ok, usually what I do here is "stage" my artifacts in Azure Storage (secured with a sasToken). The uri you provide in the template must be accessible to AzureRM. You VSTS build output is likely secured, so even though you could access it interactively, AzureRM cannot.
Essentially what you need is a task in RM (or build) that will 1) copy the artifacts to Azure (securely) and then 2) tell the next task where those artifacts are... Here's one option:
https://azure.microsoft.com/en-us/documentation/articles/vs-azure-tools-resource-groups-ci-in-vsts/
This doc is using VSTS build, but RM works the same way. The other part that's different is the doc is using a PS script used by Visual Studio in the Azure Resource Group projects. There's nothing special about that script (it will work anywhere just like any other PS script) but that's the example. It doesn't use the Azure Resource Group Deployment Task because that task cannot do the staging of the artifacts.
Essentially what you need to do is:
parameterize that URI property (see example & repo below)
copy the webdeploy package to Azure (PowerShell in this case)
deploy the template and pass in the uri of the package
e.g.
"packageUri": "[concat(parameters('artifactsLocation'), webdeploy.zip, parameters('sasToken')]"
That doc shows you how VS does it, and you should be able to adapt that for your scenario. If you go this route, you would use the Azure PowerShell task and no longer need the Azure Resource Group Deployment Task.
Another way to do this is with the Azure File Copy task, but currently that task does not output the URI or sasToken, so you couldn't pass it in to the deployment task (there's a PR in the queue to make that work).
Another option if you don't have access to Visual Studio is this repo:
https://github.com/Azure/azure-xplat-arm-tooling/tree/master/PowerShell
It has the same PS script that VS uses, and the templates show an example of the parameterized URL (for a dsc.zip file in this example) but would work the same way for msdeploy.
You've actually hit on one of the more sophisticated scenarios and at the moment not doc'd real well, but it's pretty cool when it works. LMK if you need more help here.

Related

Trying to create a "template" Amplify project

Most of our client projects have a very similar starting point:
Pristine AWS account used only for a single environment for this application
GraphQL API and a basic model to start with
A REST API with an OAuth handler endpoint and a generic webhook listener endpoint, each with a corresponding Lambda function (with code for each)
I've created this basic amplify app and I want to create a repo with this general structure as a starting point for future projects. The idea being that I'd copy the contents of the repo when starting a project and build from there.
So I've copied the entire amplify directory over to a new location, removing everything that is in the amplify section of the .gitignore file, and I have a folder structure like this:
My steps to start a new project are:
Create a new directory
Copy the template repo files into this directory
run amplify init
Once I do that, it creates two additional files:
amplify/.config/project-config.json
amplify/team-provider-info.json
Then, I try to do amplify push -- but I get No changes detected.
I'm not even sure if what I'm doing is possible -- I was wondering if anyone else has tried this?

Azure pipeline with multiple environments

My dotnetcore app has one appsettings.json per environment (appsettings.json and appsettings.Development.json for example) and I would like to take advantage of this on my pipeline.
I see 2 options for the pipeline:
Build Artifact for Dev -> Deploy on Dev -> Build Artifact for Prod -> Deploy on Prod
or
Build Artifact -> Deploy on Dev -> Deploy on Prod
For the first option, I could set the environment as a parameter for the build.
For the second option, how could I build the App only once, and set the environment according to the current deployment step? Taking advantage of the multiple appsettings.json I have.
And finally, are these approaches aligned with the best practices? If not, what would be the best practices for pipelines with multiple environments?
Generally we can generate a single artifact, then deploy the artifact to different environments and perform the different transformations at any environment within it's own stage release phase. That means we can change and override the settings which defined in the appsettings.json in each release environment.
Please refer to File transforms and variable substitution reference on how to do the transformation with .json files.
Besides, we can try to install the Replace Tokens extension, then use Replace Tokens task to load and change the settings defined in the appsettings.json file in each release environment/stage.
You can also transform the settings or use File Creator to create a new appsettings.jsonfile to overwrite the existing one.
Below blogs for your reference:
Replace appsetting tokens in config files with Build & Release
Management in VSTS (TFS)
Transform configurations in a .NET Core 2.2 Web API using Azure
DevOps
Using custom appsettings.json with ASP.NET Core integration
tests
You could go with Azure AppConfiguration and add it as an extra source for the configuration. This way your building/releasing process stays extremely simple.
See this documentation: https://learn.microsoft.com/en-us/azure/azure-app-configuration/enable-dynamic-configuration-dotnet-core
It's very powerful: you can select only part of the configuration (through filters), you can have feature flags, and you can have secrets (from linked key vaults).

Changing the Odata service of WebIDE Archive (FIORI APP)

For reasons of security I cannot use the cloud connector in conjunction with the on premise system which we have. Never the less I am very comfortable using WebIDE in order to create the necessary applications. I create the applications in WebIDE using a .edmx file which represents the on premise ODATA service which i plan to use.
After the application is made. I import the archive and then make necessary modifications to the archive in HANA Studio (inside Java EE perspective).
I am doing things according to this guide: https://www.sap.com/developer/tutorials/hcp-webide-switch-live-odata.html
My understanding is that the manifest.json and neo-app.json are both to be modified pointing to the real ODATA service.
In the manifest.json:
According to the guide above, within the neo-app.json, I need to point it to the gateway.
Here is the information of our on premise system.
System Name: sapewp01.xxxxx.com
localURI: /sap/opu/odata/sap/zbw_odata_q3_srv/
Port: 8012 (i assume, the odata service link works on my end)
SAP Gateway (sapgw12)
Another other required information can be provided on request.
How does one change a web ide app to be able link into an on premise ODATA service, WITHOUT disrupting all the work done on webIDE?
In the sap.app part of the manifest.json can't you just specify?
"dataSources": {
"myService": {
"uri": "/sap/opu/odata/sap/zbw_odata_q3_srv/",
"type": "OData",
"settings": {
"odataVersion": "2.0"
}
}
}
At least with my experience working in Eclipse, all I had to do was have the URI to create the model.
oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl, oConfig);
but this was using a legacy app, maybe Web IDE does it a different way?

How can I delete existing files when deploying an ASP.Net 5 Web App to Azure

I've got a web application in ASP.Net 5 with the source in VS Team Services. Using the Team Services build system, I'd like to deploy it directly to Azure for Continuous Deployment.
I've followed the steps here: https://msdn.microsoft.com/Library/vs/alm/Build/azure/deploy-aspnet5
However, when the website is deployed, only the new files are added and existing ones are overridden. Any deleted files are not removed. This means that extra controllers that were removed during refactoring (for example) still hang around.
Is there a way to force the deployment to wipe out any existing deployed website before putting the new one in place?
I've already run into an issue where the site is unable to deploy due to files being locked. I fixed this by wrapping the publish command in commands to start/stop the site:
Stop-AzureWebsite -Name $websiteName
. $publishScript -publishProperties $publishProperties -packOutput $packOutput
Start-AzureWebsite -Name $websiteName
In theory I could instead remove and create the website, but that seems a bit heavy handed...
Another option, using the publish profile:
Add this to your MSBuild parameters:
/p:SkipExtraFilesOnServer=False
Additional parameters here:
Valid Parameters for MSDeploy via MSBuild

Run acceptance/smoke tests after deployment

I have set up continuous deployment from a Visual Studio Online Git repository to an Azure Web App.
What is the best way to run acceptance/smoke tests on the website after a build is triggered and deployment has completed?
I have already tried POST_DEPLOYMENT_ACTION (How to add a custom post deployment script to azure websites?), but this seems to get ignored.
I also had a look at the Kudu PostDeployment hook (https://github.com/projectkudu/kudu/wiki/Post-Deployment-Action-Hooks), which appears overly hacky.
I am deploying a standard ASP.NET 4 MVC site by the way. Any help appreciated.
What is hacky about the PostDeployment hook?
An alternative to that could be to subscribe to the PostDeployment hook from the Kudu/SCM site
POST /api/hooks
{
"url": "http://www.callback.com/callback",
"event": "PostDeployment",
"insecure_ssl": false (set to true to ignore https certificate check, for test purposes only)
}
That would give you a POST like below on the specified URL when deployment is done:
{
"id": "cd5bee7181e74ea38a3522e73253f6ebb8ed72fb",
"status": "success", (could be pending, building, deploying, failed, success)
"author_email": "someone#somewhere.com",
"author": "Some One",
"message": "My fix",
"deployer": "Some One",
"start_time": "2013-06-06T01:24:16.5873293Z",
"end_time": "2013-06-06T01:24:17.63342Z"
}
More info here on kudu github wiki
What I ended up doing was customizing the build process to add a RunScriptTask at the end, which invokes my tests.
You can pass build parameters to the RunScriptTask like so:
"-username user#example.org -password test123 -environment " + DeploymentSettings.GetValue(Of String)("ProviderHostedDeploymentEnvironmentName")
If you edit the build definition from Visual Studio -> Team Explorer -> Builds, there is a tab on the left called Process that breaks down the build steps. If you click Show details at the top, there is an option to download the XAML build process template. You can customize this as you wish and then create a new build process template from that file. (Note that XAML build process template file must be pushed to the remote repository beforehand)

Resources