Octopus deployments with TeamCity for multiple forks of the same git repository

Paul has good guidance to get you going here.

My requirement was to have deployments for various forks of Git repositories enabled via Octopus. Octopus will interrogate the TC nuget feed for available packages, so how does one get it to differentiate between packages of different forks of the same git repo?

The problem is that the packages have the same name, so Octopus could correctly be configured to pull in the package for deployment, but it could be a package generated by the wrong fork. So, one has to somehow get the package named uniquely per fork. Right, so how?

Puzzle piece 1: The name of a nuget package is specified by the ID in it’s nuspec file. Here’s a link to the nuspec reference.

Puzzle piece 2: Octopus makes use of Octopack to generate slightly modified nuget packages for deployment. OctoPack consumes an OctoPack.targets msbuild file to integrate with the build process.

The octopack.targets contains these properties:

<!–
Configuration properties – you can override these from the command line
–>
<PropertyGroup>
  <OctopusProjectRoot Condition=”‘$(OctopusProjectRoot)’ == ””>$(MSBuildProjectDirectory.TrimEnd(”))</OctopusProjectRoot>
  <OctopusPackageConfiguration Condition=”‘$(OctopusPackageConfiguration)’ == ””>Release</OctopusPackageConfiguration>
  <OctopusNuSpecFileName Condition=”‘$(OctopusNuSpecFileName)’ == ””>$(MSBuildProjectName.Replace(‘.csproj’, ”).Replace(‘.vbproj’, ”)).nuspec</OctopusNuSpecFileName>
  <OctopusTemporaryDirectory Condition=”‘$(OctopusTemporaryDirectory)’ == ””>$(OutputPath.TrimEnd(”))NuGet-temp</OctopusTemporaryDirectory>
  <OctopusWebConfigFile Condition=”‘$(OctopusWebConfigFile)’ == ””>$(OctopusProjectRoot)Web.config</OctopusWebConfigFile>
  <OctopusOutputDirectory Condition=”‘$(OctopusOutputDirectory)’ == ””>$(OutputPath)</OctopusOutputDirectory>
  <OctopusPublishPackageToFileShare Condition=”‘$(OctopusPublishPackageToFileShare)’ == ””></OctopusPublishPackageToFileShare>
  <OctopusPublishPackageToHttp Condition=”‘$(OctopusPublishPackageToHttp)’ == ””></OctopusPublishPackageToHttp>
  <OctopusPublishApiKey Condition=”‘$(OctopusPublishApiKey)’ == ””></OctopusPublishApiKey>
</PropertyGroup>

Note the OctopusNuSpecFileName property. We can use it to specify the name of the nuspec file for a project.

Puzzle piece 3: Get TeamCity to pass the correct parameter to octopack for the relevant build

 

Solution:

I configured separate CI and Packaging projects in TeamCity.

image

The Packaging project has an snapshot dependency on the CI build.

image

The Packaging project has the following Artifact Paths (in General Settings):

image

This simply tells TeamCity to copy any .nupkg files to a Packages folder in the build artifacts.

Build Steps:

image

 

Cleanup

The first build step deletes any previous .nukpg files in case some are hanging around with the following command line:

del /S /F *.nupkg

 

Package

The actual packaging MSBuild steps follow the guidance provided by Paul, with the only extra bit of information provided being the OctopusNuSpecFileName parameter as a a command line parameter:

OctopusNuSpecFileName=MyFork.nuspec

The parameter as specified above will result in a MyFork.nupkg package being generated, and because of the artifact paths defined, it will be copied to the Packages folder in the artfacts produced by the project.

 

Octopus Configuration

The last step is to configure the various deployment projects in Octopus. All that needs to be done is to consume the correct nuget package from TeamCity for your deployments. I have configured a project for each fork’s deployment.