|  | #!/bin/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. | 
|  |  | 
|  | # This loop reads the arguments passed to the script, parses them, and exports them as environment variables. | 
|  | for ARGUMENT in "$@" | 
|  | do | 
|  | KEY=$(echo $ARGUMENT | cut -f1 -d=) | 
|  |  | 
|  | KEY_LENGTH=${#KEY} | 
|  | VALUE="${ARGUMENT:$KEY_LENGTH+1}" | 
|  | export "$KEY"="$VALUE" | 
|  | done | 
|  |  | 
|  | # This block sets default values for several environment variables to run CD script. | 
|  | export ORIGIN=${ORIGIN-"PG_EXAMPLES"} | 
|  | export SUBDIRS=${SUBDIRS-"./learning/katas ./examples ./sdks"} | 
|  | export BEAM_ROOT_DIR=${BEAM_ROOT_DIR-"/workspace/beam"} | 
|  | export PROJECT_ID=${PROJECT_ID} | 
|  | export SDK_CONFIG=${SDK_CONFIG-"$BEAM_ROOT_DIR/playground/sdks.yaml"} | 
|  | export BEAM_EXAMPLE_CATEGORIES=${BEAM_EXAMPLE_CATEGORIES-"$BEAM_ROOT_DIR/playground/categories.yaml"} | 
|  | export BEAM_USE_WEBGRPC=${BEAM_USE_WEBGRPC-"yes"} | 
|  | export BEAM_CONCURRENCY=${BEAM_CONCURRENCY-2} | 
|  | export SDKS=${SDKS-"java python go"} | 
|  | export FORCE_CD=${FORCE_CD-'false'} | 
|  |  | 
|  | # Playground FQDN | 
|  | if [[ -z "${DNS_NAME}" ]]; then | 
|  | echo "DNS_NAME is empty or not set. Exiting" | 
|  | exit 1 | 
|  | fi | 
|  | # GCP Datastore namespace to load examples to | 
|  | if [[ -z "${DATASTORE_NAMESPACE}" ]]; then | 
|  | echo "DATASTORE_NAMESPACE parameter was not set. Exiting" | 
|  | exit 1 | 
|  | fi | 
|  | # Master branch commit after merge | 
|  | if [[ -z "${MERGE_COMMIT}" ]]; then | 
|  | echo "MERGE_COMMIT paramter was not set. Exiting" | 
|  | exit 1 | 
|  | fi | 
|  | if [[ "${FORCE_CD}" != "false" &&  "${FORCE_CD}" != "true" ]]; then | 
|  | echo "FORCE_CD parameter must be either 'true' or 'false'. Exiting" | 
|  | exit 1 | 
|  | fi | 
|  |  | 
|  | # Constants | 
|  | export STEP=CD | 
|  |  | 
|  | # This function logs the given message to a file and outputs it to the console. | 
|  | function LogOutput () | 
|  | { | 
|  | # CDLOG keyword to simplify search over the global log | 
|  | echo "CDLOG $(date --utc '+%D %T') $1" | 
|  | } | 
|  |  | 
|  | LogOutput "Input variables: | 
|  | ORIGIN=$ORIGIN | 
|  | STEP=${STEP} | 
|  | SUBDIRS=$SUBDIRS | 
|  | BEAM_ROOT_DIR=$BEAM_ROOT_DIR | 
|  | PROJECT_ID=$PROJECT_ID | 
|  | SDK_CONFIG=$SDK_CONFIG | 
|  | BEAM_EXAMPLE_CATEGORIES=$BEAM_EXAMPLE_CATEGORIES | 
|  | BEAM_CONCURRENCY=$BEAM_CONCURRENCY | 
|  | SDKS=$SDKS | 
|  | MERGE_COMMIT=$MERGE_COMMIT | 
|  | DNS_NAME=$DNS_NAME | 
|  | BEAM_USE_WEBGRPC=$BEAM_USE_WEBGRPC | 
|  | DATASTORE_NAMESPACE=$DATASTORE_NAMESPACE | 
|  | FORCE_CD=$FORCE_CD" | 
|  |  | 
|  |  | 
|  | # Script starts in a clean environment in Cloud Build. Set minimal required environment variables | 
|  | if [ -z "$PATH" ]; then | 
|  | export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin/:/usr/bin:/sbin:/bin" | 
|  | fi | 
|  | if [ -z "$HOME" ]; then | 
|  | export HOME="/builder/home" | 
|  | fi | 
|  |  | 
|  | LogOutput "Installing python and dependencies." | 
|  | # set -e  # Exit immediately if any command fails | 
|  | export DEBIAN_FRONTEND=noninteractive | 
|  | apt install -y apt-transport-https ca-certificates software-properties-common curl unzip apt-utils > /dev/null 2>&1 | 
|  | add-apt-repository -y ppa:deadsnakes/ppa > /dev/null 2>&1 && apt update > /dev/null 2>&1 | 
|  | apt install -y python3.8 python3.8-distutils python3-pip > /dev/null 2>&1 | 
|  | apt install -y --reinstall python3.8-distutils > /dev/null 2>&1 | 
|  | pip install --upgrade google-api-python-client > /dev/null 2>&1 | 
|  | python3.8 -m pip install pip --upgrade > /dev/null 2>&1 | 
|  | ln -s /usr/bin/python3.8 /usr/bin/python > /dev/null 2>&1 | 
|  | apt install -y python3.8-venv > /dev/null 2>&1 | 
|  |  | 
|  | LogOutput "Installing Python packages from beam/playground/infrastructure/requirements.txt" | 
|  | cd $BEAM_ROOT_DIR | 
|  | pip install -r playground/infrastructure/requirements.txt | 
|  |  | 
|  | LogOutput "Looking for files changed by the merge commit $MERGE_COMMIT" | 
|  | git fetch origin $MERGE_COMMIT | 
|  | diff_log=$(git diff --name-only $MERGE_COMMIT~ $MERGE_COMMIT) | 
|  | diff=($(echo "$diff_log" | tr '\n' ' ')) | 
|  | LogOutput "Discovered changes introduced by $MERGE_COMMIT: $diff_log" | 
|  | git checkout $MERGE_COMMIT | 
|  | if [ $? -ne 0 ]; then | 
|  | LogOutput "Can't checkout to $MERGE_COMMIT. Exiting" | 
|  | exit 1 | 
|  | fi | 
|  | declare -a allowlist_array | 
|  | for sdk in $SDKS | 
|  | do | 
|  | eval "check_${sdk}_passed"="false" | 
|  | example_has_changed="UNKNOWN" | 
|  | if [ "$FORCE_CD" = "true" ]; then | 
|  | LogOutput "FORCE_CD is true. Example deployment for SDK_${sdk^^} is forced" | 
|  | example_has_changed="true" | 
|  | else | 
|  | LogOutput "------------------Starting checker.py for SDK_${sdk^^}------------------" | 
|  | cd $BEAM_ROOT_DIR/playground/infrastructure | 
|  | python3 checker.py \ | 
|  | --verbose \ | 
|  | --sdk SDK_"${sdk^^}" \ | 
|  | --allowlist "${allowlist_array[@]}" \ | 
|  | --paths "${diff[@]}" | 
|  |  | 
|  | checker_status=$? | 
|  | if [ $checker_status -eq 0 ] | 
|  | then | 
|  | LogOutput "Checker found changed examples for SDK_${sdk^^}" | 
|  | example_has_changed="true" | 
|  | elif [ $checker_status -eq 11 ] | 
|  | then | 
|  | LogOutput "Checker did not find any changed examples for SDK_${sdk^^}" | 
|  | example_has_changed="false" | 
|  | else | 
|  | LogOutput "Error: Checker is broken. Exiting the script." | 
|  | exit 1 | 
|  | fi | 
|  | fi | 
|  | #Nothing to check | 
|  | if [[ $example_has_changed != "true" ]] | 
|  | then | 
|  | LogOutput "No changes require validation for SDK_${sdk^^}" | 
|  | eval "check_${sdk}_passed"="true" | 
|  | continue | 
|  | fi | 
|  |  | 
|  | cd $BEAM_ROOT_DIR/playground/infrastructure | 
|  | LogOutput "Running ci_cd.py for SDK $sdk" | 
|  |  | 
|  | export SERVER_ADDRESS=https://${sdk}.${DNS_NAME} | 
|  | python3 ci_cd.py \ | 
|  | --datastore-project ${PROJECT_ID} \ | 
|  | --namespace ${DATASTORE_NAMESPACE} \ | 
|  | --step ${STEP} \ | 
|  | --sdk SDK_"${sdk^^}" \ | 
|  | --origin ${ORIGIN} \ | 
|  | --subdirs ${SUBDIRS} | 
|  | if [ $? -eq 0 ]; then | 
|  | LogOutput "Examples for $sdk SDK have been successfully deployed." | 
|  | eval "check_${sdk}_passed"="true" | 
|  | else | 
|  | LogOutput "Examples for $sdk SDK were not deployed. Please see the logs." | 
|  | fi | 
|  | done | 
|  | LogOutput "Script finished" | 
|  | for sdk in $SDKS | 
|  | do | 
|  | result=$(eval echo '$'"check_${sdk}_passed") | 
|  | if [ "$result" != "true" ]; then | 
|  | LogOutput "At least one of the checks has failed for $sdk SDK" | 
|  | exit 1 | 
|  | fi | 
|  | done | 
|  | exit 0 |