Inject a Git SHA into your Angular + Node App

JD McCormack
4 min readNov 1, 2019

--

Image Courtesy of: https://github.com/

Recently, I was working on a web app at work that was being deployed by another department. Due to the short timeframe of the project, we weren’t able to get access to the build pipeline or environments. With each release, someone from the other department would pull our code and deploy it to the staging server.

Without fail, every time we did a deployment we’d get a host of bugs reported for things we had fixed. These were almost always related to a mismatch between the code they pulled for the server and the code they pulled for the frontend. Each time the engineers would promise they were deploying the latest code, but after a few hours of emails back and forth it would become apparent that one of the deployments was still set to an old commit.

Without access to the dev tools, we were unable to verify the commits ourselves so we were at the mercy of their team to check it each time. Instead, we chose to create a debugging tool for quickly and easily reporting the sha.

Let’s start with the backend:

The backend was super simple to setup. Since the code is running on the server, we can just kickoff a child process to grab the commit.

We create a new route /api/version. The command git rev-parse HEAD will give us the SHA of the current HEAD on the server. Using the --short flag just gives us an easier to read shortened SHA instead of the full length one. We then kick off a child process which will run this command on the server. There is a chance the server the code is running on won’t have git installed, so we catch that error and just return a generic string if it errors out for any reason. Otherwise, we trim() the trailing whitespace of the SHA and return it as a bit of json. Now when we navigate to this route we see this:

The sha returned in a JSON object.

That was easy enough! What about for the client side?

Well the biggest issue is the client code is running in the browser. We can’t just run another child process and expect to get the SHA back. Instead, we’ll add a small script to the build process to inject the file into the frontend. We’ll then make it so this is a hidden variable we can see in the dev console.

First, let’s make a template file. This will be what we use to generate an object with the sha in it.

It doesn’t look like much, but we’ll be using a regex to replace ~GIT_SHA~ with the actual sha.

Next for the build script:

Using the filesystem library “fs”, we copy the git-sha.template over to a file called git-sha.ts. We then call the child process again with the same git command as before. We then call the replace(key, value) function to replace the key ~GIT_SHA~ with the actual sha. Here we’re just using a simple regex to find and replace the key. This could easily be expanded to more keys if there were additional environment variables you wanted to be able to inject at build time. After running this with node:

node inject-git-sha.js

We get the output file:

Which we can then reference in our code like so:

window['GIT_SHA'] = buildConstants.GIT_SHA;

Then in the console we can access this by just typing in the name of the constant:

The Git Sha reporting in the google chrome console.

But wait we have a slight issue

We don’t want to check in the git-sha.ts file as we want it to generate itself on build. The obvious solution would be to just delete the file and add it to the git ignore, but then wherever we try to import it in angular we’ll get an error because the file doesn’t exist. What’s the solution? Check in a file without the SHA set, then tell Git to track the file, but no additional changes to it. To do this, create a placeholder git-sha.ts file like below:

This has the added benefit of including a default value should the build fail for any reason. Now, commit this file into git then run:

git update-index --skip-worktree environments/git-sha.ts

This will mean any changes to the file will be ignored, but the file will remain checked into git. Now we just need to add this as a build step in package.json:

{
"scripts": {
"start": "npm run generate-sha && ng serve --host 0.0.0.0",
"build": "npm run generate-sha && ng build --prod",
"generate-sha": "node ./src/environments/inject-git-sha.js"
},

And that’s it! Now you can easily access the sha’s of both your front-end and backend even when you don’t have access to the servers themselves!

--

--