Pairing Git with Webpack+React application

VK Team
4 min readFeb 18, 2022

Sometimes showing some information from your git repository right in your application can be helpful.

My name is Nikolay Syrmolotov, I’m a front-end engineer at VK Pay and in this article, we’re going to take advantage of the NodeJS built-in function execSync and display three versions of the main branch (the one in the current branch, the local one, and the remote one) so that we can see the difference between all the three versions of the main branch right in our app without doing things manually.

Warning! Do not allow any user input in execSync. I hope you will not use a development bundle as a production-ready one, so no third-party data will make it to the function. Anyway, if you do use a dev bundle of your app with user input ending up in execSync somehow, make sure to validate the input.

Let’s write some code! First of all, we need a function with execSync, which accepts command as a string and executes git command.

We use casting to String because execSync returns a buffer. This function can accept any string command that git will try to execute.

Next, we have to define an object that contains our environment variables. At first, I got something like:

What do these commands do?

  • git branch –-show-current will return the name of the current branch name;
  • git merge-base main ${branchName} will revert commit hash of the last common commit between the main and the current branches;
  • git log -–format=%B commithash will return the body and the subject of a commit by the given commit hash (we can also use the subject — %s).

They worked pretty well but only once per build. And then I came across runtimeValue at webpack:

It is possible to define variables with values that rely on files and will be re-evaluated when such files change in the file system. This means webpack will rebuild when such watched files change.

Perfect! It seemed to be a suitable solution to our problem. It enabled us to get a new value not once per start of a build but on every file change. However, it had a minor downside: if a developer checked the application after a while without bringing any changes to the local codebase, they probably would see outdated information. I have not come up with a better solution for this yet but it is just a slight inconvenience, which can be dealt with by triggering the rebuild. Let me know if you know how to fix it!

Let’s take a look at what I got next:

This way we will get a string with a message from git Merge branch ‘X’ into ‘main’. Now, we need to extract this X in order to show it in our application. It is time for a simple regex:

Since we are using the pattern rc/x.xxx.x for release candidates in our project, this regex is doing its job pretty well. In your case, you need a pattern matching your RCs or branches to extract it from the string.

Putting everything together, we get:

If we want to show a version of the current main branch, we can simply run git log -n 1 main --format=%B:

Finally, we want to show a version of the remote main branch — just to make sure we can pull updates for our local main branch.

We can use git ls-remote to get a list of all the heads, tags, and merge requests of a remote repository. We are interested in heads, and we also may be willing to specify our remote. In my case, it’s origin. You can check the list of origins by executing git remote.

git ls-remote --heads origin

This way, we will get all the heads, but we need only those that start with rc:

git ls-remote --heads origin rc\*

So we have got heads for RCs. Now we should sort them because the default sorting is by string characters — it means 0.100.10 will be placed right after 0.100.1. We can do sorting by date:

git ls-remote --sort=committerdate --heads origin rc\*

Now it is in order, and we want only the latest result on the list:

git ls-remote --sort=committerdate --heads origin rc\* | tail -n1

Perfect! We have got commit hash and its ref:

…ccf55a1d refs/heads/rc/0.100.10

Summing up the above, we can return our latest remote version of main branch:

Yet, there is a new problem. This git command requires a connection to our remote repository, thus taking some time. And in some cases like using VPN or a bad connection it might take longer than usual — for instance, I experienced 5–10 second delays.

Luckily, I have managed to find a quick fix for that.

We can declare a constant for delay in seconds and an empty variable:

Then, inside of the callback function for REMOTE_VERSION runtime value, we should check if remoteUpdTime is empty or if current time in milliseconds during the rebuild exceeds the previous “timer”, so we can update the version:

Now if the rebuild is triggered at any moment after these 5 minutes, we will get an update for the remote version of the main branch.

Awesome! Now we can access REMOTE_VERSION, LOCAL_VERSION and WORKING_VERSION as any process.env variable in our React application.

In our application we use these for two scenarios:

  1. We can press Shift+V in any part of the application to see a little pop-up window with all three versions;
  2. There’s a status bar in the settings, which shows if we need to pull or apply changes to the current branch.

--

--