UPDATED 2023: Auto deploy AppEngine app from Gitlab
Tags: appengine, googlecloud, gitlab, cicd
Published: 2019-12-11 19:50:19

Nowadays, CI/CD is a common task during Software Development and almost all platforms enable us to do this automatically. It is not different on Gitlab.
Today, I'll show you how to configure your Gitlab project to automatically deploy to Google Cloud App Engine.

## Google Cloud part

### First things first
First, you need to setup your App Engine project on GCP console. It is necessary because App Engine requires you to set the region of your app.
If you didn't do this, first you will need to setup using this cmd:
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/6mjhkj0q1qzst1yl989a.png" alt="gcloud app create" style="width:80%">
  <figcaption>Setup your App Engine app.</figcaption>
</figure>
and follow the instructions.

### Updates
The stesp below were made a few years ago, so some permissions were changed.
To simplify the process, I paste here a script. Take a look, and change the appropriated information:

```
export SA_NAME=gitlab-sa
export GCLOUD_PROJECT=<YOUR_PROJECT_ID_HERE>
export SA_EMAIL=${SA_NAME}@${GCLOUD_PROJECT}.iam.gserviceaccount.com

gcloud services enable appengine.googleapis.com cloudbuild.googleapis.com

gcloud iam service-accounts create ${SA_NAME} --display-name 'Gitlab Service Account to deploy' --project ${GCLOUD_PROJECT}

gcloud iam service-accounts keys create ${SA_NAME}.json --iam-account=SA_EMAIL --project ${GCLOUD_PROJECT}

cat ${SA_NAME}.json
```

Copy the JSON content and save to include in the Gitlab CICD variables page.

Now continue the process, giving to the service account some permissions:

```

gcloud projects add-iam-policy-binding ${GCLOUD_PROJECT} \
    --member="serviceAccount:${SA_EMAIL}" \
    --role=roles/appengine.appAdmin

gcloud projects add-iam-policy-binding ${GCLOUD_PROJECT} \
    --member="serviceAccount:${SA_EMAIL}" \
    --role=roles/storage.objectAdmin


gcloud projects add-iam-policy-binding ${GCLOUD_PROJECT} \
    --member="serviceAccount:${SA_EMAIL}" \
    --role=roles/iam.serviceAccountUser

gcloud projects add-iam-policy-binding ${GCLOUD_PROJECT} \
    --member="serviceAccount:${SA_EMAIL}" \
    --role=roles/cloudbuild.builds.builder

```


### Service Account and Permissions
Jump to Gitlab Config part, if you already did the script above.

~~The entire process should be made without human intervention. So, to do this on GCP you'll need a Service Account.~~

~~First, create a Service Account to be used during the process: ~~[Service Account Create](https://console.cloud.google.com/iam-admin/serviceaccounts/create)

<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/8u63dcqefc6gsg5lz9if.png" alt="Step 1" style="width:80%;border: 1px solid gray;">
  <figcaption>Step 1</figcaption>
</figure>

Step2: ~~**Critical step, here you MUST give all those permissions. Without them, the automation will not work properly.**~~
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/t0vhe0as2t1oc2s1drkr.png" alt="Step 2" style="width:80%">
  <figcaption>Step 2: VERY IMPORTANT!</figcaption>
</figure>

<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/w142ooqnd8giq96j6yok.png" alt="Step 3: Create a Key" style="width:80%">
  <figcaption>Step 3: Create a Key</figcaption>
</figure>

<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/s9ugdb3cbj5jyhq9emyb.png" alt="Step 4: choose the JSON option." style="width:80%">
  <figcaption>Step 4: choose the JSON option!</figcaption>
</figure>
In the last step, you should open the file and copy the content. This content will be necessary to configure the Gitlab.

### API Enabling
Some APIs must be enabled before trying to run the deploy.
1. Enable the App Engine Admin API, here:
[Enable App Engine Admin API](https://console.developers.google.com/apis/api/appengine.googleapis.com/overview)
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/tcpswczd51vxn3647h6r.png" alt="App Engine Admin API enabling" style="width:80%">
  <figcaption>App Engine Admin API enabling</figcaption>
</figure>

2. Enable Cloud Builder API: [Cloud Builder API Enable](https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview)
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/sqlj1tsv4f1k3oi12efw.png" alt="Cloud Build API enabling" style="width:80%">
  <figcaption>Cloud Build API enabling</figcaption>
</figure>


## Gitlab Config
Now you have all done on GCP, Gitlab part!
Go to your project and configure the CI/CD options:

<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/rp7jl6583lvmodngci0s.png" alt="Gitlab CI/CD menu option" style="width:50%">
  <figcaption>CI/CD menu option</figcaption>
</figure>

Instead of having the content of your Service Account in a file inside your repository, a best practice is to have this as a variable. So, configure a variable, following the image:

<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/0uk0cmzkf9gsmto27zts.png" alt="Configure the SERVICE_ACCOUNT_KEY variable with the JSON content downloaded in the Step 4." style="width:60%">
  <figcaption>Configure the SERVICE_ACCOUNT_KEY variable with the JSON content downloaded in the Step 4.</figcaption>
</figure>


## Gitlab CI file descriptor
To enable all these pieces together is required to "tell" to Gitlab: "Please my friend, run all these now". To do this, you should create a file in your repository called **.gitlab-ci.yml**, this file describes what you want to do.
<figure>
  <img src="https://thepracticaldev.s3.amazonaws.com/i/6i483fy9w9h5sy29fq8i.png" alt="xxxxxxxxx" style="width:80%">
  <figcaption>Basic gitlab ci descriptor.</figcaption>
</figure>
File content available here.
https://gitlab.com/giulianobr/simple-go-app/blob/235de13e310d7614f9b8cb2dab0f804c6b82a041/.gitlab-ci.yml

The CI process runs inside the container platform in Gitlab. At the glance, it seems like a Dockerfile, as you should define and base image where your deploy will run.
In this case, I'm using Google's base image that contains the Google Cloud SDK already installed.
To understand more about all configs available on Gitlab CI, take a [look here](https://gitlab.com/help/ci/examples/README.md).

## Conclusion
This post aims to help you to deploy an app to App Engine Standard. As my example is a Golang app in the 2nd gen runtime, it is a bit easier. To deploy a Java 8 app is a little bit different. If you want any help to setup your Java 8 app, ask me in the comments, I also have an example for this scenario.

I hope it helps you, people!
See you soon.

You can find this project in [my Gitlab project](https://gitlab.com/giulianobr/simple-go-app).