Introduction
Continuous Integration is a deployment concept that ensures changes to your code base results in an automatic build and deployment to their target environments. This article explains how to automatically deploy K2 Process and K2 SmartObject artefacts using the SourceCode Deployment Framework and the MSBuild Assemblies. The example code can be used to create a custom MSBuild task that can be included in a MSBuild file. CCNet, TFS and FinalBuilder are typically used to automatically build and deploy applications using MSBuild files as deployment directives.
K2 and MSBuild
The K2 Deployment Framework takes advantage of the MSBuild Libraries to build and deploy K2 Projects. This K2 deployment process is transparent to Developers using VS 2005 to compile and deploy K2 processes. The K2 Deployment API is used by VS 2005 under the covers to achieve this. This article will explain how to used this API and automate this build and deployment process.
Implementation Example
This example will create a Deployment Class called LibK2Deploy that will be referenced by a Console Application that calls a static method called Execute to deploy the K2 Processes or K2 SmartObjects.
Let’s Start
Open VS 2005 and create a new Solution. Add a new Class Library project called LibK2Build to the solution. Add a new class to the project called LibK2Deploy. Add References to the following Assemblies
· Microsoft.Build.Engine
· Microsoft.Build.Framework
· SourceCode.EnvironmentSettings.Client
· SourceCode.Framework
· SourceCode.Workflow.Design
Add the following code in your using directives
using SourceCode.EnvironmentSettings.Client;
using SourceCode.Framework.Deployment;
using SourceCode.ProjectSystem;
using SourceCode.Workflow.Design.EnvironmentSettings;
The class will contain a public Execute method and two helper methods GetEnvironmentManager and GetDeploymentPackage. Execute will use the EnvironmentSettingsManager and DeploymentPackage returned from the respective helper methods to build and deploy the K2 Project.
Add the following code into LibK2Deploy your class:
The method below is a standard way to return the Environment Manager.
private static EnvironmentSettingsManager GetEnvironmentManager()
{
EnvironmentSettingsManager environmentManager = new EnvironmentSettingsManager(false, false);
// This is weird but the only way I could get it to work!
environmentManager.ConnectToServer(GetConnectionString());
environmentManager.InitializeSettingsManager();
environmentManager.ConnectToServer(GetConnectionString());
if (_environment != null)
environmentManager.ChangeEnvironment(_environment);
environmentManager.InitializeSettingsManager();
environmentManager.GetEnvironmentFields(environmentManager.CurrentEnvironment);
return environmentManager
}
The method below is particularly useful because you can intercept and change the Environment Field Values based on your configuration. You also specify your Deployment Label and Description in this method. These are the same Label and Description you would specify in VS 2005 when you deploy your K2 Artefacts. Note there are separate sections of code that deals with K2 Workflow and K2 SmartObject objects.
private static DeploymentPackage GetDeploymentPackage(Project project, EnvironmentSettingsManager environmentManager)
{
DeploymentPackage package;
package = project.CreateDeploymentPackage();
// Populate Environment Fields
foreach (EnvironmentInstance env in environmentManager.CurrentTemplate.Environments)
{
DeploymentEnvironment depEnv = package.AddEnvironment(env.EnvironmentName);
foreach (EnvironmentField field in env.EnvironmentFields)
{
depEnv.Properties[field.FieldName] = field.Value;
}
}
package.SelectedEnvironment = environmentManager.CurrentEnvironment.EnvironmentName;
package.DeploymentLabelName = DateTime.Now.ToString();
package.DeploymentLabelDescription = string.Empty;
package.TestOnly = false;
// Get the Default SmartObject Server in the Environment
// The prefix "$Field=" is when the value of the SmartObject server is registered in the environment fields collection.
// this will do a lookup in the environment with the display name of the field, and use the value.
// If you set the value directly, no lookups will be performed.
EnvironmentField smartObjectServerField =
environmentManager.CurrentEnvironment.GetDefaultField(typeof(SmartObjectField));
package.SmartObjectConnectionString = "$Field=" + smartObjectServerField.DisplayName;
// Get the Default Workflow Management Server in the Environment
EnvironmentField workflowServerField =
environmentManager.CurrentEnvironment.GetDefaultField(typeof(WorkflowManagementServerField));
package.WorkflowManagementConnectionString = "$Field=" + workflowServerField.DisplayName;
return package;
}
This method creates a K2 Connection String that is used by the methods above.
private static string GetConnectionString()
{
return string.Format("Integrated=True;IsPrimaryLogin=True;Authenticate=True;EncryptedPassword=False;Host={0};Port={1}", _server, _port);
}
The helper methods use the private variables below that are populated with the K2HostServer, Port and Environment Name. Add these to your class:
static string _server;
static int _port;
static string _environment;
Add the Execute method to the code. This public method’s signature accepts the K2 Host Server name (eg. “BLACKPEARL”), the Environment Name (typically “Development”, “Production”), the ProjectPath the location of the “.k2proj” that needs deploying and OuputPath the location of the MSBuild files that are consumed by MSBuild during deployment.
public static bool Execute(string K2HostServer, string EnvironmentName, string ProjectPath, string OutputPath)
{
_environment = EnvironmentName;
_port = 5555;
_server = K2HostServer;