Day 7 - Deploying a Python Application to App Engine using Google Cloud Build (CI/CD)
Nowadays, automating software delivery is important to ensure efficiency and faster time to market. Continuous Integration and Continuous Deployment (CI/CD) helps us streamline this automation process by automating code building, testing and deployment.
In this article, we’ll look into setting up a simple CI/CD pipeline for a simple Flask (Python) app using Google Cloud Build. This pipeline will automatically build, test, and deploy the application to Google App Engine.
The source code for this project can be found in this GitHub repo under the Day_7 folder.
Prerequisites
Python 3.x
Google Cloud Project with Cloud Build API and App Engine enabled
gcloud CLI
installed locally on your computer
Setting up:
Create a Google Cloud Project and verify that Billing has enabled.
Download, install and configure gcloud CLI on your computer (instructions)
Create a folder you’ll be working in and create & activate a Python virtual environment we will use to install dependencies for our project:
$ python -m venv venv # Activate the virtual environment $ venv\Scripts\activate # For Windows $ source venv/bin/activate # For MacOS/UNIX
Create a requirements.txt file and add the following
Flask==3.1.0
Install the dependencies in your activated virtual environment
(venv)$ pip install -r requirements.txt
Create a file called main.py and paste the following code:
from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Welcome to Jumanji!' if __name__ == '__main__': app.run(host='0.0.0.0', port=8080)
Script explanation:
The script above uses Flask, a web framework for building web applications.
app = Flask(__name__)
creates an instance of our Flask application. The__name__
argument refers to the name of the current Python module@app.route(“/”)
defines the route for our root URL of our web app.
The home() method is responsible for returning us the output when we visit the route defined above.Create a file called test_main.py and paste the following code:
import unittest from main import app class AppTestCase(unittest.TestCase): def setUp(self): self.app = app.test_client() self.app.testing = True def test_home(self): response = self.app.get('/') self.assertEqual(response.data, b'Welcome to Jumanji!') if __name__ == '__main__': unittest.main()
Script explanation:
The script above imports and uses
unittest
, a testing framework that provides a set of tools for testing the bits of our Python code.
The test will visit the route defined(‘/’)
and check if the output would be equal to ‘Welcome to Jumanji!
’. If the output is the same, the test passes, and fails if not.Create a file called
cloudbuild.yaml
and paste the following. Remember to replace<PROJECT_ID>
with your Google Cloud Project ID:steps: # Install dependencies - name: 'python:3.10' entrypoint: 'bash' args: - '-c' - | pip install -r requirements.txt echo "Dependencies installed." # Run tests - name: 'python:3.10' entrypoint: 'bash' args: - '-c' - | python -m unittest test_main.py echo "All tests completed" images: - 'gcr.io/<PROJECT_ID>/Deploy-App-to-AppEngine-CloudBuild'
The YAML file above contains the configurations needed for our app’s deployment to Google Cloud.
Create a file called
app.yaml
. This is an important configuration file that’s used when deploying an application to Google App Engine. It defines key deployment settings, including the runtime environment, environment variables etc. Paste the following:runtime: python310 handlers: - url: /.* script: auto
Next, we’re going to create the
.gcloudignore
file. This file is used to specify files and directories that should be excluded from deployment when usinggcloud
commands. It functions similarly to.gitignore
; but specifically for Google Cloud SDK to prevent unecessary or sensitive files from being uploaded to Google Cloud services.# This file specifies files that are *not* uploaded to Google Cloud # using gcloud. It follows the same syntax as .gitignore, with the addition of # "#!include" directives (which insert the entries of the given .gitignore-style # file at that point). # # For more information, run: # $ gcloud topic gcloudignore # .gcloudignore # If you would like to upload your .git directory, .gitignore file or files # from your .gitignore file, remove the corresponding line # below: .git .gitignore # Python pycache: __pycache__/ # Ignored by the build system /setup.cfg .venv/
Run the project locally and visit
http://127.0.0.1:8080
on your browser(venv)$ python main.py
Results on the browser 👇
Deploy the app
In your terminal, run the following command:
$ gcloud app deploy
The output will request if you’d like to continue with the deployment, type Y
and hit Enter
After the deployment is successful, your terminal’s output will look something like this
Navigate to Cloud Build page on Google Cloud Console. Click on History on the left panel. Select the region you deployed your app and your build(s) will show up.
Click on the Buiid number to see the Build details like logs, details and artifacts.
Viewing our application
Navigate to App Engine page on the Google Cloud Console. Click on Services on the left panel and you will see ‘default’ service listed there
Click on the ‘default’ name and a new tab will open on your browser with your deployed application
Congratulations! You’ve deployed your application to App Engine using Cloud Build (CI/CD)
Conclusion
Implementing CI/CD pipelines streamline the development workflow by automating build, test, and deployment processes. Our setup is even more seamless with the integration with Google App Engine, reducing manual intervention.