Cloud Functions can be deployed automatically with Cloud Build by creating a cloudbuild.yaml file that defines the build steps for your function.
Here’s how it works:
Let’s say you have a simple Node.js Cloud Function named helloWorld in a file index.js:
// index.js
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send(message);
};
And you have a package.json:
{
"name": "my-cloud-function",
"version": "1.0.0",
"description": "A simple Cloud Function",
"main": "index.js",
"dependencies": {},
"devDependencies": {},
"scripts": {
"start": "functions-framework --target=helloWorld"
}
}
Now, you create a cloudbuild.yaml file in the root of your project:
steps:
# Step 1: Install dependencies
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
# Step 2: Deploy the Cloud Function
- name: 'gcr.io/cloud-builders/gcloud'
args:
- 'functions'
- 'deploy'
- 'helloWorld'
- '--runtime=nodejs18' # Specify your runtime
- '--trigger-http' # Specify your trigger type
- '--allow-unauthenticated' # Example: allow unauthenticated access
- '--source=.' # Deploy from the current directory
- '--entry-point=helloWorld' # The exported function name
- '--region=us-central1' # Your desired region
- '--project=$PROJECT_ID'
When you run gcloud builds submit --config cloudbuild.yaml ., Cloud Build will:
- Execute the
npm installcommand to install dependencies defined inpackage.json. - Use the
gcloud functions deploycommand to deploy yourhelloWorldfunction.
This setup allows you to version control your deployment configuration alongside your function code, ensuring reproducible deployments.
The gcloud functions deploy command is quite powerful. You can specify various options like --runtime, --trigger-http, --trigger-event, --trigger-resource, --memory, --timeout, --service-account, and more.
For instance, if you wanted to deploy a function triggered by a Cloud Storage object finalization event, your cloudbuild.yaml might look like this:
steps:
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
- name: 'gcr.io/cloud-builders/gcloud'
args:
- 'functions'
- 'deploy'
- 'processStorageObject'
- '--runtime=nodejs18'
- '--trigger-event=google.storage.object.finalize'
- '--trigger-resource=${_STORAGE_BUCKET_NAME}' # Use a substitution variable
- '--source=.'
- '--entry-point=processStorageObject'
- '--region=us-central1'
- '--project=$PROJECT_ID'
In this case, you’d also need to define the _STORAGE_BUCKET_NAME substitution variable when submitting the build, for example: gcloud builds submit --config cloudbuild.yaml . --substitutions=_STORAGE_BUCKET_NAME=your-bucket-name.
The source=. argument tells gcloud to use the current directory as the source code location for the function. If your function code is in a subdirectory, say my-function, you would change this to source=my-function.
Cloud Build integrates seamlessly with your version control system (like Cloud Source Repositories, GitHub, or Bitbucket). You can configure a build trigger so that every time you push code to a specific branch, Cloud Build automatically picks up the cloudbuild.yaml and deploys your function.
When you use gcloud functions deploy within Cloud Build, the deployment happens within the project specified by $PROJECT_ID. This is a built-in substitution variable provided by Cloud Build that automatically resolves to the project ID where the build is running.
The --allow-unauthenticated flag is useful for HTTP functions that don’t require authentication. If your function needs to be secured, you would omit this flag and handle authentication via IAM or other mechanisms.
The --entry-point flag is crucial. It tells the Cloud Functions runtime which exported function in your code should be executed when the function is invoked. Ensure this matches the name of your exported function.
The gcr.io/cloud-builders/npm and gcr.io/cloud-builders/gcloud images are pre-built Docker images provided by Google Cloud that contain the npm and gcloud CLIs, respectively. This means you don’t need to bake these tools into your own build images.
Cloud Build allows for more complex workflows. You could, for example, add steps to run unit tests before deployment, package your function code into a Docker image (though gcloud functions deploy handles this implicitly for many runtimes), or even deploy multiple functions in a single build.
The --runtime flag is critical for ensuring your function runs in the correct environment. For example, --runtime=python311 for Python, --runtime=go120 for Go, or --runtime=java17 for Java. Always check the Cloud Functions documentation for the latest supported runtimes.
The --source=. argument is relative to the directory where you execute the gcloud builds submit command. If your cloudbuild.yaml and function code are in the root of your repository, this works directly. If your cloudbuild.yaml is in a cloudbuild/ directory and your function code is in functions/my-function/, you’d adjust the args for gcloud functions deploy accordingly, specifying the source path.
The specific trigger type (--trigger-http, --trigger-event, --trigger-resource) depends entirely on what you want your function to react to. HTTP triggers are for webhooks or direct invocation, while event triggers respond to changes in other Google Cloud services.
One common pattern is to use a Git repository trigger. You configure Cloud Build to watch a specific branch (e.g., main or production) in your repository. When a commit is pushed to that branch, Cloud Build automatically starts a build using your cloudbuild.yaml and deploys the function.
The gcloud functions deploy command, when executed by Cloud Build, creates or updates a Cloud Function resource in your Google Cloud project. It uploads your source code, builds the function container image (if necessary), and configures the function’s trigger and runtime environment.
The next step after setting up automatic deployment is often integrating with a CI/CD pipeline that includes automated testing, or implementing more sophisticated deployment strategies like blue/green deployments or canary releases, which might involve using Cloud Deploy in conjunction with Cloud Build.