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.

2 comments:

  1. This approach works until you decide to create tag or branch for you project. In that case updating all externals (SVN term) could be very exhausted ... :(

    ReplyDelete
    Replies
    1. In tems of Mercurial:
      - By default you don't need tags for the plugins as each of them fixed at some revision. So tag is nothing but revision
      - If you needs to create release and tag creation is a part of this process, then you can get away from this anyway whetever project/plugin structure you use
      - Branches creation for application+all plugins at once is not a usual case. At least I don't remember that I've ever done that

      Delete