This tutorial will teach you how to deploy a Python 3.8-based Cloud Function using GitLab CI.
If you encounter a variable you don't recognize while reading, take a look here.
Variable name | Description |
---|---|
... |
Sensitive value. |
GIST_PROJECT_NAME |
The Google Cloud project name. |
GIST_FUNCTION_NAME |
The Google Cloud function name. |
GIST_SERVICE_ACCOUNT_NAME |
The service account name that will be created in this tutorial. |
GIST_SERVICE_ACCOUNT_EMAIL |
The service account email, often but not always created as "GIST_SERVICE_ACCOUNT_NAME@GIST_PROJECT_NAME.iam.gserviceaccount.com" |
GIST_SERVICE_ACCOUNT_KEY_PATH |
The path where the credentials file will be saved in your local machine. This path should not point to a directory. |
- A project in Google Cloud, as described here.
- A
gcloud
command-line interface set up, as described here.
Go to https://console.cloud.google.com/?project=GIST_PROJECT_NAME. Open lateral menu > IAM & Admin > Service Accounts and click in "Create service account", in the upper left corner. Alternatively, go to https://console.cloud.google.com/iam-admin/serviceaccounts/create?project=GIST_PROJECT_NAME.
Fill the form. Here, fields with (open) can be customized according to your project. Values followed by :
can be used as example in your setup.
- Service account details
- Service account name (open,
GIST_SERVICE_ACCOUNT_NAME
): continuous-integration - Service account ID (automatically filled,
GIST_SERVICE_ACCOUNT_EMAIL
) - Service account description (open): Manage continuous integration services.
- Grant this service account access to project
In the dropdown list, select the Cloud Functions Admin role.
- Grant users access to this service account
Do nothing and click "Done".
Check if the new service account is appearing:
$ gcloud iam service-accounts list
DISPLAY NAME EMAIL DISABLED
GIST_SERVICE_ACCOUNT_NAME GIST_SERVICE_ACCOUNT_EMAIL False
App Engine default service account [email protected] False
Run the following to create the service account credentials:
$ gcloud iam service-accounts keys create GIST_SERVICE_ACCOUNT_KEY_PATH --iam-account GIST_SERVICE_ACCOUNT_EMAIL --key-file-type=json
created key [...] of type [json] as [GIST_SERVICE_ACCOUNT_KEY_PATH] for [GIST_SERVICE_ACCOUNT_EMAIL]
The created file will be of format
{
"type": "service_account",
"project_id": "GIST_SERVICE_ACCOUNT_NAME",
"private_key_id": "...",
"private_key": "...",
"client_email": "GIST_SERVICE_ACCOUNT_EMAIL",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "..."
}
We'll run our Cloud Function in CI as the default service account and deploy it with the created service account. Thus, we need to give the default service account the user permission. Run
$ gcloud iam service-accounts add-iam-policy-binding [email protected] --member=serviceAccount:GIST_SERVICE_ACCOUNT_EMAIL --role=roles/iam.serviceAccountUser
Updated IAM policy for serviceAccount [[email protected]].
bindings:
- members:
- serviceAccount:GIST_SERVICE_ACCOUNT_EMAIL
role: roles/iam.serviceAccountUser
etag: ...
version: ...
Create a .gitlab-ci.yml file in your project root directory with contents
variables:
GCLOUD_PROJECT_NAME: GIST_PROJECT_NAME
GCLOUD_SERVICE_ACCOUNT_EMAIL: GIST_SERVICE_ACCOUNT_EMAIL
GCLOUD_FUNCTION_NAME: GIST_FUNCTION_NAME
GCLOUD_HOST_NAME: https://us-central1-$GCLOUD_PROJECT_NAME.cloudfunctions.net
stages:
- build
- deploy
- deploy-test
build-job:
image: python:3.8.13
stage: build
script:
- python -m pip install -r requirements.txt
deploy-job:
image: google/cloud-sdk:387.0.0
stage: deploy
script:
- echo $GCLOUD_SERVICE_ACCOUNT_KEY_CONTENTS > key.json
- gcloud auth activate-service-account $GCLOUD_SERVICE_ACCOUNT_EMAIL --project $GCLOUD_PROJECT_NAME --key-file key.json
- gcloud functions deploy $GCLOUD_FUNCTION_NAME --runtime python38 --trigger-http --allow-unauthenticated
deploy-test-job:
image: python:3.8.13
stage: deploy-test
script:
- python -c "import urllib.request; print(urllib.request.urlopen('$GCLOUD_HOST_NAME/$GCLOUD_FUNCTION_NAME').getcode())"
Replace the fields appropriately, specially
- the
GCLOUD_HOST_NAME
variable, if your function is not running on "us-central1" - the
build-job
configuration, if you're not using Python 3.8 or want to add more commands - the last
deploy-job
command, if you're not using Python 3.8 or want to change the command-line arguments
Create a new CI variable named "GCLOUD_SERVICE_ACCOUNT_KEY_CONTENTS". Copy the contents of GIST_SERVICE_ACCOUNT_KEY_PATH
and paste into this variable.
Commit and let the pipeline run! :)