1
votes

I want Azure Package files to be the output of a successful check-in build. We want to be able to publish these packages to Azure from a drop location.

According to this post, we only need the csdef file in order to create the package file using cspack in the command line:

cspack “c:\<path to the csdeffile>\servicedefinition.csdef” /role:<Name of the role as defined in the csdef file>;<location of the binaries> /sites:<Name of the role>;<name of the site path>;<location of the website files>

But I want to avoid using the command line. I know there is a CSPack task that can be used, but I have been struggling to find more information on it. I can't find any specification online, expect for some information on this Stackoverflow post.

How can I translate the above cspack command into the CSPack build task?

I have come up with the following based on the MSDN spec for cspack.exe but I have had to make a lot of assumptions:

<PropertyGroup>
  <VisualStudioVersion Condition=" '$(VisualStudioVersion)' == '' ">10.0</VisualStudioVersion>
  <CloudExtensionsDir Condition=" '$(CloudExtensionsDir)' == '' ">$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Windows Azure Tools\2.2\</CloudExtensionsDir>
  <Roles></Roles>
</PropertyGroup>
<Import Project="$(CloudExtensionsDir)Microsoft.WindowsAzure.targets" />
<Target Name="CreatePackage" DependsOnTargets="Build">
  <CSPack 
      ServiceDefinitionFile="MyCloudProject\ServiceDefinition.csdef"
      Output="$(OutDir)Publish\$(ProjectName).cspkg"
      PackRoles="MyRoleName"
      SiteMapping="MyRoleName;MySiteName;MySitePath"
      RoleProperties="MyRoleName;$(OutDir)Publish\MyProject.dll"
      CopyOnly="false">
  </CSPack>
</Target>

I get the following build error:

C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Windows Azure Tools\2.2\Microsoft.WindowsAzure.targets (351): No default service configuration "ServiceConfiguration.cscfg" could be found in the project.

To be honest, I don't really know what I am doing. I have been at this for some time, so any guidance would be appreciated.

Copying the cspkg files will be easy enough, but I can't seem to figure out how to perform the packaging.

We are using Visual Studio Online (cloud-based TFS).

EDIT:

We do have cloud projects. This is how we have been publishing (right click -> Publish). This obviously isn't ideal as it doesn't follow a "Build Once" strategy and it adds further complications with a larger team.

@Simon Opelt: Would using the CorePublish target require a change to the build definition? Right now, the build definition uses a specific .build file (in order to perform a NuGet restore), which then runs the Build target for all projects in the solution:

<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OutDir>$(MSBuildThisFileDirectory)bin</OutDir>
    <Configuration>Release</Configuration>
    <ProjectProperties>OutDir=$(OutDir);Configuration=$(Configuration);</ProjectProperties>
  </PropertyGroup>
  <ItemGroup>
    <Solution Include="$(MSBuildThisFileDirectory)*.sln" />
  </ItemGroup>
  <Target Name="RestorePackages">
    <Exec Command="&quot;$(MSBuildThisFileDirectory).nuget\NuGet.exe&quot; restore &quot;%(Solution.Identity)&quot;" />
  </Target>
  <Target Name="Clean">
    <MSBuild Targets="Clean" Projects="@(Solution)" Properties="$(ProjectProperties)" />
  </Target>
  <Target Name="Build" DependsOnTargets="RestorePackages">
    <MSBuild Targets="Build" Projects="@(Solution)" Properties="$(ProjectProperties)" />
  </Target>
  <Target Name="Rebuild" DependsOnTargets="RestorePackages">
    <MSBuild Targets="Rebuild" Projects="@(Solution)" Properties="$(ProjectProperties)" />
  </Target>
</Project>

This also builds and runs our test projects. Would using the cloud project coupled with CorePublish still allow for this?

3
Are you using cloud projects? Is that an option or do you want to stick with web-projects plus csdef/cscfg? Have you looked at using the MSBuild CorePublish target as descibed in blog.ehuna.org/2011/02/how_to_automate_the_creation_o.html ?Simon Opelt
@SimonOpelt: Question edited. Thanks!Dave New

