Saturday 5 May 2012

Grails n applications * m plugins = Inline plugins + VCS Subrepositories


F.e. you have several Grails applications that you (team, several teams) develop simultaneously. You needs to share certain logic between all the applications, so you get a number of shared plugins. How to organize infrastructure that provides effective/fast development processes?

Classical infrastructure would be to have independent repositories for each plugin and application. Each plugin is included into application via BuildConfig.groovy (f.e.) as a dependency. This way looks fine for usual J2EE application development. But this is not true for Grails. Here we lose possibility to develop application fast enough i.e., run application and change at runtime both application and plugins simultaneously (!)

Here is the approach that is based on 1) Grails inline plugins + 2) Mercurial subrepositories. Grails application structure:
- <app root>
 - [grails-app]
   - [conf]
 - BuildConfig.groovy
 - [lib]
 - [plugins]
   - [plugin 1]
   - [plugin 2]
   ...
   - [plugin <n>]
 - [scripts]
 - [src]
 - [test]
 - [web-app]

Let’s see BuildConfig.groovy content:
…..
grails.plugin.location.plugin1 = ./plugins/plugin1
grails.plugin.location.plugin2 = ./plugins/plugin2

grails.plugin.location.plugin<n> = ./plugins/plugin<n>
….

Here each plugin is Mercurial subrepository, technically it is a link to external repository that is fixed at specific revision. Any developer can change in parallel application and shared plugins just in place. Each commit on application level will cause additional commit into changed plugins repos too.
Here is the application file structure that from VCS (i.e. Mercurial) point of view:

- <app root>
 - [.hg]
- hgrc (1)
 - ...
 - [plugins
   - [plugin1]
     - [.hg]
       - hgrc (2)
   - [plugin2]
     - [.hg]
   - hgrc
...
- [plugin<n>]
 - [.hg]
   - hgrc
 - ...
 .hgsub (3)
 .hgsubstate (4)

Now let’s see what is there:

  • hgrc (1)
[paths]
Here is the application repository URL




  • hgrc (2)
          [paths]
          default = http://host/hg/plugin1
Here is the plugin1 repository  URL

  • .hgsub (3)
          [paths]
          plugins/plugin1 = http://host/hg/plugin1
        Here is the link to plugin1 repository that is stored in application repository


  • .hgsubstate (4)
          8bc9d1062f9d7bdf85dd144e3070d2162907ee4b plugins/plugins1
        Here is the revision number of plugin1 repository that is stored in application repository

This structure perfectly fits for day by day development on case when your team is working simultaneously at Grails based applications that share a lot of different logic via set of shared plugins.

P.S. In case if you don't use Mercurial you can do the same things with Git or SVN.

Thursday 3 May 2012

Project sources health overview: HoTo?

Preface

 Nowadays a lot of developers uses modern and popular tools that performs static code analysis, calculate code coverage and etc. All of this provides possibility to keep projects in fit. Still I it was not enough for me and I was thinking about how to check project sources health. Finally I found simple way to do this basing on the activity that developers produce within the project for a period of time.

Idea

 What are the tools used in every day development? Version control system where all the source go + bug tracking system. Each sources change (or most of them) is committed into version control using messages that usually defines the issue number basing on which anyone could check what was the real task. Most of the tasks/issues have 'Bug' or 'New Feature' type. Final my idea was to gather statistics on each source file to find out how many changes are committed into it basing on certain issue type, i.e. Bug or New Features. This give the overview how 'healthy' the source is and whether it requires closer look and potential refactoring.

Implementation

 Finally I wrote a console tool using Java + Mavenhg4j that analyzes project source files that are placed into Mercurial repository and whole development process is organized using Jira. See more details here.