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.
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.
- Discover a bundle (one thing like this perhaps) that can be utilized to execute
- 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);
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
Right here is the code.
const getTaggedVersion = () =>
outcome("git describe --long", (err, response) =>
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
introduction="My title is $title"
> "My title is Matthew"
introduction=`My title is $title`
> "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
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 = () =>
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
readFileSync to learn a supplied file, and
writeFileSync to write to a supplied file. Each features are supplied by the
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 (
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
writeAsync, let’s go over yet one more perform supplied by the
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 = () =>
console.log(`Changelog merchandise already exists for n $merchandise`)
We’ll get to
writeChangelog in a second, however first, right here’s
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
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
We will verify this by making use of
indexOf once more. If
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" )
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
Which one must you use?
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.
The complete code is on GitHub.