Continuous integration on server side – Part 1

I will start this post from a bit far… Far, because I will start from our AngularJs client. : )

I start with Yeoman.
Yeoman, if you work with AngularJs you have probably heard about yeoman.

If you don’t you really need to check it on http://yeoman.io/

It makes your life much easier!
“Yeoman is more than just a tool. It’s a workflow.” “Modern workflows for modern webapps”

It is a collection of tools:

  • Yo – It generates you a good skeleton to work on an AngularJs project.
  • Grunt – It helps you to host the app with only one command – grunt server (and a lot of other things it can do for you but this is the easiest one and the first one you will meet.)
  • Bower – It helps you to find and install easily components to AngularJs. (Like the node Package Manager in the Node.js world)
  • To have the whole stack of tools I would suggest one more tool, a Bower module: Generator-Angular

Generator-Angular can generate for you all the necessary components of an AngularJs app. Like services, controllers, directives and so on with a simple command:

yo angular:directive myDirective 

and it will generate you everything to have a directive as part of your app.

But we are working on a server side now. Losing all the good staffs only because you work on server side would make you feel bad. As it would make us sad too. BUT Grunt helps you on server side as well!

What is this Grunt exactly? – you could ask.

Grunt is a task runner tool to automatize the execution of your repetitive tasks.

If you are a developer Grunt makes your life easier with automatising your not ‘coding’-tasks and
if you are a project manager it gives you well sounding-words to improve your project’s marketing.

Automation and continuous integration. They are really nice words for public but they are really important things in development as well.

There are tasks that you need to do repetitive and doing them always manual would be a lot of work.

But you can automatize your tasks!

If you think of automatizing something in software development, the most common thought is testing. It is very important of course and automatizing the test runs is a really good idea (we do that as well)
but there are other smaller tasks as well that you can automatize. Like generating documentation, minifying, uglifying the source code and so on.

You need to execute some tasks very often. Maybe some tasks more than once a day. With that we arrived to the concept of Continuous integration*.
*Continuous integration (CI) is the practice, in software engineering, of merging all developer working copies with a shared mainline several times a day.

And here comes the grunt for. It will support you to do all of this.

Now we know everything about the ‘Why?’ but let’s see the ‘How?’ part of all of this.

Let’s see how to use grunt on server side!

(I will write about CI with grunt in three posts. This is the first one with a longer intro and with integration of small third-party tasks, in the second we will create an own task and check how to use it and the last one will be about testing and automatizing the test runs with grunt.)

Our requirements were:

  • We wanted to generate documentation to our project for the customer.
  • We wanted to prepare a deliverable package with the minified and uglified source.
  • Extra was the request to clean the folders before regenerating the components.

For almost everything exists a grunt component. If you use a third party library to generate doc or to test you will find the grunt task version of it.

– To minify and uglify the source code we found the grunt-contrib-uglify.
– We use YuiDoc to create our documentation and of course there is a task to use yuidoc with grunt – grunt-contrib-yuidoc.

This modules are available on github, they have simple documentations and it is easy to use them.

Integrate Grunt into your project

To integrate Grunt you need to add only one file to your project called Gruntfile.js.

The content of the file needs to be inside a module.exports block

module.exports = function (grunt) {
    ...
};

…and the file have to contain 3 section:

1, To configure the modules you use:

    grunt.initConfig({
    	...
    	});

2, To load the tasks (the sources)

    grunt.loadNpmTasks('module_name');

    grunt.loadTasks('your_module');

3, To specify the grunt task collections you want to run later

    grunt.registerTask('default', ['myclean:default', 'yuidoc', 'uglify']);

    grunt.registerTask('onlyDocs', ['myclean:onlyDocs','yuidoc']);

Our configuration for the two modules that I mentioned before are really simple:

uglify: {
            options: {
                banner: '/*! innio <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            my_target: {
                files: [
                    {
                        expand: true,
                        src: ['./core/*.js', './routes/*.js'],
                        dest: '../../Deployment/Server',
                        ext: '.min.js'
                    }
                ]
            }
        }
yuidoc: {
            compile: {
                name: '<%= pkg.name %>',
                description: '<%= pkg.description %>',
                version: '<%= pkg.version %>',
                url: '<%= pkg.homepage %>',
                options: {
                    paths: './',
                    outdir: './docs/'
                }
            }
        }

They are only from the default examples on the module’s github pages. We only parametrized them other for our purpose.

Tip 1. Uglify creates by default one file for everything inside the source folder but with the following config it generates separated folders and files with the minified versions of it and structures them as the original structure looked like.

And that’s it.

module.exports = function (grunt) {

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),

        uglify: {
            options: {
                banner: '/*! innio <%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            my_target: {
                files: [
                    {
                        expand: true,
                        src: ['./core/*.js', './routes/*.js'],
                        dest: '../../Deployment/Server',
                        ext: '.min.js'
                    }
                ]
            }
        },

        yuidoc: {
            compile: {
                name: '<%= pkg.name %>',
                description: '<%= pkg.description %>',
                version: '<%= pkg.version %>',
                url: '<%= pkg.homepage %>',
                options: {
                    paths: './',
                    outdir: './docs/'
                }
            }
        }
    });

    /*Load tasks*/
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.loadNpmTasks('grunt-contrib-yuidoc');


    /*Register tasks*/
    grunt.registerTask('default', ['yuidoc', 'uglify']);
};

To execute this you only need to write the command “grunt” into the terminal and hit Enter.

Spoiler

The next post will be about creating your own task. It is a more adventures challenge but we will go through it step by step.

Advertisements

One thought on “Continuous integration on server side – Part 1

  1. Pingback: Continuous integration on server side ā€“ Part 2 | My Journey InTo JavaScript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s