Multiple environment deployment

This recipe shows how to add SSH deployment to the build.gradle to build and deploy your application to your dev, staging or production environments.

This is a companion recipe to the Ubuntu provisioning script found here.

This example has 4 environments that the application can be deployed to:

  • Local
  • Dev
  • Staging
  • Prod

Go to your project Deployment Settings and generate a context.xml and web.xml.

image

Locate the folder where the war-context.xml was created and make copies for each environment you are deploying to. In this example, I have dev-war-context.xml, staging-war-context.xml and prod-war-context.xml. Each of these will be modified to point to the appropriate database and database server.

You need to add a dependency for the Gradle SSH plugin “org.hidetake:gradle-ssh-plugin:2.9.0” to the build script dependencies.

image

Add the following Gradle script at the end of your build.gradle:

def buildWarCommonConfiguration = {
    appHome = '${catalina.base}/work'
    singleWar = true
    includeContextXml = true
    includeJdbcDriver = true
    webXmlPath = 'modules/web/web/WEB-INF/single-war-web.xml'
    appProperties = [
        'cuba.automaticDatabaseUpdate': true,
        'cuba.webPort': 443,
        'cuba.logDir': '/opt/tomcat/logs/',
        'cuba.web.loginDialogDefaultUser': '',
        'cuba.web.loginDialogDefaultPassword': '',
        'reporting.openoffice.path': '/usr/lib/libreoffice/program',
        'reporting.displayDeviceUnavailable': true
    ]
}

remotes {
    local {
        host = 'ubuntu.local'
        port = 9922
        user = 'myusername'
		password = 'myuserpassword'
        knownHosts = allowAnyHosts
    }

    dev {
        host = 'dev.myserver.com'
        port = 9922
        user = 'myusername'
        identity = file("${System.properties['user.home']}/.ssh/id_rsa")
    }

    staging {
        host = 'staging.myserver.com'
        port = 9922
        user = 'myusername'
        identity = file("${System.properties['user.home']}/.ssh/id_rsa")
    }

    prod {
        host = 'prod.myserver.com'
        port = 9922
        user = 'myusername'
        identity = file("${System.properties['user.home']}/.ssh/id_rsa")
    }
}

def copyToHost(destination) {
    println ':Copying war to: ' + destination.host
    ssh.run {
        session(destination) {
            #put from: 'build/distributions/war/app.war', into: '.'
            #execute 'sudo mv ./app.war /opt/tomcat/webapps'
            put from: 'build/distributions/war/ROOT.war', into: '.'
            execute 'sudo mv ./ROOT.war /opt/tomcat/webapps'
        }
    }
}

task deployWarLocal(type: CubaWarBuilding) {
    configure buildWarCommonConfiguration
    coreContextXmlPath = 'modules/core/web/META-INF/dev-war-context.xml'
    appProperties['cuba.webHostName'] = 'ubuntu.local'
    appProperties['app.environment'] = 'DEV'
    doLast {
        copyToHost(remotes.local)
    }
}

task deployWarDev(type: CubaWarBuilding) {
    configure buildWarCommonConfiguration
    coreContextXmlPath = 'modules/core/web/META-INF/dev-war-context.xml'
    appProperties['cuba.webHostName'] = 'dev.mydomain.com'
    appProperties['app.environment'] = 'DEV'
    doLast {
        copyToHost(remotes.dev)
    }
}

task deployWarStaging(type: CubaWarBuilding) {
    configure buildWarCommonConfiguration
    coreContextXmlPath = 'modules/core/web/META-INF/staging-war-context.xml'
    appProperties['cuba.webHostName'] = 'staging.mydomain.com'
    appProperties['cuba.web.productionMode'] = true
    appProperties['app.environment'] = 'STAGING'
    doLast {
        copyToHost(remotes.staging)
    }
}

task deployWarProd(type: CubaWarBuilding) {
    configure buildWarCommonConfiguration
    coreContextXmlPath = 'modules/core/web/META-INF/prod-war-context.xml'
    appProperties['cuba.webHostName'] = 'www.mydomain.com'
    appProperties['cuba.web.productionMode'] = true
    appProperties['cuba.automaticDatabaseUpdate'] = false
    doLast {
        copyToHost(remotes.prod)
    }
}

To deploy the app, open a console or IntelliJ terminal and execute “gradlew deployWar{Site}”. {Site} being Local, Dev, Staging or Prod. For example:

image

Notes:

  • Windows is challenging for SSH as the various clients tend to put the .ssh folder in different locations. I use the Git Shell that comes with the Git Hub distribution. This includes the msys ssh client which creates the .ssh folder in the correct location.
  • knownHosts = allowAnyHosts should only be used for trusted hosts. I included as windows can be difficult when adding a host to %USERPROFILE%.ssh\known_hosts.
  • I implement a modified main window that uses the app.environment to display the environment currently logged in to. This is to stop end users from mistakenly entering production data into the wrong system as I copy the production database to staging for QA.
3 Likes