Deploying An ASP.NET Core Site, You're Still Doing It Wrong: Part 4 - Octopus Deploy: Configuration And Deployments

This day and age, predictability and reliability are two of the most important words when it comes deployments. In this series, I am going to talk about how to add both predictability and reliability to your ASP.NET Core Continuous Integration pipeline using TeamCity and Octopus Deploy.

  1. Intro
  2. TeamCity
  3. Octopus Deploy: Installation And Targets
  4. Octopus Deploy: Configuration And Deployments
  5. Why Stop Now

In the last post of this series, we discussed some of the reason why you want to remove the human element from the configuration and deployment of an application and how we can go about accomplishing this through automation with the help of Octopus Deploy. We then went over the details of actually installing Octopus Deploy and setting up Environments, Accounts, and Targets inside our installation. In this post we tie it all together by creating a Project inside Octopus Deploy, setting up a Deployment Process and automating configuration using a single source of truth.

Revisiting TeamCity: Pushing To Octopus

Depending on how many and what type of deployment Targets you have, you might have to revisit your build configuration(s) and re-configure them to produce assets for x-number of platforms. For example, if you planned on deploying your ASP.NET Core application to a Windows and Linux environment, you would need to configure your TeamCity Build(s) in a way that produces the publish assets for both of these platforms.

When we originally set up our "Build Configuration" inside TeamCity, we got to the point where TeamCity was restoring, building and publishing our .NET Core application. This process produced an artifact that was "scoped" to the TeamCity environment. We now need to take the process one step further and push those artifacts over to Octopus Deploy so that our Octopus Deploy Project can utilize them as it sees fit.

The team at Octopus has made available a plugin that will help us with this build step. Head over to the Octopus Download page and deploy the plugin to your TeamCity server. If you don't recall how to deploy plugins to TeamCity, you can reference the "Installing 'The' Plugin & .NET Core SDK" section in Part 2 of this series.

Once installed, head back to your Project's Build Configuration and add a Build Step of the type "OctopusDeploy: Push Packages" as the last step in your build process.

TeamCity Octopus Push

A basic configuration would encompass the following.

  • Octopus Connection.
    • Add the URL to your Octopus install.
    • Add the API Key to validate your connection.
      • This key is generated and obtained by and per users inside of Octopus.
        TeamCity Octopus Push
  • Packaged Paths
    • Define the contents and name of the package that the plugin will produce and push to Octopus.
  • Publish packages as build artifacts
    • In Part 2 of this series, we had TeamCity create an artifact directly by setting the "Artifacts Path" value in the "General Settings" page.
    • By selecting this checkbox, we can effectively remove that setting from "General Settings" and still get an accessible artifact inside of TeamCity.

Once you have this step configured, in TeamCity, manually tell your Project to "Run". If your new build step was setup correctly, you can view that Octopus Deploy received the artifact from TeamCity by heading the configuration > audit screen in the Octopus Deploy portal and looking for a "pushed" log in your feed.

TeamCity Octopus Log

Creating A Project

A project is a collection of deployment steps and configuration variables that you want Octopus to run during deployment. It's like a recipe - you define how the application is deployed, and then you create many releases to deploy different versions. OctousDeploy

Now that we have an "Environment" containing a "Target", we need to create a "Project" to that utilizes that "Target" for deployments. Head to the projects page in your portal and click "Add Project". Assign it a name and add a description if you see fit. Click "Save" and you should end up at your newly created Project's portal page.

When creating a Project, typically you use that Project to promote a single app through your CI pipeline. Development to test, test to stage and stage to production. In a multi-platform deployment, you might have to abstract each deployment out to its own Project.

Variables: One Source Of Truth

Variables contain the configuration values for an application that change as it's promoted from one environment to another. Octopus Deploy

A standard ASP.NET Core application is configured at runtime by way of the appsettings.json file. Depending on our deployment environment, the values in the file will need to be updated. In order to automate this process, we need to head over to our Project's variables page and add key-value pairs that coordinate to our deployment needs and scope them to our desired Target.

