slow-cheetah icon indicating copy to clipboard operation
slow-cheetah copied to clipboard

Azure worker role App.config transform fails with TFS online build

Open vkam opened this issue 11 years ago • 21 comments

This is a continuation from thread "Support for Azure projects". I was asked to enter this as a new issue, so here it is.

The project is an Azure worker role with a simple app.config transform. I am using the TFS online's build definition to build and deploy. When I queue the build, I get the error: "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Windows Azure Tools\1.8\Microsoft.WindowsAzure.targets (2713): Could not copy the file "C:\a\bin\obj\test\SlowCheetah\app.config" because it was not found" . The "test" is my app.config transform file (app.test.config).

The one thing I notice is the folder structure where slow cheetach is looking at. The bin and obj folders are siblings and there is no \bin\obj\ folder under my project hierarchy. But slow cheetach is looking at "C:..\bin\obj..." on TFS build server?

vkam avatar Dec 31 '12 21:12 vkam

I'm not sure what is happening here. I just tried this out on TFSPreview and it did work for me. Since we started the other thread I have created a NuGet package for SlowCheetah. This can be used to more easily execute the transforms for build servers. I've written up a blog post on how to use it at http://sedodream.com/2012/12/24/SlowCheetahBuildServerSupportUpdated.aspx.

If that doesn't help solve the issue can you give me a specific set of steps that I can follow to reproduce your issue?

sayedihashimi avatar Jan 04 '13 05:01 sayedihashimi

Hi Sayed, I created a brand new Azure worker role project and tried to follow the steps per your article above. The step3 is where it gets interesting.

  1. First of all, I am not using the default template. I use "AzureContinuousDeployemnt.11.xaml".
  2. Why am I using that template? : When I create a cloud service on the Azure portal, there is a place where you can link your TFS publishing. When we do that, it creates a buld definition file on our TFS with the above template as the default build process template and this is infact the only template available to build and deploy from TFS online to Azure cloud service. We edit this template to our needs.
  3. The Azure build template looks different from the regular template. I don't see "Items to Build" parameter (for step3 of your article). So I am not sure where I would do that in the Azure build template?
  4. I am using TFS online production version, not using TFS preview.

vkam avatar Jan 04 '13 19:01 vkam

Sorry, didn't mean to close the issue, clicked the wrong button.

vkam avatar Jan 04 '13 19:01 vkam

For the Azure build template on TFS online, these are the parameter values I provided. There are 6 sections and this is what I fill out: Section 1.Required: Solution to Build - the location of .sln solution file that's checked in TFS online Section 2.Basic: Configuration To Build - "Any CPU|MyTestTransform" (this is from app.MyTestTransofrm.config file name, (or web.confg transform file name, in the case of web apps) ) Section 4: Publishing: Deployment Settings name - hosted cloud service name (myappname) Section 5: Alternale Cloud Service Environment - Production, Alternate Cloud Service Name - myappname, Alternate Service Configuration - name of the custom service config name (In this project, I don't have any)

vkam avatar Jan 04 '13 19:01 vkam

I guess I am getting closer, but not there yet. So with the nuget package solution as you described, I am happy to report that the TFS online build doesn't fail anymore as it used to. So build and deploy is working fine. But the app.config is still not transofrmed. It still shows the value from the base app.config although as you can see from my comment above that I am indicating that it should run "MyTestTransform" config file. BTW, I am using the slowcheetah release version that's available in visual studio 2012 nuget gallery. Is there any other intermediate version of slowcheetah that I should be using that might have fixed the app.config issue?

vkam avatar Jan 04 '13 20:01 vkam

When I did Install-Package SlowCheetah –pre, I am using slowCheetah prerelease version thta's available in Visual studio (2.5.2.4-beta (Prerelease))

vkam avatar Jan 04 '13 20:01 vkam

The nuget package you said is supposed to put the targets under packages folder and it also supposed to edit the .csproj to refer to this target location. I looked at WorkerRole1.csproj, the slowcheetah still seems to be looking LocalAppData. It's transforming locally but not on the build server. Am I missing something ? <PropertyGroup> <SlowCheetahTargets Condition=" '$(SlowCheetahTargets)'=='' ">$(LOCALAPPDATA)\Microsoft\MSBuild\SlowCheetah\v1\SlowCheetah.Transforms.targets</SlowCheetahTargets> </PropertyGroup>

