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.
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.
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:
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.