A basic appsettings.json file might look like this.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=pioneercode;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

Using the DefaultConnection value as an example, we can add it to our Project Variables like so.

TeamCity Variables

In order to scope to a nested value in a JSON file, we have to use the : delimiter like so, ConnectionStrings:DefaultConnection. If you are dealing with .config based configuration files, you would not have to "scope" to nested variables like this. For more information, you can head to the official documentation at Configuration Files.

Here you can see we targeted a variable in our appsettings.json file, set a value for it and set the Scope to our Production Target. This means when we run a deployment against our Production Target, the appsettings.json file will get updated with this value before being deployed. If we wanted to set a value on a different deployment Target, we would have to add a new variable and set its Scope appropriately.

Deployment

Each project defines the actions you want Octopus to perform on your behalf. In Octopus terms, this is called the deployment process. The deployment process is like a recipe. It defines the set of instructions that will be run repeatably each time the project is deployed. Octopus Deploy

Now that we have setup "one source of truth" in regards to our configuration variables, we can start putting together a Deployment Process. Head to the Project you are working on go to the Process tab and click "Add Step". You should be presented with a list of Process template to choose from.

Octopus Deploy Process Step Templates

Linux

For my Linux Target, I picked the template title "Deploy a package". Once selected, you are presented with a list of configuration options. Here you are going to want to define things such as what package you want to deploy, what Target you want to deploy to, where you want to deploy on your Target, and what files to target for Configuration updates.

Octopus Deploy Process Step Configuration

If you click the "Configure features" link on the configuration page of a Deployment Process Step, you will be presented with more configuration options to add to that step. This is where I enabled the "JSON Configuration Variables" option. This option is responsible for telling our step to reach into our "single source of truth" and make updates to the appsettings.json file accordingly.

Windows

When deploying to Windows under a typical IIS Web Server, you will want to pick the "Deploy an IIS Web Site" template for you Deployment Step. Of which has a very robust set of configuration values centered around the idea of a website inside of IIS. This includes items such as IIS Application Pools, IIS Bindings, and IIS Authentication and Configuration. If you are familiar with IIS, configuring this type of Step should feel familiar.

Topics such as setting up IIS to work with .NET Core is out of the scope of this post. For more information on how to accomplish, you can reference the official documentation at - Set up a hosting environment for ASP.NET Core on Windows with IIS.

The amount of options in the "Deploy an IIS Web Site" type is much larger then "Deploy a package" type because a lot of the Web Server configuration was setup ahead of time on the Linux Deployment. How you approach this is entirely dependent on what suits your goals. Meaning, there is nothing stopping you from controlling NgNix on Linux from your automated deployment just like you would with IIS on Windows.

Is This Actually Going To Work?

Yes, yes it will. Eariler in this post, we already verified Octopus Deploy was receiving packages from TeamCity by looking at the configuration > audit logs. Now, head back to your Project page and on the top left click "Create release".

Octopus Deploy Create Release

After you click "Create release", you will end up at configuration screen for you release where you can specify a version number that is relative to Octopus Deploy, a package version coming from TeamCity and release notes if you desire.

Octopus Deploy Configure Release

Once you hit "Save", if all is setup correctly your Project will start its Deployment Process. Upon successful completion, you will end up with something similar on your Octopus Deploy portal homepage. If something went wrong, you will get a red "X" instead of a green check, along with an opportunity to view the associated logs.

Octopus Deploy Successful Release

Congratulations!

If all is in order, you now have an automated CI pipeline from the point of code check-in to the actual deployment. We have removed the human variable from the equation and introduced predictability and reliability into our deployments. At this point, I think we can say that we are now "doing it right".

Up Next

Int the next post of this series, I will talk about additional steps you can take to make your CI pipeline even more reliable and useful. Until the, feel free to leave any comments, questions or concerns in the comment section below.

Deploying An ASP.NET Core Site: You're Still Doing It Wrong - Part 5 - Why Stop Now