This task wouldn’t require much efforts but:
- Service Fabric doesn’t support packaging its “package” (which is not a real package but just a directory) into .sfpkg out-of-the-box. Only suggests to use ZipFile.CreateFromDirectory.
- MSBuildTasks doesn’t support .NET Core so we can’t use its Zip task. So we have to write our own instead.
- .NET Core doesn’t support
CodeTaskFactory
. Soon it will (see the same issue, in the bottom) but for now we can use RoslynCodeTaskFactory
Here’s the full project, I called it package.props
and imported from all my sfproj:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\RoslynCodeTaskFactory.2.0.7\build\RoslynCodeTaskFactory.props" />
<UsingTask TaskName="Zip"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(RoslynCodeTaskFactory)"
Condition="'$(RoslynCodeTaskFactory)' != ''">
<ParameterGroup>
<SourceDirectoryName ParameterType="System.String" Required="true" />
<DestinationArchiveFileName ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.IO.Compression.FileSystem" />
<Using Namespace="System.IO.Compression" />
<Code Type="Fragment" Language="cs">
<![CDATA[
try
{
if (File.Exists(DestinationArchiveFileName))
{
Log.LogMessage("File {0} already exists, deleting.", DestinationArchiveFileName);
File.Delete(DestinationArchiveFileName);
}
string directoryName = Path.GetDirectoryName(DestinationArchiveFileName);
if (!Directory.Exists(directoryName))
{
Log.LogMessage("Directory {0} doesn't exist, creating..", directoryName);
Directory.CreateDirectory(directoryName);
}
Log.LogMessage("Zipping directory {0} to {1}", SourceDirectoryName, DestinationArchiveFileName);
ZipFile.CreateFromDirectory(SourceDirectoryName, DestinationArchiveFileName);
return true;
}
catch (Exception ex)
{
Log.LogErrorFromException(ex);
return false;
}
]]>
</Code>
</Task>
</UsingTask>
<Target Name="Package" DependsOnTargets="$(PackageDependsOn)" AfterTargets="Build" Returns="@(_AllPackageFiles)" />
<Target Name="ZipPackage" AfterTargets="Package">
<PropertyGroup>
<PackageSource>pkg\$(Configuration)</PackageSource>
<PackageDestination>sfpkg\$(MSBuildProjectName).sfpkg</PackageDestination>
</PropertyGroup>
<Zip SourceDirectoryName="$(PackageSource)" DestinationArchiveFileName="$(PackageDestination)" />
</Target>
</Project>
It will zip folder pkg\Release
to sfpkg\.sfpkg
.
Now call the Package target using PowerShell:
param
(
[Parameter(Mandatory=$true)]
[ValidateSet('Debug', 'Release')]
[string]$Configuration
)
$projects = Get-ChildItem *.sfproj -Recurse
foreach ($project in $projects)
{
Write-Host "Packaging project $project and configuration $Configuration"
& msbuild "$project" /t:Package /p:Platform=x64 /p:Configuration=$Configuration /m
}
That’s it. Now you can take the resulting sfpkg and deploy it directly to your Service Fabric cluster.
Hi Alex, but maybe you can demystify how application type version from the manifest interoperate (or doesn’t) with the typeVersion of Microsoft.ServiceFabric/clusters/applications? It seems to be possible to package application with certain applicationTypeVersion X and deploy using ARM template with typeVersion Y.