Publishing ASP.NET Core 1.1 applications to Azure using git deploy
I took an ASP.NET Core 1.0 application and updated its package references to ASP.NET 1.1 today. I also updated to my SDK to the Current (not the LTS - Long Term Support version). Everything worked great building and running locally, but then I made a new Web App in Azure and did a quick git deploy.
Basically:
c:\aspnetcore11app> azure site create "aspnetcore11test" --location "West US" --git
c:\aspnetcore11app> git add .
c:\aspnetcore11app> git commit -m "initial"
c:\aspnetcore11app> git push azure master
Then I watched the logs go by. You can watch them at the command line or from within the Azure Portal under "Log Stream."
The deployment failed when Azure was building the app and got this error:
Build started 11/25/2016 6:51:54 AM. 2016-11-25T06:51:55 1>Project "D:\home\site\repository\aspnet1.1.xproj" on node 1 (Publish target(s)). 2016-11-25T06:51:55 1>D:\home\site\repository\aspnet1.1.xproj(7,3): error MSB4019: The imported project "D:\Program Files (x86)\dotnet\sdk\1.0.0-preview3-004056\Extensions\Microsoft\VisualStudio\v14.0\DotNet\Microsoft.DotNet.Props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk. 2016-11-25T06:51:55 1>Done Building Project "D:\home\site\repository\aspnet1.1.xproj" (Publish target(s)) -- FAILED. 2016-11-25T06:51:55
See where it says "1.0.0-preview3-004056" in there? Looks like Azure Web Apps has some build that isn't the one that I have. Theirs has the new csproj/msbuild stuff and I'm staying a few steps back waiting for things to bake.
Remember that unless you specify the SDK version, .NET Core will use whatever is the latest one on the box.
Well, what do I have locally?
C:\aspnetcore11app>dotnet --version
1.0.0-preview2-1-003177
OK, then that's what I need to use so I'll make a global.json at the root of my project, then move my code into a folder under "src" for example.
{
"projects": [ "src", "test" ],
"sdk": {
"version": "1.0.0-preview2-1-003177"
}
}
Here I'm "pinning" the same SDK version. This will tell Azure (or you, if I gave you the code) to use this SDK version when building.
Now I'll redeploy with a git add, commit, and push. It works.
I think this should be easier, but I'm not sure how it should be easier. Does this mean that everyone should have a global.json with a preferred version? If you have no preferred version should Azure give a smarter error if it has an incompatible newer one?
The learning here for me is that not having a global.json basically says "*.*" to any cloud build servers and you'll get whatever latest SDK they have. It could stop working any day.
Sponsor: Big thanks to Octopus Deploy! Do you deploy the same application multiple times for each of your end customers? The team at Octopus have taken the pain out of multi-tenant deployments. Check out their latest 3.4 release!
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter
There is the latest .net core 1.1 version, then there is the tooling version... and then there is that moment you just upgraded to the latest versions of the framework and tooling but visual studio keeps creating .net core projects with dependencies for 1.0.1 in project.json and 1.0.0-preview2-003131 in global.json.
I even deleted the unwanted sdk versions from C:\programfiles\dotnet\sdk\1.0.0-preview2-003131
But then Visual Studio fails to load sdk.
Well... I guess better productive days are to come. :)
dotnet migrate --sdk [version]could solve the issue of having to change the global.json, project.json, for those projects that still use it, and .cproj.
I am excited for msbuild but there are still a great few things that aren't smooth yet.
I know things are in flux, but I find it hard to imagine .NET versioning/tooling being more confusing than they are right now.
I started a project months ago - knowing full well that I was teetering on the cutting edge of something new.
I know the tooling and SDK are at different stages, but is there somewhere that explains the version numbering?
Last week I dl'd the (LTS) 1.0.1 SDK. The file that dl's is 1.0.0-preview2...
Hold up, 1.0.0? preview?
The difference in version number between what I'm using now, and what I was using is ...3121 -> ...3131.
I see refs in VS to DNX - but I thought DNX was being deprecated in favour of dotnet. I used DNVM to find refs to DNX but read that it too was being deprecated, but dotnet doesn't show me what dnvm did.
I'm considering a win reinstall to start fresh...
Maybe it's just me that's finding it difficult to keep up.
Can you at least tell us that things will get better Scott-wan?
Or point me to somewhere that explains everything?
Thanks
The only way to fix this as far as I've found so far is to use the advanced tools in the Azure portal to fully clean out the site-folder and then do the deploy.
After this is done once, it will work. Seems like old versions of certain SDK files are left behind after a deploy.
It also works you do a publish from VS and enable "Remove additional files".
It's possible to avoid this, but Azure really doesn't make things easy for you if you go that way. My preferred approach is to perform the build on a build server (usually one I control, although at least if you use a VSTS (formerly Visual Studio Online) hosted build Microsoft documents exactly what's installed and it's fairly easy to find out when changes are coming), and then to deploy the artifacts produced by that build to the Web App. This way you can be confident that the thing you're pushing to production is actually the same thing you tested - you deploy exactly the same compiled artifacts in each case, rather than running a whole new build each time. But rather astonishingly, the VSTS Integration in Azure Web Apps doesn't work that way - as with going via a git repo, it assumes that you want App Service to do your build. There's no way to tell an App Service to deploy the output of a VSTS build.
And if you set up a working Release pipeline in VSTS, there's no good way to see what's currently deployed. With old-school Cloud Services there was a thing called a deployment label, which was just a bit of text you could set to whatever you want, and which you could see in the portal when looking at a slot, and I usually put the build number and branch name in there so it was easy to see what was deployed. With App Services there's no such thing, and if you're using deployment slots, there's no straightforward way to see what's in which slot, so if you swap slots manually it's very easy to forget whether you've done it... I generally now automate slot swapping as part of my release process, but the problem with that is you never get to see any of the warnings the Azure Portal would show you if you've done something potentially dangerous (e.g., mismatched config settings).
What's particularly aggravating is that it *is* easy to see what's deployed if you let App Service build from source for you (because the Deployments blade will show you what's currently deployed) but that doesn't work if you drive deployments from VSTS or Team City or whatever. (There are workarounds of course - you can have your deployment process supply an Application Setting in the web app that states the build number, for example, but it seems a bit of a hack, particularly since there's that Deployments page there for precisely this purpose but which doesn't work in this scenario.)
The deploy-from-source model is great for static sites, because there's nothing to compile in that case, and it's beautifully simple. But for anything else it seems too much like a toy, and it's frustrating that there's not great support for more solid approaches.
Comments are closed.
My preference, then, is that a global.json should ideally always be specified. If that's too big a change of behaviour, then producing a warning that the resulting code might not be portable without it should hopefully help anyone getting that error and wondering what's wrong.
Obviously the errors caused by this will be different depending on the expected SDK version and the version actually used, so I don't think there will be an easy way of determining at compile time that it boils down to the wrong SDK version. To that end, it might be worth explicitly stating in the dotnet tooling which SDK version is being inferred (and why, i.e. using latest as no global.json found) during the build step.
For those unfamiliar with the command line, I'd also like to see more helpful prompts during failures as well, even if it's just telling them how to run the build with verbosity set to high for more information.