Setting up your project and TeamCity/OctoPack for front-end builds

Dzulqarnain Nasir 2016-04-26 05:36:40

Octopus Deploy has a nice NuGet package, called OctoPack, for generating Octopus Deploy-compatible NuGet packages out of .NET projects.

However, OctoPack will only pack files that are included in the CSPROJ file, and in the case of static files, have Build Action set to Content. This is a problem, because this means that all files generated by your task runners, be it Gulp or Grunt, will have to be included in the project and pushed out to source control.

This introduces an unnecessary problem - conflicts in generated code. So, if developer A was working on a SCSS file which was referenced in the main stylesheet, and developer B was working on a separate SCSS file, also referenced in the same main stylesheet, why should either one have to resolve a conflict caused in the file generated by the task runner?

This makes no sense. It's like building your .NET project, and pushing the generated DLL files to source control, and then having to resolve conflicts within the DLL files generated by the build. Why would you do that?

So, in order for you to never have to resolve another conflict in generated files again, here's my guide on how to set up your project so they play nice with TeamCity and OctoPack.

Create a NUSPEC file for your project, and include the folders that are not currently included in the project.

What this does is it informs OctoPack about the files that you want to include in the deployment package. Here's an example.

<?xml version="1.0"?>
<package >
<metadata>
<id>MyProject.Web</id>
<version>$version$</version>
<authors>Geta AS</authors>
<owners>Geta AS</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>MyProject.Web deployment package</description>
<copyright>Copyright 2016</copyright>
</metadata>
<files>
<file src="public\**\*.*" target="public" />
</files>
</package>

As you can probably already tell, this will cause OctoPack to only include files stored in the specified folder in the generated deployment package. That's no good.

On to the next step.

Update the project CSPROJ file to include all other files.

<?xml version="1.0" encoding="utf-8"?>
...
<PropertyGroup>
<OctoPackEnforceAddingFiles>True</OctoPackEnforceAddingFiles>
</PropertyGroup>
...

This tells OctoPack to include all the files it would normally include in addition to the files specified in the NUSPEC file.

Once we have all this set up, we can commit the files, and push them to source control.

Update TeamCity settings

I'm assuming you have all the necessary priviliges to make changes to the build settings for your project. I'm also assuming you have the TeamCity Node plugin installed.

Set up NPM

Now head over to the Build Configuration Settings, and under Build Steps, add a new build step. Select Runner Type as Node.js NPM, and give it a descriptive name. Enter install as the value for npm commands, along with any other NPM tasks you'd like to perform during the build.

save image

Set up Gulp

This may or may not be relevant to you, depending on how you're building your front-end code. I know some people who use NPM scripts instead of external task runners such as Gulp and Grunt. In which case, you can include your build scripts in the previous step. Otherwise, read on.

Add another build step, like you did in the previous step, except this time, instead of selecting Node.js NPM, select Gulp as the Runner type. Then fill in the name of the tasks you want to run during the build in the Gulp Tasks field.

save image

Both build steps should be ordered so that they are executed before the MS project build. This is because the packaging process is done during the MS build step, so if you don't do it then, your files will not be included in the deployment package.

Save your settings

This goes without saying.

Profit

That's it! If you've done everything right, your front-end files will be compiled and deployed on TeamCity on your next build.