vkam avatar Jan 04 '13 21:01 vkam

I also don't have a folder called 'packages' under my solution. It created a folder called .nuget and I see NuGet.targers file

vkam avatar Jan 04 '13 21:01 vkam

I forgot to update the NuGet package. I have just updated the NuGet package. Its now version 2.5.2.5.

Regarding the SlowCheetah extension itself for this you will have to use the link I provided previously http://sedodream.com/2012/12/24/SlowCheetahBuildServerSupportUpdated.aspx.

I am not familiar with that build template but should be able to take a look this weekend.

sayedihashimi avatar Jan 04 '13 21:01 sayedihashimi

@vkam I looked at the Azure Build template and I'm not sure if the NuGet package approach will work here. From what I can tell that build template only lets you build a single .SLN file. Because of that, the NuGet package restore + build won't be able to invoke the transforms. You need to be able to invoke two builds. See my blog for more details at http://sedodream.com/2012/12/24/SlowCheetahBuildServerSupportUpdated.aspx.

If SlowCheetah were to support this scenario it would require some feature work. Our feature backlog is being prioriized at http://slowcheetah.uservoice.com/. If you are passionate about this please create an entry there. If it gets enough votes we can start looking at supporting this. I will go ahead and close this item.

sayedihashimi avatar Jan 05 '13 21:01 sayedihashimi

I will open a new feature request as this is a must feature for me. But I still don't understand why people are claiming that it's working. It is now apparent that Slowcheetah doesn't support Azure worker role transforms with TFS online. Are people using a different build template? As far as I can see, the only build template that you can use with TFS online is Azure build template. You also mentioned that it's working with TFS preview, how did that work? On a second note, I appreciate the work you have been doing but from a product maintenability perspective, It's a bit unnerving to use something that's not part of the standard tooling on our product. Is there a reason why Microsoft is not making app transofrms part of standard tooling similar to web transforms? Are there any altenatives to make worker role app config transforms and builds on TFS online?

vkam avatar Jan 07 '13 20:01 vkam

It's working for the following scenarios:

  1. Publishing to azure from VS
  2. Creating an azure package and later publishing that
  3. Publishing from the command line
  4. Publishing from build servers where you can build more than 1 item at once

The reason why it doesn't work with the Azure template is that it only allows a single .sln file to be selected during build. The NuGet package restore doesn't not occur soon enough for the build to leverage the downloaded .targets.

In your case, an alternative is to checking in the packages folder. If you checkin in the NuGet packages then you won't have to worry about them being restored.

If you would like SlowCheetah to be integrated into VS the best thing to do is to vote it up at http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/3400655-add-slow-cheetah-out-of-the-box. If it gets enough votes the Visual Studio team will have to consider it.

sayedihashimi avatar Jan 08 '13 16:01 sayedihashimi

FYI I think I have found a work around until we can find another solution.

Follow these steps for any project which already has the SlowCheetah nuget package installed.

  1. Create a file azure-publish.proj in your repository near your .sln/.*proj file
  2. Place the contents of https://gist.github.com/4491191 in that file
  3. Update path to packageRestore.proj - this should be in the worker role folder
  4. Update the path to your .sln file
  5. Check in all the files
  6. Update your TFS build definition to build azure-publish.proj instead of your solution file
  7. Kick off a build

FYI reminder the transforms for worker role are currently limited to app.config. I still have one active issue #44 for this. For now just try with app.config.

sayedihashimi avatar Jan 09 '13 07:01 sayedihashimi

Hi Sayed,

I get an error when trying to get it to work. The error:

Exception Message: Please specify a Visual Studio Solution (.sln) to build. (type BuildFromSolutionException)
Exception Stack Trace:    at System.Activities.Statements.Throw.Execute(CodeActivityContext context)
   at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
   at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)

When I set the logging level of the build definition to diagnostic I see the following entry:

Find the Azure Project in the Solution
Initial Property Values
SolutionPath = C:\a\src\Source\[Solution Folder]\azure-publish.proj
Final Property Values
Result = 
SolutionPath = C:\a\src\Source\[Solution Folder]\azure-publish.proj
Final Property Values
Condition = True

Followed by an exception:

