kdeng / my-blogs

Kefeng's blogs
0 stars 0 forks source link

How to deploy Go app to GAE #4

Open kdeng opened 6 years ago

kdeng commented 6 years ago

I have done some works for deploying a Python-based application to GAE, and now I would like to simply update the scripts to enable myself can deploy a Go application to GAE easily. And if you want to achieve the same goal, please have a look at following scripts.

Before starting to run the scripts, you need to create a service account key, which should be granted with the proper permissions to deploy to GAE.

The project folder structure should look like following:

go-gae-demo
|-- appengine
|    | -- app.yaml
|-- scripts
|    |-- ci-deploy.sh
|    |-- docker-deploy.sh
|-- src
|    |-- app.go
|-- go-gae-demo-dev.service-account-key.json   

The CI deploy script content is below.

#!/usr/bin/env bash
# This is the content of ci-deploy.sh

# Force the shell to immediately if a single command exits with a non-zero exit value.
set -e

# Turn on / off the debug mode
# set -x
GCP_PROJECT_ID=$PROJECT
GAE_SERVICE_NAME=$SERVICE_NAME

# Define the version number
VERSION=$(date '+%Y%m%d-%H%M%S')

GO_VERSION=1.10.2

WORD_DIR=`pwd`
echo -e "\n[PREPARE]: Current work directory is $WORD_DIR"

install_golang() {
    echo -e "\n[INSTALL]: Install go tools"
    apt-get -y install wget
    cd /tmp && wget https://dl.google.com/go/go$GO_VERSION.linux-amd64.tar.gz
    tar -C /usr/local -xzf go$GO_VERSION.linux-amd64.tar.gz
    export PATH=$PATH:/usr/local/go/bin
    go version
    echo -e "\n[INSTALL]: Go back to work directory $WORD_DIR"
    cd $WORD_DIR
    export GOPATH=$WORD_DIR/dist
}

login_gcp_with_service_account() {
    echo -e "\n[LOGIN]: Login with service account"
    gcloud auth activate-service-account --key-file $1
    gcloud auth list
}

build_and_deploy_appengine_service() {

    project_id=$1
    version=$2
    service_name=$3
    library_to_ignore=".DS_Store"
    files_to_ignore=".DS_Store|test"

    rm -rf ./dist
    mkdir -p ./dist/src/main

    echo -e "\n[Build]: Start to deploy default service to project '$project_id'"

    echo -e "\n[Build]: Generating resources"
    find ./appengine -maxdepth 1 ! -path ./appengine | egrep -v "${library_to_ignore}" | xargs -IELEMENT cp -r ELEMENT ./dist/src/main

    echo -e "\n[Build]: Copying all modules"
    find ./src -maxdepth 1  -type f ! -path ./src | egrep -v "${files_to_ignore}" | xargs -IELEMENT cp -r ELEMENT ./dist/src/main

    echo -e "\n[Build]: Copying all libraries"
    find ./src -maxdepth 1  -type d ! -path ./src | egrep -v "${files_to_ignore}" | xargs -IELEMENT cp -r ELEMENT ./dist/src

    echo -e "\n[INSTALL]: Install go packages to GOPATH=$GOPATH"
    go get -u -v github.com/julienschmidt/httprouter
    go get -u -v google.golang.org/appengine
    go get -u -v cloud.google.com/go/bigquery

    echo -e "[Build]: Starting to deploy GAE service"
    cd ./dist && gcloud app deploy ./src/main/app.yaml --quiet --project="$project_id" --promote --version="$version"
    echo -e "\n[Deploy]: Deploy version [$version] successfully"

    # Delete all previous version
    previous_versions=$(gcloud app versions list --project "$project_id" --service "$service_name" | egrep -v "$version|VERSION" | awk '{print $2}')
    joined_previous_versions=$(echo "$previous_versions" | paste -sd "," -)
    if [ ! -z "$previous_versions" ]; then
        echo -e "\n[Deploy]: Deleting previous version '$joined_previous_versions'"
        gcloud app versions delete --quiet --project "$project_id" $previous_versions
    fi

    echo -e "\n\n======= DONE ======="

}

install_golang
login_gcp_with_service_account ./$GCP_PROJECT_ID.service-account-key.json
build_and_deploy_appengine_service $GCP_PROJECT_ID $VERSION $GAE_SERVICE_NAME

In order to isolate CI environment with my local environment, I use the docker to build and deploy the application, that's why we need a service account key.

So, the docker deploy script is below.

#!/usr/bin/env bash

project_id="go-gae-demo"
environment="dev"
service_name="go-gae-demo-service"

docker run --rm -it \
    --user root \
    -v $(PWD):/app \
    -e PROJECT="$project_id-$environment" \
    -e SERVICE_NAME="$service_name" \
    -w /app google/cloud-sdk:latest \
    sh -c "/app/scripts/ci-deploy.sh"