I haven’t had much success with finding useful deployment strategies and/or scripts for Grails anywhere. The extent of the documentation I’ve been able locate for deployment simply tells you to create a WAR and upload it to the servlet container.
Not terribly helpful if you want to run a formal process.
So, for my Grails webapps, I came up with this. I create a file in the “gradle” directory named “deploy.gradle” containing the following:
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
buildscript { repositories { jcenter() } dependencies { classpath 'org.hidetake:gradle-ssh-plugin:2.9.0' } } apply plugin: 'org.hidetake.ssh' // the below is in it's own ext block because it can potentially be // overridden by .deployrc.gradle in the user's home directory, and the scmUser // might be required in the following ext block (where the repository is // set up) ext { scmUser = project.hasProperty('user') ? project.getProperty('user') : System.properties['user.name'] } // please note that the file must end in ".gradle" or Gradle won't know how // to process it, and you'll get a "String index out of bounds: 0" error def rcFile = new File("${System.properties['user.home']}/.deployrc.gradle") if (rcFile.exists()) { apply from: rcFile.absolutePath } ext { timeNow = new Date().format('yyyyMMddHHmmss') // TODO: the below should use a repository directly associated with the individual user scmRepository = "${project.scmUser}@my.site:/var/repos/${project.name}.git" runEnvironment = project.hasProperty('env') ? project.getProperty('env') : 'production' scmBranch = project.hasProperty('branch') ? project.getProperty('branch') : 'master' tmpDir = System.getProperty('java.io.tmpdir') + "${project.name}/${timeNow}" } apply from: "${project.projectDir}/gradle/deploy/${project.runEnvironment}.gradle" task deploy { group 'Remote Deployment' description 'Deploys a branch from your SCM to a target environment on a remote server' doLast { println "Deploying from branch ${project.scmBranch} to environment ${project.runEnvironment}" ssh.run { session(remotes.role('webserver')) { // upload the WAR to the target server(s) println 'Uploading WAR file' put from: "${project.buildDir}/libs/mercury.war", into: "mercury/mercury-${timeNow}.war" // stop Tomcat so we can get this party started println 'Stopping Tomcat' execute 'sudo service tomcat8 stop' // if a pre-existing link exists to "current", remove it println 'Symlinking' execute 'if [ -f mercury/mercury-current.war ]; then rm mercury/mercury-current.war; fi' // link our new WAR to the name "current" execute "cd mercury; ln -s mercury-${timeNow}.war mercury-current.war" // Tomcat doesn't clean up extracted WAR file directories, so we must flush out the /var/lib/tomcat8/webapps directory execute 'if [ -d /var/lib/tomcat8/mercury ]; then sudo rm -rf /var/lib/tomcat8/mercury; fi' // Fire tomcat back up println 'Starting Tomcat' execute 'sudo service tomcat8 start' } } } } task deployBuild << { println "Building WAR for ${project.runEnvironment} environment" exec { workingDir project.tmpDir environment 'TERM', 'dumb' // this prevents grails+gradle for displaying a second progress bar during the following invocation commandLine 'grails', "-Dgrails.env=${project.runEnvironment}", 'war', 'mercury.war' } } task deployCheckout << { println "Cloning ${project.scmRepository}#${project.scmBranch} for user ${project.scmUser} into ${project.tmpDir}" exec { commandLine 'git', 'clone', '-b', project.scmBranch, project.scmRepository, project.tmpDir } } task deployCleanup << { println "Removing temporary directory ${project.tmpDir}" exec { commandLine 'rm', '-rf', project.tmpDir } } deployBuild.dependsOn deployCheckout deploy.dependsOn deployBuild deploy.finalizedBy deployCleanup |
Also in the “gradle” directory is a subdirectory named “deploy” where I have the files specific to the environments to which I can deploy, such as “staging.gradle”:
1 2 3 4 5 6 7 8 |
remotes { web { role 'webserver' host = 'my.site' user = 'webapps' identity = file("${System.properties['user.home']}/.ssh/webapps") } } |
Using the script above, I can deploy a particular branch from within my git repository to a specific environment thus:
1 |
gradle -Penv=staging -Pbranch=hotfix/1.2.3.001 deploy |
It’s probably not perfect, but since I’m new to Gradle and Grails, I think it’s a pretty good start!