How to Write JavaScript Code to Create and Update a Changelog | by Matthew Croak | Apr, 2022

No extra turbines, logs, or dependencies-now for JavaScript!

Picture by Greg Rakozy on Unsplash

In case you learn my previous post about write a python script to create and replace a changelog, or the post earlier than that about writing a changelog script in bash, you would possibly discover this put up fascinating as properly. The aim is so as to add help to a number of languages so builders don’t have to decide on only one reasonably than they’ll select the one that’s most according to the stack they’re at present utilizing.

I’ve added JavaScript support to increase my original changelog script to engineers with a desire for JavaScript. Now you can use the identical script logic with JavaScript. In case you’re a JS developer and need to add extra customizations to your changelog creation/technology, you are able to do so extra simply now with this added help.

Because it’s the identical logic as my final two posts pertaining to Bash and Python, I received’t go too in depth when it comes to performance. Just like the one on Python, this put up will spotlight syntactic variations.

First, create a changelog.js file to run the script’s logic. You may make this file executable by working chmod +x changelog.js. With this it is possible for you to to run ./changelog.js out of your command line or embrace it in one other script if that’s most popular by appending ./changelog.js to it.

Subsequent, we want our venture’s model to be synced with our changelog. That is most likely probably the most difficult a part of the JavaScript code. You are able to do considered one of two issues:

  1. Discover a bundle (one thing like this perhaps) that can be utilized to execute git describe --long in a JavaScript file.
  2. Be a purist and do all of it with your individual code! If that is the route you’re going, now we have just a few steps.

First, now we have to require what is known as child_process after which run exec on that little one course of. This method permits us to run instructions within the console and buffer the output. Right here is our first line of code.

const exec = require('child_process').exec;

Subsequent, we have to write a perform that runs a toddler execution that accepts "git describe --long" as an argument, together with a callback perform. Under is our perform.

const outcome = (command, cb) => 
var little one = exec(command, (err, stdout, stderr) =>
if(err != null)
return cb(new Error(err), null);
else if(typeof(stderr) != "string")
return cb(new Error(stderr), null);
else
return cb(null, stdout);

);
return little one

That is mainly a wrapper that can execute a handed command together with the callback perform. This wrapper additionally affords preliminary error-handling. All now we have left to do is write a perform that truly executes this sequence and handles the outcome. We’ll name this perform getTaggedVersion.

Right here is the code.

const getTaggedVersion = () => 
outcome("git describe --long", (err, response) =>
if(!err)
console.log(response);
else
console.log(err);

);

It’s a bit convoluted, however it will probably prevent from having to put in and configure a dependency! Now, onto the remainder of our script.

There are locations in changelog.js the place we use string interpolation. That is completed a bit otherwise in JavaScript than it’s in Bash or Python. See under for Bash string interpolation.

title="Matthew Croak"
introduction="My title is $title"
echo $introduction
> "My title is Matthew"

Lastly, right here is string interpolation for JavaScript.

title="Matthew Croak"
introduction=`My title is $title`
console.log(introduction)
> "My title is Matthew"

String interpolation is necessary for the script as a result of we shall be writing and rewriting the changelog file from supplied strings. These strings will include up to date info, resembling at this time’s date and the model of the bundle.

Subsequent, let’s write our init perform. This perform shall be used to find out whether or not or not we need to create a brand new changelog or just replace an present one. In JavaScript, the fs module makes file dealing with comparatively easy. We will import existsSync from the fs module and verify if a supplied path exists. See under.

const existsSync = require('fs');
const path = './CHANGELOG.md'
const init = () =>
strive
if (existsSync(path))
newChangelogItem()
else
newChangelog()

catch (err)
console.log(err)

Subsequent, let’s go over how we learn and write our changelog file. In Bash, that is the way you learn the file:

whereas learn line; do           
# code carried out for every line
completed < CHANGELOG.md

In JavaScript, we make use readFileSync to learn a supplied file, and writeFileSync to write to a supplied file. Each features are supplied by the fs module. readFileSync will basically take a supplied file and convert it to a string. We will then take this string and cut up it at each new line (/n).

This fashion, we are able to create an array of traces to iterate over. See under.

const fileData = readFileSync("CHANGELOG.md",  encoding: "utf8" );
const fileDataArray = fileData.cut up("n");

