- Adding a copyright banner at the top of our compiled JS library files
- Tagging our git repo with our library version
- Deploying our library to an AWS bucket
The team was already using Grunt to automate the build process
through a custom
grunt build task, so we were ready to build our
task on top of it.
Adding a copyright banner to the top of a file
The goal of this task was two-fold. First, we wanted to add a non-minified text notice at the beginning of our already-minified library with the usual authorship, copyright and license information.
Second, we wanted to include in the banner the updated version number,
which needed to be extracted from the project’s
package.json and only added to the library after the library had been compiled.
It turns out this simple operation of adding a string to the top of a file can be performed both from the concat task and from the uglify task, which, in our case, was useful because we were publishing both a non-minified and a minified version of the library a we were already using both tasks.
Before adding the banner we had to load the contents of
object, which can be simply achieved by making a call to
is one of the built-in methods available in Grunt.
1 2 3 4
From that moment on, the contents of
package.json file were available from the
pkg variable and the addition of the banner was as easy as adding the corresponding
banner option to the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Notice that this configuration provides a means to keep the copyright notice updated
to the year of the build, by invoking another one of Grunt’s built-in methods:
Tagging the remote Git repository
We also wanted to tag our GitHub repo every time we released a new version of our library. I found out there is a nice Grunt plugin to run Git commands as Grunt tasks: grunt-git.
At the moment of this writing the
grunt-git plugin supports the following
Git commands (with maybe some limitations):
So we configured a Grunt task that tagged the repository with a label based
on the contents of the
package.json file at the time of its execution.
1 2 3 4 5 6 7
That was pretty easy. Wasn’t it? Well, not really. We also wanted to ensure that our local repo had no unstaged changes before tagging (i.e. it was “clean”), because if it wasn’t that would be a sympton that the repository contents were probably not in-sync with the remote.
Fortunately, another Grunt plugin came to the rescue grunt-checkrepo. which can do exactly that, i.e.: check whether there are unstaged files in local repository, as well as other tag-related checks which turned out to be useful later on.
For the moment, we only created the subtask to check if the repo was clean:
1 2 3 4 5
And then we registered a task to perform the tag operation only after succesfully checking that the local repository was clean:
1 2 3 4
Deploying our library to an AWS S3 bucket
Once our library was tested and compiled (not part of this article) and our repo was clean and tagged, we were ready to deploy to our CDN, which in our case was the AWS S3 service.
To perform this task, another convenient Grunt plugin, grunt-aws-s3, came handy.
Naturally, part of this plugin configuration involves (who would have thought?) providing the user’s credentials to the AWS account that is intented to be used. We were concerned that if our AWS keys were stored in a file, they might end up being exposed by mistake, despite being .gitignored. For that reason, we decided to store the credentials only in system (environment) variables.
It turns out Grunt exposes, by default, all environment variables
Gruntfile.js through the
process.env variable. So just, we created our
custom task to read them:
1 2 3 4 5 6 7
We also wanted to do some additional checks on the state of our local repo before
uploading, like ensuring that the repo was clean (again), that the last commit
had been properly tagged, that the tag that had been used matched the current
version specified in
package.json and also that the version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
Some of this validation might seem redudant considering that the
tagging of the repo and the push of the tag to the remote was suposed to be done
exclusively via the aforementioned Grunt workflow. However, we want our Grunt tasks
to follow the usual best practices in development and, therefore, be robust and modular so
that they can be reused and combined and not depend on any of the other tasks. This
approach allows the
deploy task to be executed independently of the
with some guarantee that we are deploying the latest code in our branch.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
One of the nicest bits about the grunt-aws-s3
plugin, is that it it allows to perform a task in
debug mode, which would run
a safe version of the task in which the credentials and the availability of both
the AWS S3 bucket and the file to upload are checked, but no actual uploading takes
place. This behaviour turns out to be very useful while creating or modifying the
task itself and can easily be forced by adding
debug: true to the subtask
Finally, publishing the library made the release “official”, which made it necessary to ensure we were updating the remote with the current tag in the local repo. Another grunt-git
1 2 3 4 5 6 7 8 9
That was all. We added a couple of minor tasks after that, like a task to automatically rebuild our library documentation based on its own comments grunt-docco but…you get the point.
There is a lot of automation that can be achieved by doing some research. I believe that all this automation very quickly compensates the time spent on that research.
I believe there is also room for even safer and more useful processes to be designed by using git hooks in combination with grunt tasks.
I’d like to know about other people’s experiences with front-end automation. If you have something to share, please, post a comment.