3 Answers

1
votes

Set the following properties in your build (via command line msbuild /p: switches, or property pages, or whatever you like):

PublishDir = [Folder you want the packages published to]

PackageForComputeEmulator = true

Then add a target that turns on Publish after build like so:

  <Target
    Name="BuildPackagesForAzure"
    Condition="'$(DoPackagesInBuild)'=='True'"
    DependsOnTargets="Publish"
    AfterTargets="Build">
      <Message Importance="high" Text="Doing Azure packaging in build." />
  </Target>
1
votes

If your solution contains a "Cloud Project" This project is tied to the Azure SDK. If you edit the project, you can see this imports the Microsoft.WindowsAzure.targets file:

You'll see the reference to this in any .ccproj (cloud service) project

<Import Project="$(CloudExtensionsDir)Microsoft.WindowsAzure.targets" />

This .targets file executes CSPack for you:

Line 3003 in my Azure 2.6 SDK targets file:

 <CSPack
  ServiceDefinitionFile="@(TargetServiceDefinition)"
  Output="@(PublishServicePackage)"
  PackRoles="@(Roles)"
  SiteMapping="@(SiteMapping)"
  RoleProperties="@(RoleProperties)"
  ImportedModules="@(ImportedModules)"
  CopyOnly="false" 
  >
</CSPack>

So, you just need to set things up properly to call this target.

It's already included by default from the presence of the project in your solution. Search your build output log for this:

CorePublish: PackageWebRole

You should see if the CSPack is being called:

[CorePublish] CorePublish: PackageWebRole = True
[18:56:39] :[CorePublish] Publishing starting...
[18:56:39] :[CorePublish] RolePlugins       is ;
[18:56:39] :[CorePublish] Importedmodules is Diagnostics
[18:56:39] :[CorePublish] Publishing to '...'
[18:56:39] :[CorePublish] MakeDir
[18:56:39] :[MakeDir] Creating directory "...".
[18:56:39] :[CorePublish] TargetServiceDefinition is ...\Deploy\.ReleasePackage\ServiceDefinition.csdef
[18:56:39] :[CorePublish] TargetServiceConfiguration is ...\Deploy\.ReleasePackage\ServiceConfiguration.cscfg
[18:56:39] :[CorePublish] Roles is ...
[18:57:18] :[CorePublish] Copying the service configuration file.
[18:57:18] :[CorePublish] Copy
[18:57:18] :[Copy] Copying file from "...\Deploy\.ReleasePackage\ServiceConfiguration.cscfg" to "...\Deploy\.ReleasePackageapp.publish\ServiceConfiguration.Cloud.cscfg".
[18:57:18] :[CorePublish] Publishing process has completed.

(I removed info specific to my build)

The output is specified a bit earlier in the file:

<PublishServicePackage Include="$(PublishDir)$(TrailingSlashChar)$(ProjectName).cspkg" />

So, you shouldn't have to call CSPack manually if you have the SDK. And you have to have the SDK to create a Cloud Project. Just make sure to install the SDK on the build machine too!

0
votes

I could not get the CSPack task working. I ran into countless problems, so I went with executing cspack.exe directly:

<PropertyGroup>
  <PackageCommand>
    "C:\Program Files\Microsoft SDKs\Windows Azure\.NET SDK\v2.3\bin\cspack.exe" $(OutputPath)ServiceDefinition.csdef /role:MyRoleName;$(OutputPath) /sites:MyRoleName;MySiteName;$(OutputPath) /rolePropertiesFile:MyRoleName;$(OutputPath)RoleProperties.txt /out:$(OutputPath)Publish\MyRoleName.cspkg /useCtpPackageFormat
  </PackageCommand>
</PropertyGroup>
<Target Name="CreatePackage" DependsOnTargets="Build" AfterTargets="Build">
  <MakeDir Directories="$(OutputPath)Publish"></MakeDir>
  <Message Text="Using cspack create a package for deployment..."></Message>
  <Exec Command="$(PackageCommand)"></Exec>
</Target>