1
votes

I have read the documentation here, which gives the structure, but does not offer any help on how to create the actual logic.

I want to build a very simple script which does a clean, creates the war, creates a zip of the sources (without the target directory, and without any svn dirs), and creates a tar (idealy gzipped) of the migrations dir so this can be used with liquibase. Each of these 3 artifacts should have the app version in their name (like the existing "grails war" does.

The project structure looks like this:

svn
main-app
   grails-app
       migrations
       target
       :
exploded-plugin-1
   grails-app
   :
exploded-plugin-2
   grails-app
   :

This is how far I have got:

includeTargets << grailsScript("_GrailsInit")

target(packageUs: "Creates war, zips source, tars liquibase scripts") {
    depends(clean, war-us, zip-source, tar-liquibase)
}

setDefaultTarget(packageUs)

target ("war-us" : "creates war") {
    ant.war()  // this was a guess at calling the existing war - it doesnt work
}

target ("zip-source" : "zips sources") {
  // cd to top dir of project, i.e. above the app.
}

target ("tar-liquibase":"produces tar of migrations dir") {
    // tar up the migrations dir
    // name it with the app-version
    // put it in the target dir along side the war etc.
}

target ("clean") {
  // call the default clean some how, or cd to target dir, and delete everything
}

The above script was originally created with "grails create-script package-us"

Sadly, not even this works, it produces the following error:

| Error Error executing script PackageUs: No signature of method: org.codehaus.gant.GantBinding$_initializeGantBinding_closure5.doCall() is applicable 
for argument types: (java.lang.String, PackageUs$_run_closure5) values: [clean, PackageUs$_run_closure5@5ed0b4e3]

I could not find any example scripts nor documentation beyond the very basic overview in the link.

I cant even get ant.echo() to work - intellij says there is only one ant.echo function which takes a LinkedHashmap, a String and a Closure, but the ant documentation says echo only takes a "message" string. What should the linkedhashmap, string and closure be? I have tried minimum 30 different variations, none work.

Update 1: What I have got working so far

includeTargets << grailsScript("_GrailsInit")
target(packageUs: "Creates war, zips source, tars liquibase scripts") {
    depends(clean, "war-us", "zip-source")
}
setDefaultTarget(packageUs)

target ("war-us" : "creates war") {
   ant.echo(message:"hello") // this compiles and runs, but does nothing.
   println "hello there"  // this does work.
   // ant.war(?)
}

// puts in it wrong dir, and doen't have app version in name, but at least it zips the right content!
target ("zip-source" : "zips sources") {
    ant.delete(file: 'sources.zip')  // dont know how to add this to the clean cycle
    ant.zip(destfile: 'sources.zip', basedir: '..', excludes: "**/*.zip **/target/**  **.idea **/.classpath **/.iml")
}

What I havent figured out:

  1. How to get hold of app.version so it can put put in file names. e.g this: println "creating war for $app.version" does not work
  2. how to build the war. It is not possible to put it in the depdends list, and ant.war("myfile.war") does not work unfortunately. Other strategies might be running this script on the war building event, which is not ideal, as wars are built frequiently without needing this, or perhaps to call "grails war" by calling a shell command.

Update 2 - Can't produce a "prod" war

With help from Ashraf Purno, we have a script (below) which creates a war, zips the sources and tar.gz the liquibase files and produces our package of them. However, it has one major flaw, the war that is created is always the "dev" version, in that when you deploy it to a tomcat, it tires to use the dev datasource, and dev environment. There seems to be no way to change this in the build scirpt, and setting the environment to be prod on the command line which calls the script (e.g. "grails prod myscript") also has no influence - it also produces a dev version of the war (which is of no use)

includeTargets << grailsScript("_GrailsInit")
includeTargets << grailsScript("_GrailsClean")
includeTargets << grailsScript("War")

target(warpack: "Creates war, zips source, tars liquibase scripts") {
    depends(cleanAll, cleanRealyAll, war, "zip-source", "tar-liquibase", "package-all")
}

setDefaultTarget(warpack)

target ("cleanRealyAll" : "Cleans stuff that clean-all wont touch") {
    println "wiping the target dir"
    ant.delete(dir: "target")
    ant.mkdir(dir: "target")
}

target ("zip-source" : "zips sources") {
    println "zipping sources for ${metadata.'app.version'}"

    String zipFile = "target/sources-${metadata.'app.version'}.zip"
    ant.delete(file: zipFile)
    ant.zip(destfile: zipFile, basedir: '..', excludes: "**/*.zip **/target/**  **.idea **/.classpath **/.iml")
}

target ("tar-liquibase":"produces tar of migrations dir") {
    println "tarring liquibase for ${metadata.'app.version'}"

    String tarFile = "target/migrations-${metadata.'app.version'}.tar"
    String gzipfile = "target/migrations-${metadata.'app.version'}.tar.gz"

    ant.tar(destfile:tarFile, basedir: "grails-app/migrations")
    ant.gzip(src: tarFile, destfile : gzipfile )
    ant.delete(file: tarFile)
}

target ("package-all":"puts it all together in one file, relies on externally running 'grails war' first") {
    println "creating package for ${metadata.'app.version'}"

    String packageFile = "target/ourpackage-${metadata.'app.version'}.tar"

    ant.delete(file: packageFile)
    ant.tar (destfile: packageFile, basedir:"target", includes: "*.war *.zip *.gz" )
}
1

1 Answers

2
votes

After a bit googling and peeking through grails core scripts I managed to create a script which does the things you mentioned in your question. Here it is

    import grails.util.Metadata

    includeTargets << grailsScript("_GrailsInit")
    includeTargets << grailsScript("_GrailsClean")
    includeTargets << grailsScript("_GrailsWar")

    target(pack: "Creates war, zips source, tars liquibase scripts") {
        depends(cleanAll, war)

        String appVersion = Metadata.current[Metadata.APPLICATION_VERSION],
               zipFileName = "${basedir}/target/sources-${appVersion}.zip",
               tarFileName = "${basedir}/target/migrations-${appVersion}.tar.gz"

        println "Creating Sources Zip"
        ant.delete(file: zipFileName)
        ant.zip(destfile: zipFileName, basedir: basedir, excludes: "**/target/**  **/.idea/** **/.classpath/** **/.iml/**")

        println "Creating Migrations Tar Ball"
        ant.delete(file: tarFileName)
        ant.tar(destfile: tarFileName, basedir: "${basedir}/grails-app/migrations")
    }

    setDefaultTarget(pack)

I have put all the tasks in a single target just for simplicity. You can divide them in several targets and add them to depends if you want. I have used Grails 2.5.1 for testing this script.

You can take a look here http://mrhaki.blogspot.com/2014/05/grails-goodness-run-groovy-scripts-in.html for some available props/configs in scripts.