You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by jb...@apache.org on 2018/08/31 16:48:49 UTC

[geode] branch develop updated: GEODE-5657: Build job now behaves like test job. (#2399)

This is an automated email from the ASF dual-hosted git repository.

jbarrett pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 00f7603  GEODE-5657: Build job now behaves like test job. (#2399)
00f7603 is described below

commit 00f760371efb535721ca645da7273328b2821d1c
Author: Patrick Rhomberg <pr...@pivotal.io>
AuthorDate: Fri Aug 31 09:48:44 2018 -0700

    GEODE-5657: Build job now behaves like test job. (#2399)
    
    * Build now provisions an external worker, similar to other testing
    jobs.
    * Add execute_build.sh, to be combined with existing execute_tests.sh in
    GEODE-5659.
    * Increase verbosity during testing
    * Correct issue with extra newline in Jinja templating of pipelines
    * Introduce a shared_utilities.sh for bash functions
    * Multiple whitespace adjustments
    * Build artifacts are now tar'd in archive_results.sh
    * * This is achieved with the test env parameter
    TAR_GEODE_BUILD_ARTIFACTS
    * Remove block for sending build-success email, as this is never done
---
 ci/pipelines/geode-build/deploy_pipeline.sh |   2 +-
 ci/pipelines/geode-build/jinja.template.yml | 112 ++++++++++++++++++++--------
 ci/pipelines/shared/jinja.variables.yml     |  13 ++++
 ci/pipelines/shared/shared_jinja.yml        |   2 +-
 ci/scripts/archive_results.sh               |  43 ++++++-----
 ci/scripts/build.sh                         |  63 +++++-----------
 ci/scripts/execute_build.sh                 | 101 +++++++++++++++++++++++++
 ci/scripts/shared_utilities.sh              |  60 +++++++++++++++
 8 files changed, 301 insertions(+), 95 deletions(-)

diff --git a/ci/pipelines/geode-build/deploy_pipeline.sh b/ci/pipelines/geode-build/deploy_pipeline.sh
index a8e4937..49aadfe 100755
--- a/ci/pipelines/geode-build/deploy_pipeline.sh
+++ b/ci/pipelines/geode-build/deploy_pipeline.sh
@@ -33,7 +33,7 @@ for cmd in Jinja2 PyYAML; do
   fi
 done
 
-set -e
+set -ex
 
 if [ -z "${GEODE_BRANCH}" ]; then
   GEODE_BRANCH=$(git rev-parse --abbrev-ref HEAD)
diff --git a/ci/pipelines/geode-build/jinja.template.yml b/ci/pipelines/geode-build/jinja.template.yml
index e94c99d..720c33a 100644
--- a/ci/pipelines/geode-build/jinja.template.yml
+++ b/ci/pipelines/geode-build/jinja.template.yml
@@ -43,7 +43,7 @@ SERVICE_ACCOUNT: ((!concourse-gcp-account))
 groups:
 - name: main
   jobs:
-  - Build
+  - {{ build_test.name }}
   {% for test in (tests + windowstests) if not test.name=="StressNew" -%}
   - {{test.name}}Test
   {% endfor -%}
@@ -51,12 +51,6 @@ groups:
   - PublishArtifacts
 
 resources:
-- name: geode-build-artifact
-  type: gcs-resource
-  source:
-    bucket: ((!public-bucket))
-    json_key: ((!concourse-gcp-key))
-    regexp: artifacts/{{repository.branch}}/geodefiles-(.*).tgz
 - name: send-notification-email
   type: email
   source:
@@ -122,36 +116,55 @@ resource_types:
     repository: pcfseceng/email-resource
 
 jobs:
-- name: Build
+- name: {{build_test.name}}
   public: true
   serial: true
   plan:
-  - get: geode
-    trigger: true
   - get: geode-ci
-  - get: geode-build-version
-    params:
-      pre: build
-  - task: build
-    config:
-      platform: linux
-      image_resource:
-        type: docker-image
-        source:
-          password: ((!docker-password))
-          repository: gcr.io/apachegeode-ci/{{ pipeline_prefix() }}((!docker-image-name))
-          tag: latest
-          username: ((!docker-username))
+  - aggregate:
+    - get: geode
+      trigger: true
+    - get: geode-build-version
       params:
-        MAINTENANCE_VERSION: {{repository.branch}}
-        SOURCE_REPOSITORY: {{repository.branch}}
-        PUBLIC_BUCKET: ((!public-bucket))
-        SERVICE_ACCOUNT: ((!concourse-gcp-account))
+        pre: build
+    - do:
+      - put: concourse-metadata-resource
+      - task: start_instance
+        {{ alpine_tools_config()|indent(8) }}
+          params:
+            CPUS: {{build_test.CPUS}}
+            GEODE_BRANCH: {{repository.branch}}
+            GEODE_FORK: {{repository.fork}}
+            RAM: {{build_test.RAM}}
+          run:
+            path: geode-ci/ci/scripts/start_instance.sh
+          inputs:
+          - name: concourse-metadata-resource
+          - name: geode-ci
+          outputs:
+          - name: instance-data
+        timeout: 15m
+        attempts: 100
+  - task: rsync_code_up
+    {{ alpine_tools_config()|indent(4) }}
       run:
-        path: geode-ci/ci/scripts/build.sh
+        path: geode-ci/ci/scripts/rsync_code_up.sh
       inputs:
+      - name: geode-ci
       - name: geode
+      - name: instance-data
+    timeout: 5m
+  - task: build
+    {{ alpine_tools_config()|indent(4) }}
+      params:
+        GRADLE_TASK: {{ build_test.GRADLE_TASK }}
+        {{ common_test_params(build_test) | indent(8) }}
+      run:
+        path: geode-ci/ci/scripts/execute_build.sh
+      inputs:
       - name: geode-ci
+      - name: geode
+      - name: instance-data
       - name: geode-build-version
       outputs:
       - name: built-geode
@@ -163,13 +176,48 @@ jobs:
           body: results/body
           subject: results/subject
     ensure:
-      aggregate:
-      - put: geode-build-artifact
-        params:
-          file: built-geode/geodefiles-*.tgz
+      do:
+      - task: rsync_code_down
+        {{ alpine_tools_config()|indent(8) }}
+          run:
+            path: geode-ci/ci/scripts/rsync_code_down.sh
+          inputs:
+          - name: geode-ci
+          - name: instance-data
+          outputs:
+          - name: geode-results
+        timeout: 5m
       - put: geode-build-version
         params:
           file: results/number
+      ensure:
+        do:
+        - aggregate:
+          - task: archive_results
+            {{ alpine_tools_config()|indent(12) }}
+              params:
+                ARTIFACT_SLUG: {{build_test.ARTIFACT_SLUG}}
+                GRADLE_TASK: {{build_test.GRADLE_TASK}}
+                MAINTENANCE_VERSION: {{repository.branch}}
+                PUBLIC_BUCKET: ((!public-bucket))
+                SERVICE_ACCOUNT: ((!concourse-gcp-account))
+                TAR_GEODE_BUILD_ARTIFACTS: true
+              run:
+                path: geode-ci/ci/scripts/archive_results.sh
+              inputs:
+              - name: concourse-metadata-resource
+              - name: geode-ci
+              - name: geode-build-version
+              - name: geode-results
+            timeout: 1h
+          - task: stop_instance
+            {{ alpine_tools_config()|indent(12) }}
+              run:
+                path: geode-ci/ci/scripts/stop_instance.sh
+              inputs:
+              - name: geode-ci
+              - name: instance-data
+            timeout: 1h
 
 - name: UpdatePassingRef
   public: true
diff --git a/ci/pipelines/shared/jinja.variables.yml b/ci/pipelines/shared/jinja.variables.yml
index 85d495a..e902678 100644
--- a/ci/pipelines/shared/jinja.variables.yml
+++ b/ci/pipelines/shared/jinja.variables.yml
@@ -24,6 +24,19 @@ platforms:
 - name: "Windows"
   prefix: "Windows"
 
+build_test:
+  name: "Build"
+  CPUS: "8"
+  RAM: "16"
+  ARTIFACT_SLUG: build
+  CALL_STACK_TIMEOUT: "1800"
+  PARALLEL_DUNIT: "false"
+  DUNIT_PARALLEL_FORKS: "4"
+  # Actual gradle task is "build install" but is hard-coded in execute_build.sh
+  # It's consumption is more like a "TEST_RESULTS_DESTINATIONS_DIRECTORY_STUB_THING.
+  GRADLE_TASK: build
+  execute_test_timeout: 10m
+
 tests:
 - name: "Acceptance"
   CPUS: "8"
diff --git a/ci/pipelines/shared/shared_jinja.yml b/ci/pipelines/shared/shared_jinja.yml
index 69fd1a9..309e3ba 100644
--- a/ci/pipelines/shared/shared_jinja.yml
+++ b/ci/pipelines/shared/shared_jinja.yml
@@ -24,7 +24,7 @@
 {%- if repository.fork=="apache" %}
 {%- else -%}
 {{repository.sanitized_fork}}-{{repository.sanitized_branch}}-
-{%- endif %}
+{%- endif -%}
 {%- endmacro %}
 
 {%- macro docker_config(repository_url) %}
diff --git a/ci/scripts/archive_results.sh b/ci/scripts/archive_results.sh
index be6116d..400201a 100755
--- a/ci/scripts/archive_results.sh
+++ b/ci/scripts/archive_results.sh
@@ -17,7 +17,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-set -e
+set -ex
 
 BASE_DIR=$(pwd)
 
@@ -30,6 +30,7 @@ done
 SCRIPTDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
 
 source ${BASE_DIR}/concourse-metadata-resource/concourse_metadata
+source ${SCRIPTDIR}/shared_utilities.sh
 
 BUILDROOT=$(pwd)
 DEST_DIR=${BUILDROOT}/geode-results
@@ -68,7 +69,7 @@ if [ -z ${MAINTENANCE_VERSION+x} ]; then
 fi
 
 if [ -z "${GEODE_PULL_REQUEST_ID}" ]; then
-CONCOURSE_VERSION=$(cat ${GEODE_BUILD_VERSION_FILE})
+  CONCOURSE_VERSION=$(cat ${GEODE_BUILD_VERSION_FILE})
   CONCOURSE_PRODUCT_VERSION=${CONCOURSE_VERSION%%-*}
   GEODE_PRODUCT_VERSION=${GEODE_BUILD_VERSION_NUMBER}
   CONCOURSE_BUILD_SLUG=${CONCOURSE_VERSION##*-}
@@ -95,17 +96,7 @@ gcloud config set account ${SERVICE_ACCOUNT}
 FILENAME=${ARTIFACT_SLUG}-${FULL_PRODUCT_VERSION}.tgz
 
 pushd ${GEODE_BUILD}
-
-  set +e
-  find . -type d -name "reports" > ${directories_file}
-  find . -type d -name "test-results" >> ${directories_file}
-  (find . -type d -name "*Test" | grep "build/[^/]*Test$") >> ${directories_file}
-  find . -name "*-progress*txt" >> ${directories_file}
-  find . -name "*.hprof" >> ${directories_file}
-  find . -type d -name "callstacks" >> ${directories_file}
-  echo "Collecting the following artifacts..."
-  cat ${directories_file}
-  echo ""
+  find-here-test-reports ${directories_file}
   tar zcf ${DEST_DIR}/${FILENAME} -T ${directories_file}
 popd
 
@@ -113,6 +104,15 @@ ARTIFACTS_DESTINATION="${PUBLIC_BUCKET}/builds/${FULL_PRODUCT_VERSION}"
 TEST_RESULTS_DESTINATION="${ARTIFACTS_DESTINATION}/test-results/${SANITIZED_GRADLE_TASK}/${BUILD_TIMESTAMP}/"
 TEST_ARTIFACTS_DESTINATION="${ARTIFACTS_DESTINATION}/test-artifacts/${BUILD_TIMESTAMP}/"
 
+BUILD_ARTIFACTS_FILENAME=geode-build-artifacts-${FULL_PRODUCT_VERSION}.tgz
+BUILD_ARTIFACTS_DESTINATION="${ARTIFACTS_DESTINATION}/${BUILD_ARTIFACTS_FILENAME}"
+
+if [ -n "${TAR_GEODE_BUILD_ARTIFACTS}" ] ; then
+  pushd ${GEODE_BUILD}
+    tar zcf ${DEST_DIR}/${BUILD_ARTIFACTS_FILENAME} .
+    gsutil -q cp ${DEST_DIR}/${BUILD_ARTIFACTS_FILENAME} gs://${BUILD_ARTIFACTS_DESTINATION}
+  popd
+fi
 
 if [ ! -f "${GEODE_BUILD}/build/reports/combined/index.html" ]; then
     echo "No tests exist, compile failed."
@@ -121,17 +121,26 @@ if [ ! -f "${GEODE_BUILD}/build/reports/combined/index.html" ]; then
 fi
 
 pushd ${GEODE_BUILD}/build/reports/combined
-gsutil -q -m cp -r * gs://${TEST_RESULTS_DESTINATION}
+  gsutil -q -m cp -r * gs://${TEST_RESULTS_DESTINATION}
 popd
 
+gsutil cp ${DEST_DIR}/${FILENAME} gs://${TEST_ARTIFACTS_DESTINATION}
+
+set +x
+
+
 echo ""
 printf "\033[92m=-=-=-=-=-=-=-=-=-=-=-=-=-=  Test Results Website =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\033[0m\n"
 printf "\033[92mhttp://${TEST_RESULTS_DESTINATION}\033[0m\n"
 printf "\033[92m=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\033[0m\n"
 printf "\n"
 
-gsutil cp ${DEST_DIR}/${FILENAME} gs://${TEST_ARTIFACTS_DESTINATION}
-
-printf "\033[92mTest artifacts from this job are available at:\033[0m\n"
+printf "\033[92mTest report artifacts from this job are available at:\033[0m\n"
 printf "\n"
 printf "\033[92mhttp://${TEST_ARTIFACTS_DESTINATION}${FILENAME}\033[0m\n"
+
+if [ -n "${TAR_GEODE_BUILD_ARTIFACTS}" ] ; then
+  printf "\033[92mBuild artifacts from this job are available at:\033[0m\n"
+  printf "\n"
+  printf "\033[92mhttp://${BUILD_ARTIFACTS_DESTINATION}\033[0m\n"
+fi
diff --git a/ci/scripts/build.sh b/ci/scripts/build.sh
index e221a39..398a809 100755
--- a/ci/scripts/build.sh
+++ b/ci/scripts/build.sh
@@ -89,46 +89,21 @@ mkdir -p ${BUILD_ARTIFACTS_DIR}
 ln -s ${ROOT_DIR}/geode ${GEODE_BUILD_DIR}
 
 pushd ${GEODE_BUILD_DIR}
-set +e
-set -x
-./gradlew --no-daemon --parallel -PbuildId=${BUILD_ID} --system-prop "java.io.tmpdir=${TMPDIR}" \
-  -PsourceRevision="$(git rev-parse HEAD)" -PsourceRepository="${SOURCE_REPOSITORY}" build install
-GRADLE_EXIT_STATUS=$?
-set +x
-set -e
-
+  set +e
+  set -x
+    ./gradlew --no-daemon --parallel -PbuildId=${BUILD_ID} --system-prop "java.io.tmpdir=${TMPDIR}" \
+      -PsourceRevision="$(git rev-parse HEAD)" -PsourceRepository="${SOURCE_REPOSITORY}" build install
+    GRADLE_EXIT_STATUS=$?
+  set +x
+  set -e
 popd
+
 ARTIFACTS_DESTINATION="${PUBLIC_BUCKET}/builds/${FULL_PRODUCT_VERSION}"
 TEST_RESULTS_DESTINATION="${ARTIFACTS_DESTINATION}/test-results/build/"
 FULL_BUILD_ARCHIVE_DESTINATION="${ARTIFACTS_DESTINATION}/geodefiles-${FULL_PRODUCT_VERSION}.tgz"
 BUILD_ARTIFACTS_FILENAME=geode-build-artifacts-${FULL_PRODUCT_VERSION}.tgz
 BUILD_ARTIFACTS_DESTINATION="${ARTIFACTS_DESTINATION}/${BUILD_ARTIFACTS_FILENAME}"
 
-function sendSuccessfulJobEmail {
-  echo "Sending job success email"
-
-  cat <<EOF >${EMAIL_SUBJECT}
-Build for version ${FULL_PRODUCT_VERSION} of Apache Geode succeeded.
-EOF
-
-  cat <<EOF >${EMAIL_BODY}
-=================================================================================================
-
-The build job for Apache Geode version ${FULL_PRODUCT_VERSION} has completed successfully.
-
-
-Build artifacts are available at:
-http://${BUILD_ARTIFACTS_DESTINATION}
-
-Test results are available at:
-http://${TEST_RESULTS_DESTINATION}
-
-
-=================================================================================================
-EOF
-
-}
-
 function sendFailureJobEmail {
   echo "Sending job failure email"
 
@@ -163,7 +138,7 @@ if [ ! -d "geode/build/reports/combined" ]; then
 fi
 
 pushd geode/build/reports/combined
-gsutil -q -m cp -r * gs://${TEST_RESULTS_DESTINATION}
+  gsutil -q -m cp -r * gs://${TEST_RESULTS_DESTINATION}
 popd
 
 echo ""
@@ -174,6 +149,7 @@ printf "\n"
 
 tar zcf ${DEST_DIR}/geodefiles-${FULL_PRODUCT_VERSION}.tgz geode
 gsutil cp ${DEST_DIR}/geodefiles-${FULL_PRODUCT_VERSION}.tgz gs://${FULL_BUILD_ARCHIVE_DESTINATION}
+
 cp -r geode/geode-assembly/build/distributions ${BUILD_ARTIFACTS_DIR}/
 cp -r geode/build/reports/rat ${BUILD_ARTIFACTS_DIR}/
 cp -r geode/build/reports/combined ${BUILD_ARTIFACTS_DIR}/
@@ -181,25 +157,24 @@ cp -r geode/build/reports/combined ${BUILD_ARTIFACTS_DIR}/
 directories_file=${DEST_DIR}/artifact_directories
 
 pushd geode
-find . -name "*-progress*txt" >> ${directories_file}
-echo "Collecting the following artifacts..."
-cat ${directories_file}
-echo ""
-mkdir -p ${BUILD_ARTIFACTS_DIR}/progress
-tar cf - -T ${directories_file} | (cd ${BUILD_ARTIFACTS_DIR}/progress; tar xpf -)
+  find . -name "*-progress*txt" >> ${directories_file}
+  echo "Collecting the following artifacts..."
+  cat ${directories_file}
+  echo ""
+  mkdir -p ${BUILD_ARTIFACTS_DIR}/progress
+  tar cf - -T ${directories_file} | (cd ${BUILD_ARTIFACTS_DIR}/progress; tar xpf -)
 popd
 
 pushd ${BUILD_ARTIFACTS_DIR}
-tar zcf ${DEST_DIR}/${BUILD_ARTIFACTS_FILENAME} .
+  tar zcf ${DEST_DIR}/${BUILD_ARTIFACTS_FILENAME} .
 popd
+
 gsutil -q cp ${DEST_DIR}/${BUILD_ARTIFACTS_FILENAME} gs://${BUILD_ARTIFACTS_DESTINATION}
 printf "\033[92mBuild artifacts from this job are available at:\033[0m\n"
 printf "\n"
 printf "\033[92mhttp://${BUILD_ARTIFACTS_DESTINATION}\033[0m\n"
 
-if [ ${GRADLE_EXIT_STATUS} -eq 0 ]; then
-    sendSuccessfulJobEmail
-else
+if [ ${GRADLE_EXIT_STATUS} -ne 0 ]; then
     sendFailureJobEmail
 fi
 
diff --git a/ci/scripts/execute_build.sh b/ci/scripts/execute_build.sh
new file mode 100755
index 0000000..e2a45d2
--- /dev/null
+++ b/ci/scripts/execute_build.sh
@@ -0,0 +1,101 @@
+#!/usr/bin/env bash
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+BASE_DIR=$(pwd)
+
+SOURCE="${BASH_SOURCE[0]}"
+while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
+  SCRIPTDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
+  SOURCE="$(readlink "$SOURCE")"
+  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
+done
+SCRIPTDIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
+
+if [[ -z "${GRADLE_TASK}" ]]; then
+  echo "GRADLE_TASK must be set. exiting..."
+  exit 1
+fi
+
+ROOT_DIR=$(pwd)
+BUILD_DATE=$(date +%s)
+EMAIL_SUBJECT="results/subject"
+EMAIL_BODY="results/body"
+
+GEODE_BUILD_VERSION_FILE=${ROOT_DIR}/geode-build-version/number
+GEODE_RESULTS_VERSION_FILE=${ROOT_DIR}/results/number
+GEODE_BUILD_VERSION_NUMBER=$(grep "versionNumber *=" geode/gradle.properties | awk -F "=" '{print $2}' | tr -d ' ')
+GEODE_BUILD_DIR=/tmp/geode-build
+GEODE_PULL_REQUEST_ID_FILE=${ROOT_DIR}/geode/.git/id
+
+if [ -e "${GEODE_PULL_REQUEST_ID_FILE}" ]; then
+  GEODE_PULL_REQUEST_ID=$(cat ${GEODE_PULL_REQUEST_ID_FILE})
+  FULL_PRODUCT_VERSION="geode-pr-${GEODE_PULL_REQUEST_ID}"
+else
+  CONCOURSE_VERSION=$(cat ${GEODE_BUILD_VERSION_FILE})
+  CONCOURSE_PRODUCT_VERSION=${CONCOURSE_VERSION%%-*}
+  GEODE_PRODUCT_VERSION=${GEODE_BUILD_VERSION_NUMBER}
+  CONCOURSE_BUILD_SLUG=${CONCOURSE_VERSION##*-}
+  BUILD_ID=${CONCOURSE_VERSION##*.}
+  FULL_PRODUCT_VERSION=${GEODE_PRODUCT_VERSION}-${CONCOURSE_BUILD_SLUG}
+  echo "Concourse VERSION is ${CONCOURSE_VERSION}"
+  echo "Geode product VERSION is ${GEODE_PRODUCT_VERSION}"
+  echo "Build ID is ${BUILD_ID}"
+fi
+
+echo -n "${FULL_PRODUCT_VERSION}" > ${GEODE_RESULTS_VERSION_FILE}
+
+DEFAULT_GRADLE_TASK_OPTIONS="--parallel --console=plain --no-daemon"
+
+SSHKEY_FILE="instance-data/sshkey"
+
+INSTANCE_NAME="$(cat instance-data/instance-name)"
+INSTANCE_IP_ADDRESS="$(cat instance-data/instance-ip-address)"
+PROJECT="$(cat instance-data/project)"
+ZONE="$(cat instance-data/zone)"
+
+
+echo 'StrictHostKeyChecking no' >> /etc/ssh/ssh_config
+
+scp -i ${SSHKEY_FILE} ${SCRIPTDIR}/capture-call-stacks.sh geode@${INSTANCE_IP_ADDRESS}:.
+
+
+
+if [[ -n "${PARALLEL_DUNIT}" && "${PARALLEL_DUNIT}" == "true" ]]; then
+  PARALLEL_DUNIT="-PparallelDunit -PdunitDockerUser=geode"
+  if [ -n "${DUNIT_PARALLEL_FORKS}" ]; then
+    DUNIT_PARALLEL_FORKS="-PdunitParallelForks=${DUNIT_PARALLEL_FORKS}"
+  fi
+else
+  PARALLEL_DUNIT=""
+  DUNIT_PARALLEL_FORKS=""
+fi
+
+
+if [ -v CALL_STACK_TIMEOUT ]; then
+  ssh -i ${SSHKEY_FILE} geode@${INSTANCE_IP_ADDRESS} "tmux new-session -d -s callstacks; tmux send-keys  ~/capture-call-stacks.sh\ ${PARALLEL_DUNIT}\ ${CALL_STACK_TIMEOUT} C-m"
+fi
+
+GRADLE_COMMAND="./gradlew \
+    ${DEFAULT_GRADLE_TASK_OPTIONS} \
+    build install"
+
+echo "${GRADLE_COMMAND}"
+ssh -i ${SSHKEY_FILE} geode@${INSTANCE_IP_ADDRESS} "mkdir -p tmp && cd geode && ${GRADLE_COMMAND}"
diff --git a/ci/scripts/shared_utilities.sh b/ci/scripts/shared_utilities.sh
new file mode 100644
index 0000000..d1a3326
--- /dev/null
+++ b/ci/scripts/shared_utilities.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+find-here-test-reports() {
+  output_directories_file=${1}
+  set +e
+  find . -type d -name "reports" > ${output_directories_file}
+  find .  -type d -name "test-results" >> ${output_directories_file}
+  (find . -type d -name "*Test" | grep "build/[^/]*Test$") >> ${output_directories_file}
+  find . -name "*-progress*txt" >> ${output_directories_file}
+  find . -name "*.hprof" >> ${output_directories_file}
+  find . -type d -name "callstacks" >> ${output_directories_file}
+  echo "Collecting the following artifacts..."
+  cat ${output_directories_file}
+  echo ""
+}
+
+
+
+function sendFailureJobEmail {
+  echo "Sending job failure email"
+
+  cat <<EOF >${EMAIL_SUBJECT}
+Build for version ${FULL_PRODUCT_VERSION} of Apache Geode failed.
+EOF
+
+  cat <<EOF >${EMAIL_BODY}
+=================================================================================================
+
+The build job for Apache Geode version ${FULL_PRODUCT_VERSION} has failed.
+
+
+Build artifacts are available at:
+http://${BUILD_ARTIFACTS_DESTINATION}
+
+Test results are available at:
+http://${TEST_RESULTS_DESTINATION}
+
+
+Job: \${ATC_EXTERNAL_URL}/teams/\${BUILD_TEAM_NAME}/pipelines/\${BUILD_PIPELINE_NAME}/jobs/\${BUILD_JOB_NAME}/builds/\${BUILD_NAME}
+
+=================================================================================================
+EOF
+
+}
\ No newline at end of file