Tag : git

Tips and Tricks: Git Check-Ignore

Have you ever found yourself wondering “why in the world is git ignoring this file!?”

Have you spent countless minutes combing over every line of a .gitignore to try to determine what obscure rule is preventing your file from being committed?

Have you ever been so frustrated with git, that you bit your computer?

Have you ever been so frustrated with git, you bit your computer?

I have something that can help! It’s called git check-ignore and it will CHANGE. YOUR. LIFE!¬†(your results may vary)

If you haven’t heard about the git check-ignore command, you’re missing out on an underappreciated git command.

I found myself stuck for about 15 minutes one day, trying to figure out why a file wasn’t showing up in git. After banging my head against a wall for so long, I decided to see if there was a better way. I found an article that pointed me at this little command and I it seemed like it wold do the trick. I navigated to the folder that contained the troublemaking file, Settings.config, and typed git check-ignore -v Settings.config and it gave me:

.gitignore:51:Source/*.Web/App_Config/Include/zSites/*/**/*.config

I was overjoyed! It told me which gitignore file it was in (there were several on the project), what line to look at, and what the rule was.

If you’d like to read up on it further, check out the official docs: https://git-scm.com/docs/git-check-ignore

Octopus: Build Once, Deploy Many

The Problem

I had to setup a production environment for a client who had a development environment, a QA CM, two QA CD’s, a production CM, and 2 production CD’s. These machines are behind all sorts of firewalls and on different subnets. The normal robocopy procedure wouldn’t have been easy. On top of that, the build in Jenkins takes about 10 minutes to complete. Simple math: 10 minutes x 7 targets = 70 minutes.

I needed to solve 2 problems: first, deploying code with the network configuration. Second, cutting that deployment time down. This is where Octopus shined.

What is Octopus?

Octopus is a deployment tool that allows for a “build once, deploy many” style of deployments. It allows you to use your CI tool of choice (i.e. TeamCity or Jenkins) to build your code, and it will then deploy that code on as many servers as you want.

How it Works

Octopus has 2 main parts: the Octopus server itself, and its tentacles. Tentacles are listening applications that you install on the deployment target. They listen on specific ports, which are easy to whitelist on a firewall across different networks. Think of Octopus as the conductor, and the tentacles as the orchestra.

The Process

Deployments

The deployment procedure becomes the following:

  1. Jenkins builds the code and packages it up into a zip format for Octopus
    1. Note: an alternative (and preferred) method is to have the CI server create NuGet packages. TeamCity has a great integration for that, but as of my this post, my experience is that Jenkins and NuGet were difficult to work with.
  2. Jenkins pushes the code package to Octopus’ package repository
  3. Octopus pushes this code package to each tentacle that is configured to build this code
  4. The tentacle performs any config transforms, runs any custom scripts (PowerShell)
  5. The tentacle deploys the code

Source Control

This was the hardest part actually, and it didn’t have to be. When you’re not working with a release management tool such as Octopus, you get into a certain mindset. I’ve used GitFlow in the past and it’s a great way of handling releases. I’d have separate, identical Jenkins jobs setup to build the code on different branches. The jobs would also push the code to where it needed to go (via robocopy or web deploy). Once a release manager is in the picture, things change a bit. I mentioned earlier the concept of “build once, deploy many.” No more separate Jenkins jobs. I needed to get things down to a “build once” philosophy. In the end, the same exact code is going to get pushed to different environments. How do we do this? This was a hard question for me to solve. I couldn’t find too many blog posts out there or instructions.

Since the team was new to Octopus, we decided to keep things simple and build only off of master. We’d make feature branches off and submit pull requests to be reviewed. Once approved, the code would enter master. Octopus would handle the individual releases and rollbacks effortlessly, so we thought this would be sufficient. Once we got closer and closer to the production deployment, we realized that this wouldn’t be sustainable. We needed to have a separate unstable channel, but we had a problem. I thought we’d need to have a separate Jenkins job: one for unstable and one for stable. This would violate the “build once” principle, and we’d have different code on different environments.

The Jenkins Conundrum

I reached out to the Sitecore Community Slack team to see if anybody’s encountered this before. Kamruz Jaman answered my distress call and shared with me his experiences with Octopus and TeamCity. He gave me a lot of helpful information, and helped me realize my problem. I had forgotten that a Jenkins job could build multiple Git branches! TeamCity handles different build configs a lot more cleanly (my opinion) and it was probably second nature to him, but it blew my mind.

We added two new branches to our workflow: “dev” and “release”. I altered Jenkins’ Git config to look for the following regex as a branch specifier:

:^(origin\/master$|origin\/dev$|origin\/release-\d{0,3}\.\d{0,3}\.\d{0,3}$).*

Using¬†GitVersion, I was able to setup different channels in Octopus, so it was able to look at the version name and deploy the package to different environments. Packages with a version “unstable” went to dev, “beta” went to QA, and release versions went to QA + Release.