Auto-Deploy Your Chatbot with Cloud Build
Build a CI/CD pipeline that deploys your Node.js chatbot to Cloud Run automatically.
Introduction
30 Second Summary
Every time you update your chatbot's code, you need to get that change live for your users. Doing this manually means logging into servers, running build commands, and hoping nothing breaks along the way.
In this project, you will build a CI/CD pipeline on Google Cloud Platform that automatically deploys your Node.js chatbot every time you push code to GitHub.
What You'll Build
A complete automated pipeline using Cloud Build that containerizes your Express chatbot, stores it in Artifact Registry, and deploys it to Cloud Run on every push to main.
By the end of this project, you'll have:
- A Dockerfile that packages your chatbot into a portable Docker container image.
- A cloudbuild.yaml configuration that automates your build, push, and deploy workflow.
- A Cloud Build trigger connected to GitHub that deploys your chatbot on every push to main.
- Secret Mission: Add a staging environment that deploys on pull requests so you can test changes before merging to main.
Are there any prerequisites?
You need a GCP account with billing enabled, the gcloud CLI installed on your machine, and a GitHub repository containing a Node.js/Express application with a package.json.
Before We Start
Before We Start...
Initialize gcloud and Enable GCP Services
Before you can deploy anything to Google Cloud, your local gcloud CLI needs to know which project to work with. It also needs the right APIs turned on and the right permissions configured.
In this step, you will initialize the CLI, enable the services your pipeline depends on, and grant your Cloud Build service account permission to deploy to Cloud Run.
In this step, get ready to:
- Initialize the gcloud CLI and set your default region.
- Enable the Cloud Build, Cloud Run, and Artifact Registry APIs.
- Grant IAM roles so Cloud Build can deploy to Cloud Run.
Initialize the gcloud CLI
The gcloud CLI is your command-line interface for managing resources on Google Cloud Platform. Initializing it connects your terminal to your GCP account and selects a project to work in.
- Open your terminal by pressing Cmd+Space (macOS) or the Windows key (Windows), then type Terminal and press Enter.
- Start the initialization process by running this command:
gcloud init
What will gcloud init ask you?
This command launches an interactive setup. It will open your browser to sign in with your Google account, then prompt you to select a GCP project. If prompted about a default Compute Engine zone, you can skip it for now since we will set it manually in the next command.
- Sign in with your Google account when the browser opens.
- Select the GCP project you want to use for this pipeline when prompted.
- Set your default region to us-central1 by running these commands:
gcloud config set compute/region us-central1
gcloud config set compute/zone us-central1-a
Why us-central1?
This is a Tier 1 pricing region for Cloud Run, meaning it has the lowest cost. It is also widely available for all GCP services and is the default in most quickstarts.
- Verify your configuration by running:
gcloud config list
You should see output showing your account, project, region as us-central1, and zone as us-central1-a.
Don't see a project listed?
Make sure you selected a project during gcloud init. You can set it manually with gcloud config set project YOUR_PROJECT_ID. Replace YOUR_PROJECT_ID with the ID from your Google Cloud Console dashboard.
Help me troubleshoot my gcloud init setup
Enable the required APIs
GCP disables most service APIs by default. Your pipeline needs three services enabled: Cloud Build to run builds, Cloud Run to host your container, and Artifact Registry to store your container images.
- Enable all three APIs by running this command:
gcloud services enable cloudbuild.googleapis.com run.googleapis.com artifactregistry.googleapis.com
What does this command do?
This single command turns on three separate Google Cloud APIs in your project. cloudbuild.googleapis.com lets you run containerized builds in the cloud. run.googleapis.com lets you deploy and run containers as serverless services. artifactregistry.googleapis.com gives you a private Docker registry to store your images.
- Wait for the command to complete. This can take 30-60 seconds.
You should see a success message like Operation finished successfully for each API.
Seeing a permission denied error?
You need the Owner or Editor role on the project to enable APIs. Check that you selected the correct project with gcloud config get-value project. If the project is managed by an organization, ask your admin to grant you the Service Usage Admin role.
Help me fix a permission error when enabling GCP APIs
Grant IAM roles to the Cloud Build service account
Cloud Build uses a service account to perform actions on your behalf. By default, this service account does not have permission to deploy containers to Cloud Run. You need to grant it two roles: Cloud Run Admin (to create and update services) and Service Account User (to act as the runtime identity during deployment).
- Get your project number by running:
gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)'
What is a project number?
Your project number is different from your project ID. The project ID is a human-readable string you chose. The project number is a numeric identifier that GCP assigns automatically. Service account email addresses use the project number, not the project ID.
- Copy the number that appears in the output. You will need it for the next two commands.
- Grant the Cloud Run Admin role to your Cloud Build service account by running this command (replace your project number with the number you just copied):
gcloud projects add-iam-policy-binding $(gcloud config get-value project) \
--member="serviceAccount:[[PROJECT_NUMBER="your project number"]]@cloudbuild.gserviceaccount.com" \
--role="roles/run.admin"
What does this command do?
This grants the roles/run.admin role to the Cloud Build service account on your project. This role gives Cloud Build full control over Cloud Run services, allowing it to create and update deployments on your behalf.
- Grant the Service Account User role so Cloud Build can act as the Compute Engine default service account during deployment:
gcloud iam service-accounts add-iam-policy-binding \
[[PROJECT_NUMBER="your project number"]]-compute@developer.gserviceaccount.com \
--member="serviceAccount:[[PROJECT_NUMBER="your project number"]]@cloudbuild.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
Why does Cloud Build need Service Account User?
When Cloud Build deploys a container to Cloud Run, the Cloud Run service runs using a runtime identity. By default, this is the Compute Engine default service account (PROJECT_NUMBER-compute@developer.gserviceaccount.com). Cloud Build needs permission to "act as" this account, which is what the Service Account User role grants.
You should see the updated IAM policy printed to your terminal after each command completes.
Seeing PERMISSION_DENIED on the IAM commands?
Double-check that you replaced the project number placeholder with the actual numeric value from the earlier command. Also make sure your own account has the Owner or IAM Admin role on the project.
Help me fix IAM permission errors for Cloud Build
Your GCP project is now fully configured. Next up, you will containerize your chatbot with a Dockerfile so Cloud Build knows how to package it.
Containerize Your Chatbot
Your GCP environment is configured and ready to go. Now you need to teach Cloud Build how to package your chatbot into a portable unit it can deploy anywhere.
That portable unit is called a container. You define how to build it by writing a Dockerfile, which is a recipe that tells Docker exactly what goes into the container and how to start your app.
In this step, get ready to:
- Create a Dockerfile for your Express chatbot.
- Create a .dockerignore file to keep the container lean.
- Test the container build with Cloud Build.
Create a Dockerfile for your chatbot
A Dockerfile lists every instruction needed to build your app into a container image. It starts from a base image (like Node.js), copies your source code in, installs dependencies, and defines how to start the app.
Make sure your app listens on process.env.PORT
Cloud Run injects a PORT environment variable (default 8080) that your app must listen on. If your server.js currently hardcodes a port (like 3000), update it to use process.env.PORT || 8080 before continuing.
- In the root of your chatbot project folder (the same folder that contains your package.json), create a new file called Dockerfile (no file extension) and paste in the following code:
# Use a lightweight Node.js base image
FROM node:20-slim
# Set the working directory inside the container
WORKDIR /app
# Copy dependency manifests first (enables Docker layer caching)
COPY package*.json ./
# Install production dependencies only
RUN npm ci --only=production
# Copy the rest of the application source code
COPY . .
# Document the port the container listens on
EXPOSE 8080
# Set the PORT environment variable for Cloud Run
ENV PORT=8080
# Start the Express server
CMD ["node", "server.js"]
What does this Dockerfile do?
- FROM node:20-slim starts from a minimal Node.js 20 image, keeping the final container small.
- COPY package*.json is copied separately before COPY . . so Docker can cache the npm ci step when only your source code changes.
- npm ci --only=production installs exact versions from package-lock.json without dev dependencies, keeping the image lean.
- ENV PORT=8080 matches what Cloud Run expects, so your Express app knows which port to listen on.
- Save Dockerfile.
- Confirm the file exists by running:
ls Dockerfile
You should see Dockerfile printed in the output.
Don't see the file?
- Make sure you created the file in the root of your chatbot project folder, not inside a subfolder.
- Check that the file is named exactly Dockerfile with a capital D and no file extension (not Dockerfile.txt or dockerfile).
- Make sure your terminal is in the same folder as the file. Run pwd to check your current directory.
Help me find my Dockerfile
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 8080
ENV PORT=8080
CMD ["node", "server.js"]
Create a .dockerignore file
When Docker builds your container, it copies everything in the current folder into the build context by default. A .dockerignore file tells Docker to skip files that don't belong in the final image, like node_modules or your .git history.
- In the same project root folder, create a new file called .dockerignore and paste in the following:
node_modules
npm-debug.log
.git
.gitignore
.env
README.md
.dockerignore
Dockerfile
Why exclude these files?
- node_modules is excluded because the Dockerfile runs npm ci to install fresh dependencies inside the container.
- .git and .env are excluded to keep version history and secrets out of the container image.
- Excluding unnecessary files makes the build faster and the final image smaller.
- Save .dockerignore.
- Confirm both files exist by running:
ls -a Dockerfile .dockerignore
You should see both Dockerfile and .dockerignore listed in the output.
Only seeing Dockerfile?
Files starting with a dot are hidden by default. The -a flag in ls -a reveals them. If you still don't see .dockerignore, check that you included the leading dot in the filename.
Help me find my .dockerignore file
✔️ Awesome, I've got everything!
Great. Make sure both files are saved before moving on.
ⓧ I'd like to double check the full code
node_modules
npm-debug.log
.git
.gitignore
.env
README.md
.dockerignore
Dockerfile
Test the container build with Cloud Build
You have a Dockerfile, but you haven't proven it actually builds yet. Cloud Build can run a Docker build in the cloud without needing Docker installed on your machine.
- Submit a test build to Cloud Build by running this command from your project root:
gcloud builds submit --tag gcr.io/$(gcloud config get-value project)/chatbot:test .
What does this command do?
- gcloud builds submit uploads your source code to Cloud Build and triggers a build.
- --tag gcr.io/... tells Cloud Build to use your Dockerfile, build a container image, and tag it with this name.
- $(gcloud config get-value project) dynamically inserts your GCP project ID so you don't have to type it manually.
- The . at the end means "use the current directory as the build source."
This command takes 1-2 minutes to complete. You'll see streaming build logs in your terminal as Cloud Build executes each Dockerfile instruction.
- Wait for the build to finish and look for SUCCESS in the output along with a build ID and status.
Seeing a build error?
- If you see COPY failed: file not found, make sure you're running the command from the folder that contains your Dockerfile and package.json.
- If you see npm ERR! during the install step, check that your package-lock.json exists and is committed to your repo.
- If you see a permissions error, confirm that the Cloud Build API is enabled (you did this in Step 1).
Help me fix my Cloud Build error
Your chatbot is now containerized and proven to build successfully in the cloud. Next up, you'll create the full CI/CD pipeline configuration that builds, pushes, and deploys the container automatically.
Create the CI/CD Pipeline Configuration
Your chatbot is containerized and ready to go. In the last step, you verified that Cloud Build can successfully build your Docker image in the cloud.
Now it's time to define the full pipeline. You'll create a configuration file that tells Cloud Build exactly what to do with your container: build it, store it in a registry, and deploy it to a live URL.
In this step, get ready to:
- Create an Artifact Registry repository to store your container images.
- Write a cloudbuild.yaml pipeline configuration with build, push, and deploy steps.
- Run the full pipeline and verify your chatbot is live on Cloud Run.
Create an Artifact Registry repository
Your pipeline will build a Docker image every time you push code. That image needs to live somewhere Cloud Run can pull it from during deployment.
Artifact Registry is Google Cloud's container image storage service. Think of it as a private warehouse for your Docker images.
- Create a Docker repository in Artifact Registry by running this command:
gcloud artifacts repositories create chatbot-repo --repository-format=docker --location=us-central1
What does this command do?
- chatbot-repo is the name of your new repository. This is where all your chatbot container images will be stored.
- --repository-format=docker tells Artifact Registry this repo stores Docker container images.
- --location=us-central1 places the repository in the same region as your Cloud Run service for faster pulls.
- Confirm the repository was created by running:
gcloud artifacts repositories list --location=us-central1
You should see chatbot-repo listed with format DOCKER and location us-central1.
Don't see the repository?
- Make sure you spelled chatbot-repo exactly as shown. Repository names are case-sensitive.
- Check that the Artifact Registry API is enabled by running gcloud services list --enabled and looking for artifactregistry.googleapis.com.
- Help me troubleshoot my Artifact Registry repository creation
Write the cloudbuild.yaml pipeline configuration
Cloud Build needs a configuration file that describes your pipeline. This file defines each step in order: build the image, push it to Artifact Registry, then deploy it to Cloud Run.
- Create a new file called cloudbuild.yaml in the root of your project (the same folder as your Dockerfile).
- Paste the following pipeline configuration into it:
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA', '.']
# Push the container image to Artifact Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA']
# Deploy container image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- 'run'
- 'deploy'
- 'chatbot'
- '--image'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA'
- '--region'
- 'us-central1'
- '--platform'
- 'managed'
- '--allow-unauthenticated'
images:
- 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA'
What does this pipeline do?
This file defines three sequential steps that Cloud Build executes in order:
- Step 1 (Build) uses the official Docker builder to build your image and tag it with your project ID and commit hash.
- Step 2 (Push) pushes the built image to your chatbot-repo in Artifact Registry.
- Step 3 (Deploy) uses the gcloud SDK to deploy the image to Cloud Run with public access enabled.
$PROJECT_ID and $COMMIT_SHA are built-in substitution variables. Cloud Build fills them in automatically when triggered from a Git repository.
What is the images field for?
The images field at the bottom tells Cloud Build to record this image in its build metadata. It makes the image show up in the Cloud Console build history linked to the build that created it.
- Save cloudbuild.yaml.
Watch your YAML indentation
YAML is sensitive to spaces. Each indentation level uses exactly 2 spaces (not tabs). If your file has inconsistent indentation, Cloud Build will reject it with a parse error.
Help me fix YAML indentation errors in my cloudbuild.yaml
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here is the complete cloudbuild.yaml for comparison:
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA', '.']
# Push the container image to Artifact Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA']
# Deploy container image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args:
- 'run'
- 'deploy'
- 'chatbot'
- '--image'
- 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA'
- '--region'
- 'us-central1'
- '--platform'
- 'managed'
- '--allow-unauthenticated'
images:
- 'us-central1-docker.pkg.dev/$PROJECT_ID/chatbot-repo/chatbot:$COMMIT_SHA'
Run the full pipeline manually
Before connecting GitHub triggers, you want to confirm the entire build-push-deploy flow works end to end. You can run the pipeline manually using gcloud builds submit with a substitution for the commit hash.
Why provide a substitution?
$COMMIT_SHA is normally filled in automatically when Cloud Build is triggered from a Git push. Since you're running this manually, you need to supply a value yourself. Using latest as the tag works perfectly for a manual test.
- Make sure your terminal is in the root of your project (the folder containing cloudbuild.yaml).
- Run the full pipeline by executing this command:
gcloud builds submit --config=cloudbuild.yaml --substitutions=COMMIT_SHA=latest .
What does this command do?
- --config=cloudbuild.yaml tells Cloud Build to use your pipeline file instead of a default Dockerfile-only build.
- --substitutions=COMMIT_SHA=latest provides the value for $COMMIT_SHA since there is no Git trigger event to populate it.
- The trailing . uploads your entire project directory as the build source.
This build will take 1-2 minutes. You'll see log output for each of the three steps (build, push, deploy) in your terminal.
- Wait for the build to finish. You should see STATUS: SUCCESS at the end of the output.
- Find the Cloud Run service URL by running:
gcloud run services describe chatbot --region=us-central1 --format='value(status.url)'
You should see a URL in the format https://chatbot-XXXXXXXX-uc.a.run.app. This is your chatbot's live public address.
- Copy the URL and open it in your browser to confirm your chatbot is responding.
Build failed with a permission error?
- If you see a permissions error on the deploy step, verify that the Cloud Build service account has the Cloud Run Admin role. Run gcloud projects get-iam-policy YOUR_PROJECT_ID and look for roles/run.admin on your Cloud Build service account.
- If the push step fails, confirm your Artifact Registry repository exists by running gcloud artifacts repositories list --location=us-central1.
- If you see a YAML parse error, check that your file uses 2-space indentation (not tabs) and that all quotes are straight single quotes.
- Help me debug my Cloud Build pipeline failure
Your chatbot is live on the internet, deployed through a complete pipeline. Next, you'll automate this entire process so it runs every time you push code to GitHub.
Automate Deployment with a GitHub Trigger
Your pipeline works. You proved it by running gcloud builds submit manually in the last step. But manually typing a command every time you want to deploy defeats the purpose of CI/CD.
In this step, you will connect your GitHub repository to Cloud Build and create a trigger. Every time you push code to your main branch, Cloud Build will automatically build, push, and deploy your chatbot without any manual intervention.
In this step, get ready to:
- Connect your GitHub repository to Cloud Build using the Cloud Build GitHub App.
- Create a build trigger that fires on every push to the main branch.
- Push a code change and watch Cloud Build deploy it automatically.
Connect your GitHub repository to Cloud Build
For Cloud Build to listen for changes in your GitHub repository, you need to install the Cloud Build GitHub App. This creates a secure connection between GitHub and your GCP project.
Why connect through the Cloud Console?
The GitHub connection requires an OAuth authorization flow that happens in your browser. The Cloud Console walks you through installing the Cloud Build GitHub App on your GitHub account, which grants Cloud Build permission to receive push events from your repository.
- Open the Cloud Build Repositories page in the Google Cloud Console by visiting:
https://console.cloud.google.com/cloud-build/repos
- Make sure your GCP project is selected in the project selector at the top of the page.
- Select the 1st gen tab at the top of the page.
- Click Connect repository.
- Under Select source code management provider, select GitHub (Cloud Build GitHub App).
- Click Continue.
What will I see next?
GitHub will open in a new window asking you to authorize and install the Google Cloud Build App. You need admin permissions on your GitHub repository for this step.
- Click Authorize Google Cloud Build by GoogleCloudBuild on the authorization page.
- Click Install Google Cloud Build when prompted.
- Select Only select repositories and choose your chatbot repository from the dropdown.
- Click Install to install the Cloud Build app.
You will be redirected back to the Cloud Build Repositories page in the Google Cloud Console.
- In the Select repository section, select your GitHub account and your chatbot repository.
- Check the consent checkbox to accept the terms.
- Click Connect.
- Click Done to close the connection panel. Skip the optional "Create a trigger" section for now.
Your GitHub repository now appears on the Repositories page. This means Cloud Build can detect pushes to your repo.
Don't see your repository listed?
If your repository does not appear in the dropdown, click Edit repositories on GitHub to enable it in the Cloud Build GitHub App settings. Then return to Cloud Build and select your repository.
You also need admin-level permissions on the repository for the initial connection.
Help me connect my GitHub repository to Cloud Build.
Create a build trigger for the main branch
A build trigger tells Cloud Build which events to listen for and what to do when they happen. You will create a trigger that watches for pushes to your main branch and runs your cloudbuild.yaml pipeline.
- Create the trigger by running this command in your terminal:
gcloud builds triggers create github \
--name=chatbot-main-trigger \
--repo-owner=[[GITHUB_USERNAME="your-github-username"]] \
--repo-name=[[GITHUB_REPO="your-repo-name"]] \
--branch-pattern="^main$" \
--build-config=cloudbuild.yaml
What does this command do?
- --name=chatbot-main-trigger gives your trigger a descriptive name you can find later.
- --repo-owner and --repo-name point Cloud Build at your specific GitHub repository.
- --branch-pattern="^main$" uses a regex to match only the main branch exactly. The ^ and $ anchors prevent partial matches like "main-dev" from triggering builds.
- --build-config=cloudbuild.yaml tells Cloud Build to use your pipeline configuration file for the build steps.
- Verify the trigger was created by running:
gcloud builds triggers list
You should see chatbot-main-trigger in the output with your GitHub repository listed as the source.
Seeing a permission error?
Make sure you completed the GitHub connection step above first. The trigger command uses 1st gen repository flags (--repo-owner and --repo-name) which require an existing connection to work.
Also double-check that your GitHub username and repository name are spelled exactly as they appear on GitHub (they are case-sensitive).
Help me fix my Cloud Build trigger creation error.
Push a code change and watch the automatic deployment
The trigger is live. Now you will push a small change to your main branch and watch Cloud Build automatically pick it up.
- Open your server.js file (or your main application file) and make a small visible change. For example, update a console log message:
// Add or update a startup message
console.log('Chatbot server starting - deployed via Cloud Build trigger');
- Save server.js.
- Commit and push the change to main by running these commands:
git add .
git commit -m "Test Cloud Build trigger"
git push origin main
- Watch the build start by opening the Cloud Build History page in the Cloud Console:
https://console.cloud.google.com/cloud-build/builds
Within a few seconds of your push, you should see a new build appear with status In progress. The trigger name chatbot-main-trigger will be shown as the source.
What happens during the triggered build?
Cloud Build runs the exact same three steps from your cloudbuild.yaml that you tested manually. It builds the Docker image, pushes it to Artifact Registry with the commit SHA as the tag, and deploys it to Cloud Run.
The $COMMIT_SHA variable is now populated automatically from the Git push event instead of being generated by Cloud Build from a source upload.
- Wait for the build to complete (this takes about 1-2 minutes).
- Confirm the build succeeded by checking that the status changes to a green checkmark.
You can also verify from the terminal by running:
gcloud builds list --limit=1
The output should show your latest build with status SUCCESS and the trigger name chatbot-main-trigger.
Build not starting after your push?
Make sure you pushed to the main branch specifically. Pushes to other branches will not match the ^main$ pattern.
If the build starts but fails, click on the build in the Console to view the logs. The most common issue is a typo in your GitHub username or repository name in the trigger configuration.
Help me debug why my Cloud Build trigger isn't firing.
Your CI/CD pipeline is fully automated. Every push to main now triggers a complete build and deploy cycle. Next up, you will verify that your live chatbot is actually serving requests at its Cloud Run URL.
Verify Your Live Chatbot
Your pipeline is live and your trigger is connected. The final step is to confirm that everything works end-to-end.
You will visit your Cloud Run service URL, verify the chatbot responds, and then push a second code change to prove the full CI/CD loop fires automatically.
In this step, get ready to:
- Confirm your chatbot is responding at its public Cloud Run URL.
- Verify the script tag embed route returns the correct JavaScript snippet.
- Push a code change and watch the pipeline deploy it automatically.
Visit your Cloud Run service URL
Your chatbot is deployed on Cloud Run at a public URL. You need to grab that URL and open it in your browser to confirm the service is healthy.
- Get your Cloud Run service URL by running this command:
gcloud run services describe chatbot --region=us-central1 --format='value(status.url)'
What does this command do?
The --format='value(status.url)' flag extracts just the URL from the full service description. The output is a URL like https://chatbot-xxxxxxxxxx-uc.a.run.app.
- Copy the URL from the terminal output.
- Open a new browser tab and paste the URL into the address bar.
- Press Enter to load the page.
You should see your chatbot's main page load successfully. This confirms Cloud Run is serving your container to the public internet.
Seeing a blank page or error?
- Check that your Express app listens on process.env.PORT. Cloud Run injects PORT=8080 at runtime and your app must use it.
- Verify your server.js file (or whatever entry point your Dockerfile CMD references) exists in the repo and starts the Express server.
- Run gcloud builds list --limit=1 to confirm the latest build finished with status SUCCESS.
Help me debug why my Cloud Run service is returning an error when I visit the URL.
Verify the script tag embed route
Your chatbot serves an embeddable script tag at a dedicated endpoint. End users embed this script on their own sites, so it needs to return valid JavaScript.
- Test the embed route by running this command with your service URL:
curl [[CLOUD_RUN_URL="your Cloud Run URL, e.g. https://chatbot-xxxxxxxxxx-uc.a.run.app"]]/embed.js
Match your actual embed route
If your chatbot uses a different route for the embed script (like /widget.js or /script), replace /embed.js with your actual endpoint path.
You should see JavaScript code returned in your terminal output. This confirms the embed endpoint is working correctly on Cloud Run.
Getting a 404 or empty response?
- Double-check the route path matches what your Express app defines. The path is case-sensitive.
- Make sure the route handler sends a response with Content-Type: application/javascript or text/javascript.
Help me figure out why my embed script route is returning a 404 on Cloud Run.
Push a code change and verify automatic deployment
The true test of a CI/CD pipeline is that it works hands-free. You will make a small change, push it to main, and watch Cloud Build pick it up automatically.
- Open your chatbot project in your code editor.
- Make a small visible change to your app. For example, update a response message, or add a comment with today's date at the top of server.js.
- Save the file.
- Commit and push the change to main by running these commands:
git add .
git commit -m "Test CI/CD pipeline auto-deploy"
git push origin main
What happens next?
The moment your push reaches GitHub, the Cloud Build trigger fires. Cloud Build pulls your code, builds a new container image, pushes it to Artifact Registry, and deploys it to Cloud Run.
The entire process typically completes in about one minute.
- Wait about 60 seconds, then check your build history by running:
gcloud builds list --limit=2
You should see a new build at the top of the list with status SUCCESS. The SOURCE column shows it came from your GitHub repository.
- Refresh your chatbot's Cloud Run URL in your browser.
- Confirm your code change is reflected in the live application.
Your change is live. The pipeline deployed it automatically without any manual intervention.
Don't see the update live?
- Run gcloud builds list --limit=2 and check the status column. If the latest build shows QUEUED or WORKING, wait another minute and refresh.
- If the build shows FAILURE, run gcloud builds log BUILD_ID with the failed build's ID to see what went wrong.
- Make sure you pushed to the main branch specifically. Your trigger only fires on pushes to main.
Help me figure out why my Cloud Build trigger did not fire after I pushed to GitHub.
Secret mission
Add a Staging Environment for Pull Requests
Your pipeline deploys straight to production on every push. What if you could test changes on a separate staging URL before merging? In this secret mission, you'll create a staging environment that deploys automatically when you open a pull request.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. Cloud Run scales to zero and costs nothing when idle, and Artifact Registry gives you 500 MB of free storage, so this project is safe to leave running within free tier limits.
Resources you created in this project:
- A Cloud Run service (chatbot) that serves your chatbot at a public URL.
- An Artifact Registry repository (chatbot-repo) storing your container images.
- A Cloud Build trigger that automatically builds and deploys on pushes to main.
- Container images stored in Artifact Registry.
Keep everything running
No action needed. Choose this if you plan to keep pushing updates or want your chatbot to stay live.
- Your Cloud Run service costs $0 when idle and scales to zero automatically.
- Artifact Registry provides 500 MB of free storage per month.
- Cloud Build gives you 120 free build-minutes per day.
- As long as you stay within these free tier limits, you will not be charged.
Pause - I'll come back to this later
Delete the Cloud Build trigger to stop automatic deployments while keeping your Cloud Run service live. You can redeploy manually when you come back.
- Open the Google Cloud Console and navigate to Cloud Build, then select Triggers.
- Find your trigger and click the three-dot menu on the right.
- Select Delete to remove the trigger.
- Your Cloud Run service remains live and continues to serve traffic at no cost while idle.
- When you are ready to resume, create a new trigger following the same steps from Step 4.
Delete - I don't want to use this again
Remove all project resources and start fresh. Run these commands to delete your Cloud Run service, Artifact Registry repository, and Cloud Build trigger.
- Delete your Cloud Run service by running:
gcloud run services delete chatbot --region=us-central1
- Delete your Artifact Registry repository by running:
gcloud artifacts repositories delete chatbot-repo --location=us-central1
- Delete your Cloud Build trigger by running:
gcloud builds triggers delete chatbot-deploy
- Confirm each deletion when prompted by typing Y.
- Your local files (Dockerfile, .dockerignore, cloudbuild.yaml) remain in your GitHub repository. Delete them manually if you no longer need them.
Nice Work!
Nice Work!
You just built a production CI/CD pipeline on Google Cloud Platform. Every time you push code to main, your chatbot is automatically built, containerized, and deployed to a live URL.
You've learned how to:
- Containerized your Node.js chatbot with a Dockerfile and deployed it to a live Cloud Run URL.
- Created a cloudbuild.yaml pipeline that automatically builds, pushes to Artifact Registry, and deploys your container.
- Connected GitHub to Cloud Build with a trigger that fires on every push to main, giving you a fully automated CI/CD workflow.
- Added a staging environment that deploys on pull requests so you can test changes before merging to production.
Ready to quiz yourself?