writeFileSync appears to be like comparable nevertheless it requires an additional argument (between the filename and the encoding information). This third argument is the supplied string that shall be written into the file. See under.

writeFileSync("CHANGELOG.md", newFileData,  encoding: "utf8" );

Earlier than we proceed on with readAsync and writeAsync, let’s go over yet one more perform supplied by the fs module: appendFile.

We will use appendFile to, because the title implies, append file information to a file. By supplied a filename, file information (as a string) and a callback perform, we are able to create our changelog file with ease. See under.

const newChangelog = () => 
appendFile("CHANGELOG.md", changelogStart, (err) =>
if (err) throw err;
console.log('Changelog is created efficiently.');
)

This perform will create a brand new file (CHANGELOG.md), populating it with changelogStart (the string that’s obtainable within the changelog.js file on Github). Now that we made our perform which is able to create a changelog for us, ought to one not exist, we are able to transfer onto our perform so as to add a brand new changelog merchandise to an present changelog!

Now, earlier than we get into the road insertion code, let’s see what code we have to decide whether or not or not we ought to add an merchandise. Keep in mind, our changelog gadgets correspond to a venture model and date. If we have already got a changelog merchandise for the present model and date, we don’t must create a brand new one.

Under is the code we’ll use to verify if we want a brand new merchandise.

const newChangelogItem = () => 
if (checkIfItemExists(merchandise))
console.log(`Changelog merchandise already exists for n $merchandise`)
else
writeChangelog()

We’ll get to writeChangelog in a second, however first, right here’s checkIfItemExists.

const checkIfItemExists = (str) => 
const contents = readFileSync('CHANGELOG.md', 'utf-8');
return contents.indexOf(str) > -1;

This perform makes use of readFileAsync. This may generate a stringified model of our changelog. As soon as it’s a string, we are able to use verify the index of our changelog merchandise. If it’s higher than -1, then it exists and we don’t want so as to add a brand new one. In any other case, add a brand new one. Easy, no?

Now that we’re dealing with whether or not or not we are able to/ought to add a brand new changelog merchandise, let’s try how we are able to truly add one. For this, we are going to make use of readFileAsync and writeFileAsync. We are going to convert our file into an array of traces (as talked about earlier), then iterate over that array if traces. Whereas iterating over our traces, we lookout for the road the place we shall be inserting our new merchandise. This line is indicated by "## [Unreleased]".

We will verify this by making use of indexOf once more. If fileDataArray[i].indexOf(“## [Unreleased]”) > -1 then we all know that that is the road the place we insert our merchandise. How can we insert our merchandise in JavaScript? By making use of splice.

splice permits us so as to add new parts rather than an present one in our array. We will merely splice our new merchandise into our array proper after our “## [Unreleased]” line. See under.

iterateArr = [...fileDataArray)
for (var i = 0; i < iterateArr.length; i++)
if (fileDataArray[i].indexOf("## [Unreleased]") > -1)
fileDataArray.splice(i + 1, 0, `n$itemn### Addedn- ADD CHANGE HERE!`)
const newFileData = fileDataArray.be part of("n");
writeFileSync("CHANGELOG.md", newFileData, encoding: "utf8" )
break

iterateArr is created from fileDataArray through the use of the unfold operator. We do that as a result of we don’t need to iterate over the array we’re manipulating. As soon as now we have spliced our new merchandise into the array of traces, we are able to be part of them into one string. We will then present this string to writeFileAsync and write it to our CHANGELOG.md file.

Which one must you use?

Provided that this changelog technology now has help for Bash, Python and JavaScript, which one must you use? I personally discovered Python to be most popular. I really feel the training curve was Bash was a bit wider than Python (for me a minimum of) and whereas Bash has fewer traces of code, I struggled extra with debugging.

JavaScript is my most popular language (I’m biased as I’ve labored for years with JavaScript professionally), however for this use case, I discovered I needed to write much more configuration code. Whereas the fs module supplies loads of built-in logic for file administration and manipulation, I needed to write separate features to help the execution of git instructions and I discovered there extra steps with the intention to begin climbing by way of the file and including textual content.

However in case you’re a JavaScripter (?) by way of and thru, you now have a pure script to include into your app to generate a changelog and add changelog gadgets. It additionally affords you flexibility when it comes to format and changelog content material with out the necessity for turbines, logs, or different dependencies.

The complete code is on GitHub.

More Posts