In some cases there is need to have multiple projects within a solution that each require being packaged and then published or pushed to your repository of choice for deployment. Typically from a Web Application perspective you could have Web Services, Web Api, and finally the Web Application itself.
What I am about to detail for you is performing these actions with success using TFS 2017 and Octopus Deploy. These same actions can be applied to Visual Studio Team Services (VSTS). Be warned that this technique will not apply to older XAML build definitions.
We are going to assume that you have basic solution with .Net MVC Web Application, MVC WebApi, and Windows Services projects. You can more than this, but for the purposes of this demonstration this is what we have. Something like this:
You will also want to make sure that you have Octopus Deploy extension installed or applied to your account or TFS instance.
Where to Start
Well the most common thing here is that you will need to create is a basic Visual Studio vNext Build Definition. Log into your Project and Navigate to Build & Release and then click New in the right hand corner.
Now we are going to Scroll down and choose a Visual Studio build template. I won’t go into the details of all the different templates are, but for this exercise we will choose Visual Studio because it is a very quick way for you to get started.
Now that we have our basic build definition in place it should look something like this.
Now save what we have so that we can start with the meat of this exercise. The next little preparation that you have to do make sure that you create a Service Endpoint for your Octopus Deploy input. I will be using Built-in Nuget Repository, but can also use and external NuGet repository of your choice. The fields that you will need to fill out are listed at points 3, 4, 5. You need to give the connection a meaningful name that you can remember. You must provide a url to the octopus instance that you intend to publish to and finally you will need to have an API key with the minimum permissions to publish to the Octopus internal NuGet Repository. Rule of thumb here is to create or have a Octopus Service Account that has the appropriate permissions.
How its done
We now have the basics set up. So lets get into the requirements for getting multiple projects to be compiled, packaged, and pushed to Octopus Deploy. Previously you would have to have a lot of pre-work done to your actual project/solution, e.g., adding OctoPack, creating a nuspec file, etc. With the new build system and its extensibility, it makes your projects/solutions much cleaner and much simpler to use especially if you add more projects to your solution that require packaging and publishing later on.
Edit your saved build definition and select Build Solution step. We need to make an adjustment here to ensure that
- We get a separate folder for each project
- We ensure our Output Directory for the solution is pointing to our ArtifactsStagingDirectory
The “a” in this case means Artifact.
We will not worry about the Test Assemblies step right now and we can also leave the Publish Symbols and Copy Files Step and the Publish Artifact alone for now. The point of this post is to get your projects built, packaged, and published for deployment. Next what we need to do is add another few build steps to our Build definition.
Click on Add Build Step
And then we are going to Add the Octopus Package Application step, one for each of our projects that we wish to publish. Then we are going to add the Octopus Push Package(s) to Octopus step to finish up our Build.
Now for each of the projects you will need to edit the Package Id, Version, but more importantly you need to know what and where your source and destination path is going to be. If you don’t these two items correct, your build will fail.
We do know that our output is going to the artifacts directory and we know that each project is going to have its directory. But a critical component here is what the Octopus Step is going to do. It is important to note that we want, must, need to do is
- Keep your package small
- Take only the most relevant codebase
I have seen so many teams in the past and currently take everything from their source tree and package it into a 100MB+ file and attempt to push it to Octopus Deploy then deploy all of source tree to production. It is really hard to contemplate the security risks of putting your entire codebase for someone to steal and compromise.
For web applications and web api projects there is typically a _PublishedWebsites folder, this folder contains a reduced build output with only the most relevant dlls, config files, and other content for your web application or web api to run. Everything else is irrelevant and if you choose the folder at the higher level you will essentially get two copies of the same code base in your package. Citing the two points above, keep the package small and only package the most relevant code! This doesn’t mean only the files that have changed! This means your most minimal amount required run your application.
Now that we have edited the Package steps, we can move on the other important final element to this post, which is the Push Packages to Octopus.
Select the Push Packages step and you will notice that you need to edit the Octopus Deploy Server (this is the Service Endpoint that created earlier) and the most important item is the the location of the packages. Earlier in this post I told you that you didn’t really need to worry about the Publish Artifact step. The drop directory is where we are going to put our package after the build and packaging steps and that same directory is going be where we find those packages and publish them to our Octopus Deploy NuGet feed.
Now we are done! Save all the work that we have done and then queue a build. Don’t get frustrated if you your build doesn’t register success. Take a look at the logs for each build you attempt and step through to ensure that your folder paths are correct. Ensure that the API Key has correct permissions to publish to the Octopus NuGet Repository.
If you do have a successful build it tell you that it performed the compilation, packaging and publishing of the packages. Similar to this.
Checking each step to ensure that the logs are telling me what is happening.
and finally verified it has been pushed to our Octopus Deploy instance.
Now that I showed you how get your build to package and publish to Octopus. You may wonder what about CI/CD? or what can I do now?
To answer the second question, you can actually go ahead and make this a task group and save it for other teams to utilize in the future. You can also use this technique for other project types as well. Once you understand how you can create a package with the Octopus Deploy Extension, you can change the build definition to a CI/Timed Build and get those packages published for the next phase.
To answer the first question: That is for another post.