diff --git a/buildscripts/kokoro/gae-interop.sh b/buildscripts/kokoro/gae-interop.sh
index 2665f36a0d..6ea604e74d 100755
--- a/buildscripts/kokoro/gae-interop.sh
+++ b/buildscripts/kokoro/gae-interop.sh
@@ -1,3 +1,68 @@
-#!/bin/sh
+#!/bin/bash
-# An empty placeholder shellscript
+set -exu -o pipefail
+
+KOKORO_GAE_SERVICE="java-gae-interop-test"
+
+# We deploy as different versions of a single service, this way any stale
+# lingering deploys can be easily cleaned up by purging all running versions
+# of this service.
+KOKORO_GAE_APP_VERSION=$(hostname)
+
+# A dummy version that can be the recipient of all traffic, so that the kokoro test version can be
+# set to 0 traffic. This is a requirement in order to delete it.
+DUMMY_DEFAULT_VERSION='dummy-default'
+
+function cleanup() {
+ echo "Performing cleanup now."
+ gcloud app services set-traffic $KOKORO_GAE_SERVICE --quiet --splits $DUMMY_DEFAULT_VERSION=1.0
+ gcloud app services delete $KOKORO_GAE_SERVICE --version $KOKORO_GAE_APP_VERSION --quiet
+}
+trap cleanup SIGHUP SIGINT SIGTERM EXIT
+
+cd ./github/grpc-java
+
+##
+## Deploy the dummy 'default' version of the service
+##
+echo "
+
+ true
+ $KOKORO_GAE_SERVICE
+ java8
+
+" > ./gae-interop-testing/gae-jdk8/src/main/webapp/WEB-INF/appengine-web.xml
+cat ./gae-interop-testing/gae-jdk8/src/main/webapp/WEB-INF/appengine-web.xml
+# Deploy the dummy 'default' version. It doesn't matter if we race with other kokoro runs.
+# We only require that it exists when cleanup() is called.
+if [[ $(gcloud app versions describe $DUMMY_DEFAULT_VERSION --service=$KOKORO_GAE_SERVICE) != 0 ]]; then
+ ./gradlew --stacktrace -DgaeDeployVersion=$DUMMY_DEFAULT_VERSION -DgaeStopPreviousVersion=false -DgaePromote=false -PskipCodegen=true :grpc-gae-interop-testing-jdk8:appengineDeploy
+fi
+
+##
+## Begin JDK8 test
+##
+echo "
+
+ true
+ $KOKORO_GAE_SERVICE
+ java8
+
+" > ./gae-interop-testing/gae-jdk8/src/main/webapp/WEB-INF/appengine-web.xml
+cat ./gae-interop-testing/gae-jdk8/src/main/webapp/WEB-INF/appengine-web.xml
+# Deploy and test the real app (jdk8)
+./gradlew --stacktrace -DgaeDeployVersion=$KOKORO_GAE_APP_VERSION -DgaeStopPreviousVersion=false -DgaePromote=false -PskipCodegen=true :grpc-gae-interop-testing-jdk8:runInteropTestRemote
+
+##
+## Begin JDK7 test
+##
+echo "
+
+ true
+ $KOKORO_GAE_SERVICE
+ java7
+
+" > ./gae-interop-testing/gae-jdk7/src/main/webapp/WEB-INF/appengine-web.xml
+cat ./gae-interop-testing/gae-jdk7/src/main/webapp/WEB-INF/appengine-web.xml
+# Deploy and test the real app (jdk7)
+./gradlew --stacktrace -DgaeDeployVersion=$KOKORO_GAE_APP_VERSION -DgaeStopPreviousVersion=false -DgaePromote=false -PskipCodegen=true :grpc-gae-interop-testing-jdk7:runInteropTestRemote
diff --git a/gae-interop-testing/gae-jdk7/build.gradle b/gae-interop-testing/gae-jdk7/build.gradle
index e13578fa20..902eece88e 100644
--- a/gae-interop-testing/gae-jdk7/build.gradle
+++ b/gae-interop-testing/gae-jdk7/build.gradle
@@ -55,8 +55,12 @@ appengine { // App Engine tasks configuration
}
deploy { // deploy configuration
- stopPreviousVersion = true // default - stop the current version
- promote = true // default - & make this the current version
+ // default - stop the current version
+ stopPreviousVersion = System.getProperty('gaeStopPreviousVersion') ?: true
+ // default - make this the current version
+ promote = System.getProperty('gaePromote') ?: true
+ // Use -DgaeDeployVersion if set, otherwise the version is null and the plugin will generate it
+ version = System.getProperty('gaeDeployVersion')
}
}
// [END model]
@@ -67,7 +71,8 @@ version = '1.0-SNAPSHOT' // Version in generated output
sourceCompatibility = 1.7
targetCompatibility = 1.7
-def getAppName() {
+/** Returns the service name. */
+String getGaeProject() {
def stream = new ByteArrayOutputStream()
exec {
executable 'gcloud'
@@ -77,21 +82,49 @@ def getAppName() {
return stream.toString().trim()
}
+String getService(java.nio.file.Path projectPath) {
+ Node xml = new XmlParser().parse(projectPath.resolve("src/main/webapp/WEB-INF/appengine-web.xml").toFile())
+ if (xml.service.isEmpty()) {
+ return null
+ } else {
+ return xml.service.text()
+ }
+}
+
+String getAppUrl(String project, String service, String version) {
+ if (version != null && service != null) {
+ return "http://${version}.${service}.${project}.appspot.com"
+ } else {
+ return "http://${project}.appspot.com"
+ }
+}
+
task runInteropTestRemote(dependsOn: 'appengineDeploy') {
doLast {
// give remote app some time to settle down
- sleep(5000)
+ sleep(20000)
- def appName = getAppName()
+ def appUrl = getAppUrl(
+ getGaeProject(),
+ getService(project.getProjectDir().toPath()),
+ System.getProperty('gaeDeployVersion'))
+ logger.log(LogLevel.INFO, "the appURL=" + appUrl)
def client = new com.squareup.okhttp.OkHttpClient()
// The test suite can take a while to run
client.setReadTimeout(3, java.util.concurrent.TimeUnit.MINUTES)
- // The '?jdk7' argument is ignored by the server, it exists only to tag the request log entry
- def request = new com.squareup.okhttp.Request.Builder()
- .url("http://${appName}.appspot.com/?jdk7").build()
- def result = client.newCall(request).execute()
- if (result.code() != 200) {
- throw new GradleException("Interop test failed: " + result.body().string())
+ // The '?jdk8' argument is ignored by the server, it exists only to tag the request log entry
+ def interopRequest = new com.squareup.okhttp.Request.Builder()
+ .url("${appUrl}/?jdk7").build()
+
+ // Retry in case GAE is slow and times out
+ int maxRetries = 5
+ def result = null
+ for (int attempt = 0; attempt < maxRetries; attempt++) {
+ result = client.newCall(interopRequest).execute()
+ if (result.code() == 200) {
+ return
+ }
}
+ throw new GradleException("Interop test failed: " + result?.body()?.string())
}
}
diff --git a/gae-interop-testing/gae-jdk8/build.gradle b/gae-interop-testing/gae-jdk8/build.gradle
index 9fa34116e1..a24b4c720f 100644
--- a/gae-interop-testing/gae-jdk8/build.gradle
+++ b/gae-interop-testing/gae-jdk8/build.gradle
@@ -56,8 +56,12 @@ appengine { // App Engine tasks configuration
}
deploy { // deploy configuration
- stopPreviousVersion = true // default - stop the current version
- promote = true // default - & make this the current version
+ // default - stop the current version
+ stopPreviousVersion = System.getProperty('gaeStopPreviousVersion') ?: true
+ // default - make this the current version
+ promote = System.getProperty('gaePromote') ?: true
+ // Use -DgaeDeployVersion if set, otherwise the version is null and the plugin will generate it
+ version = System.getProperty('gaeDeployVersion')
}
}
// [END model]
@@ -68,7 +72,8 @@ version = '1.0-SNAPSHOT' // Version in generated output
sourceCompatibility = 1.8
targetCompatibility = 1.8
-def getAppName() {
+/** Returns the service name. */
+String getGaeProject() {
def stream = new ByteArrayOutputStream()
exec {
executable 'gcloud'
@@ -78,17 +83,38 @@ def getAppName() {
return stream.toString().trim()
}
+String getService(java.nio.file.Path projectPath) {
+ Node xml = new XmlParser().parse(projectPath.resolve("src/main/webapp/WEB-INF/appengine-web.xml").toFile())
+ if (xml.service.isEmpty()) {
+ return null
+ } else {
+ return xml.service.text()
+ }
+}
+
+String getAppUrl(String project, String service, String version) {
+ if (version != null && service != null) {
+ return "http://${version}.${service}.${project}.appspot.com"
+ } else {
+ return "http://${project}.appspot.com"
+ }
+}
+
task runInteropTestRemote(dependsOn: 'appengineDeploy') {
doLast {
// give remote app some time to settle down
- sleep(5000)
+ sleep(20000)
- def appName = getAppName()
+ def appUrl = getAppUrl(
+ getGaeProject(),
+ getService(project.getProjectDir().toPath()),
+ System.getProperty('gaeDeployVersion'))
+ logger.log(LogLevel.INFO, "the appURL=" + appUrl)
def client = new com.squareup.okhttp.OkHttpClient()
// The '?jdk8' argument is ignored by the server, it exists only to tag the request log entry
client.setReadTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
def request = new com.squareup.okhttp.Request.Builder()
- .url("http://${appName}.appspot.com/long_lived_channel?jdk8").build()
+ .url("${appUrl}/long_lived_channel?jdk8").build()
def result1 = client.newCall(request).execute()
def result2 = client.newCall(request).execute()
if (result1.code() != 200 || result2.code() != 200) {
@@ -99,10 +125,17 @@ task runInteropTestRemote(dependsOn: 'appengineDeploy') {
client.setReadTimeout(3, java.util.concurrent.TimeUnit.MINUTES)
// The '?jdk8' argument is ignored by the server, it exists only to tag the request log entry
def interopRequest = new com.squareup.okhttp.Request.Builder()
- .url("http://${appName}.appspot.com/?jdk8").build()
- def result = client.newCall(interopRequest).execute()
- if (result.code() != 200) {
- throw new GradleException("Interop test failed: " + result.body().string())
+ .url("${appUrl}/?jdk8").build()
+
+ // Retry in case GAE is slow and times out
+ int maxRetries = 5
+ def result = null
+ for (int attempt = 0; attempt < maxRetries; attempt++) {
+ result = client.newCall(interopRequest).execute()
+ if (result.code() == 200) {
+ return
+ }
}
+ throw new GradleException("Interop test failed: " + result?.body()?.string())
}
}