Set CompilationStatus to Failed
Initial Property Values
BuildNumber = 
CompilationStatus = Failed
DropLocation = 
KeepForever = False
LabelName = 
LogLocation = 
Quality = 
SourceGetVersion = 
Status = None
TestStatus = Unknown
Final Property Values
BuildNumber = 
CompilationStatus = Failed
DropLocation = 
KeepForever = False
LabelName = 
LogLocation = 
Quality = 
SourceGetVersion = 
Status = None
TestStatus = Unknown

We are using the AzureContinuousDeployemnt.11.xaml template with TFS preview.

Steps to reproduce:

  1. Install the nuget package to the WorkerRole project
  2. Verify the packageRestore.proj is added to the WorkerRole folder
  3. Place the azure-publish.proj in the same folder as the solution file
  4. Add https://gist.github.com/4491191 as content to azure-publish.proj
  5. Update solution path to: $(MSBuildThisFileDirectory)mysolution.sln
  6. Update packageRestore path to: $(MSBuildThisFileDirectory)[WorkerRole Folder]\packageRestore.proj

It looks like the exceptions is raised becauase azure-publish.proj is set as the solution to build, but how come you didn't get the error?

orhanmaden avatar Jan 09 '13 10:01 orhanmaden

This still doesn't work.

orhanmaden avatar Jan 17 '13 08:01 orhanmaden

I have just tried the work around too and confirm it doesn't work I get the same error message as orhanmaden

apwestgarth avatar Jan 18 '13 18:01 apwestgarth

There is no solution at this point. I am going to be meeting with the MSBuild and NuGet team next week to see if anything can be done.

For now the best thing for this template is the workaround that I mentioned https://github.com/sayedihashimi/slow-cheetah/issues/60#issuecomment-12033875.

sayedihashimi avatar Jan 18 '13 19:01 sayedihashimi

Sorry didn't realize you meant the workaround didn't work. I am out of town for the weekend but will look at this on Monday.

sayedihashimi avatar Jan 19 '13 02:01 sayedihashimi

Ive reopened until I can find a work around.

sayedihashimi avatar Jan 19 '13 02:01 sayedihashimi

I’ve also run into the same problem using Team Foundation Service AzureContinuousDeployment.11.xaml Continual Integration Build definition.

Only workaround I could find was to unfortunately remove SlowCheetah, then edit worker role project file (.csproj) and cloud project (.ccproj)

  1. Modify config files so files are nested in the solution explorer
  <ItemGroup>
    <Content Include="app.config">
      <SubType>Designer</SubType>
    </Content>
    <Content Include="app.Debug.config">
      <DependentUpon>app.config</DependentUpon>
    </Content>
    <Content Include="app.Release.config">
      <DependentUpon>app.config</DependentUpon>
    </Content>
    <None Include="packages.config" />
  </ItemGroup>
  1. At the end of the project file add UsingTask and AfterCompile target
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
  <!-- Get worker role transform start -->
  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="AfterCompile" Condition="exists('app.$(Configuration).config')">
    <!-- Generate transformed app config in the intermediate directory -->
    <TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
    <!-- Force build process to use the transformed configuration file from now on. -->
    <ItemGroup>
      <AppConfigWithTargetPath Remove="app.config" />
      <AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
        <TargetPath>$(TargetFileName).config</TargetPath>
      </AppConfigWithTargetPath>
    </ItemGroup>
  </Target>
  <!-- Get worker role transform end -->
</Project>
  1. Edit cloud project (.ccproj) to use transformed file as config simple add CopyWorkerRoleConfigurations target before the closing project node, just after import, Worker is the name of my worker role – so just replace with your project name.
  <Import Project="$(CloudExtensionsDir)Microsoft.WindowsAzure.targets" />
  <!-- Get worker role transform start -->
  <Target Name="CopyWorkerRoleConfigurations" AfterTargets="CopyWorkerRoleFiles">
    <Copy SourceFiles="$(WorkerTargetDir)\Worker.dll.config" DestinationFolder="$(IntermediateOutputPath)Worker" OverwriteReadOnlyFiles="true" />
  </Target>
  <!-- Get worker role transform end -->
</Project>

Hope this helps.

normannicolson avatar Feb 20 '13 22:02 normannicolson

Or use a WebRole as a WorkerRole by overriding the Run method of the WebRole class which inherits from RoleEntryPoint. That way you can still use Web.Config transformations out of the box.

orhanmaden avatar Mar 05 '13 14:03 orhanmaden