Orchestrating Google Cloud Run Deployments via GitHub Actions

Integrating Google Cloud Run with GitHub Actions represents a critical intersection of serverless container deployment and continuous integration/continuous deployment (CI/CD) automation. The google-github-actions/deploy-cloudrun action serves as the primary mechanism for this integration, enabling developers to deploy container images or source code directly to Google Cloud Run services and jobs. This automation extends beyond simple deployment; it manages traffic routing, environment configuration, and service account authentication, ultimately exposing the resulting service URL as a GitHub Actions output for downstream workflow steps. By leveraging this tool, organizations can streamline their release pipelines, ensuring that infrastructure changes are tightly coupled with code changes while maintaining rigorous security standards through proper authorization mechanisms.

Authentication and Authorization Strategies

The foundation of a secure deployment pipeline lies in how the GitHub Actions runner authenticates with Google Cloud. The deploy-cloudrun action does not handle authentication directly but relies on the google-github-actions/auth action or Application Default Credentials (ADC) to establish a secure identity. The service account used for deployment must possess specific roles, most notably the Cloud Run Admin role (roles/run.admin). This role grants the necessary permissions to create, update, and delete services, as well as get and set Identity and Access Management (IAM) policies. Additionally, the service account must be a member of the Compute Engine default service account ([email protected]) with the Service Account User role to ensure seamless operation within the Google Cloud ecosystem.

There are two primary methods for establishing this authentication context. The first and most secure method for new implementations involves Workload Identity Federation. This approach allows GitHub Actions to authenticate as a Google Cloud service account without storing static secrets. This requires configuring a workload identity provider and specifying the service account in the workflow. The second method leverages Application Default Credentials, which is particularly useful when using self-hosted runners hosted on Google Cloud infrastructure. In this scenario, the action automatically detects and uses the credentials attached to the instance, eliminating the need for explicit credential management in the workflow file.

yaml jobs: deploy: runs-on: ubuntu-latest permissions: contents: 'read' id-token: 'write' steps: - uses: 'actions/checkout@v4' - uses: 'google-github-actions/auth@v3' with: workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider' service_account: '[email protected]' - id: 'deploy' uses: 'google-github-actions/deploy-cloudrun@v3' with: service: 'hello-cloud-run' image: 'us-docker.pkg.dev/cloudrun/container/hello:latest'

For environments where self-hosted runners are utilized within Google Cloud, the authentication step can be omitted if the runner instance itself is configured with the appropriate service account. The action will automatically detect and use the Application Default Credentials of the instance, simplifying the workflow configuration significantly.

Deployment Targets: Services and Jobs

The deploy-cloudrun action is versatile, supporting deployment to both Cloud Run services and Cloud Run jobs. Services are designed for request-driven workloads, exposing an endpoint that responds to HTTP requests, while jobs are intended for batch processing tasks that execute once or on a schedule. The action determines the target type based on the parameters provided. If the service parameter is specified, the action executes gcloud run deploy. Conversely, if the job parameter is used, it executes gcloud jobs deploy. It is crucial to note that these parameters are mutually exclusive; one must be provided unless using the metadata parameter for advanced configurations.

When deploying to a service, the action manages the lifecycle of the revision and the traffic routing. For jobs, the focus shifts to execution timing and completion status. The action provides a wait parameter that is exclusive to jobs. When set to true, the GitHub Actions workflow will pause and wait for the job to complete before exiting, allowing subsequent steps to depend on the successful completion of the batch task. This feature is particularly useful for data processing pipelines where downstream steps require the results of the job.

yaml steps: - id: 'deploy-job' uses: 'google-github-actions/deploy-cloudrun@v3' with: job: 'my-batch-job' image: 'us-docker.pkg.dev/cloudrun/container/hello:latest' wait: 'true'

For services, the no_traffic parameter offers control over the initial exposure of the new revision. When set to true, the newly deployed revision will not receive traffic immediately. This is beneficial for staging deployments or when manual verification is required before promoting the new version to production traffic. This parameter only applies to services and has no effect on jobs.

Traffic Management and Revision Control

One of the most powerful aspects of the deploy-cloudrun action is its ability to manage traffic routing dynamically. This is achieved through the revision_traffic and tag_traffic parameters. These parameters allow for sophisticated traffic splitting, enabling blue-green deployments, canary releases, or A/B testing. The revision_traffic parameter accepts a comma-separated list of revision traffic assignments, where each assignment specifies a revision identifier and a percentage of traffic. A special tag, LATEST, can be used to refer to the most recently created revision, simplifying the promotion of new versions to 100% traffic.

yaml with: revision_traffic: 'LATEST=100'

Similarly, the tag_traffic parameter allows for traffic assignment based on tags rather than specific revision IDs. This provides a more stable way to manage traffic, as tags can persist across revisions. It is important to note that revision_traffic and tag_traffic are mutually exclusive; only one can be used in a single deployment step. This distinction allows teams to choose between explicit revision control for precise rollbacks or tag-based management for smoother release cycles.

The action also supports the tag parameter, which assigns a specific traffic tag to the newly created revision. This is useful for creating named references to specific deployments, which can then be used in subsequent steps for verification or rollback.

Environment Configuration and Secrets

Configuring environment variables and secrets is a critical part of deploying applications to Cloud Run. The deploy-cloudrun action supports multiple ways to inject configuration data into the deployed service or job. The env_vars parameter allows for defining environment variables directly in the workflow file. These can be specified as a newline-separated list or a YAML block. It is important to handle whitespace correctly; leading and trailing whitespace is trimmed unless the values are explicitly quoted.

yaml with: env_vars: |- FRUIT=apple SENTENCE=" this will retain leading and trailing spaces "

For more complex configurations, the env_vars_file parameter allows for specifying a file containing the environment variables. If both env_vars and env_vars_file are provided, the values defined in env_vars take precedence. The env_vars_update_strategy parameter controls how these values are applied. The default strategy is merge, which combines the new values with existing ones on the Cloud Run service. Alternatively, setting this to overwrite makes the GitHub Action the authoritative source, replacing all existing environment variables with those specified in the workflow.

Secrets are handled separately to enhance security. The secrets parameter accepts a list of KEY=VALUE pairs, which can be comma-separated or newline-separated. Keys or values that contain separators must be escaped with a backslash. This integration allows for secure injection of sensitive data, such as database passwords or API keys, without exposing them in the workflow logs or the repository.

Advanced Configuration and Metadata

For scenarios that require more granular control, the deploy-cloudrun action provides the flags parameter. This allows users to pass additional Cloud Run flags directly to the underlying gcloud command. This is particularly useful for applying advanced features that are not exposed via the action's standard parameters, such as adding Cloud SQL instances or customizing container resources. Flags that include other flags must be quoted to ensure proper parsing.

yaml with: flags: '--add-cloudsql-instances=... "--args=-X=123"'

It is crucial to note that the GitHub Action does not parse or validate these flags. The responsibility for ensuring that the flags are valid for the specific gcloud version and subcommand lies with the user. This flexibility comes with the trade-off of requiring a deeper understanding of the underlying Cloud Run CLI.

The action also manages metadata through the labels and annotations parameters. Labels are key-value pairs that can be used to organize and filter Cloud Run resources. The action automatically applies special labels indicating the deployment source, such as managed-by: github-actions and commit-sha: <sha>. These labels enhance the user experience by providing visibility into the deployment lineage. The skip_default_labels parameter can be set to true to prevent these automatic labels from being applied, which may be desired in environments with strict labeling policies.

Technical Requirements and Runner Compatibility

The deploy-cloudrun action is built on Node.js 24. This version requirement has significant implications for the GitHub Actions runners used in the deployment pipeline. For users relying on GitHub-hosted runners, this is generally not an issue as the hosted environments are updated regularly. However, for organizations using self-hosted GitHub Actions runners, it is critical to ensure that the runner version supports Node.js 24 or newer. Failure to meet this requirement will result in deployment failures.

The action is provided by a third party and is not certified by GitHub. This means that it operates under separate terms of service, privacy policy, and support documentation. Users should be aware of this distinction and refer to the official documentation for the google-github-actions repository for support and updates. The action is verified on the GitHub Marketplace, indicating that it meets certain security and reliability standards, but it is still important to review the code and permissions before integration into a production pipeline.

Practical Implementation Example

A typical implementation involves a workflow that authenticates with Google Cloud, sets up the Cloud SDK, builds and pushes a Docker image, and then deploys it to Cloud Run. The following example demonstrates a comprehensive workflow that incorporates authentication, environment variable management, and traffic routing.

```yaml
jobs:
build-and-deploy:
name: Setup, Build, and Deploy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

  - name: Authenticate with Google Cloud
    id: "auth"
    uses: google-github-actions/[email protected]
    with:
      credentials_json: "${{ secrets.GCP_SA_KEY }}"

  - name: Set up Cloud SDK
    uses: google-github-actions/setup-gcloud@v1

  - name: Authorize Docker push
    run: gcloud auth configure-docker ${{ secrets.REGION }}-docker.pkg.dev

  - name: Build and tag the docker image
    run: |-
      docker build --build-arg NODE_ENV=dev -t ${{ secrets.REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/${{ secrets.ARTIFACT_REGISTRY_NAME }}/${{ secrets.DEV_APP_NAME }}:${{ github.sha }} .
      docker push ${{ secrets.REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/${{ secrets.ARTIFACT_REGISTRY_NAME }}/${{ secrets.DEV_APP_NAME }}:${{ github.sha }}

  - name: Deploy to Cloud Run
    id: 'deploy'
    uses: 'google-github-actions/deploy-cloudrun@v3'
    with:
      service: '${{ secrets.DEV_APP_NAME }}'
      image: '${{ secrets.REGION }}-docker.pkg.dev/${{ secrets.PROJECT_ID }}/${{ secrets.ARTIFACT_REGISTRY_NAME }}/${{ secrets.DEV_APP_NAME }}:${{ github.sha }}'
      env_vars: |-
        NODE_ENV=dev
        API_KEY=${{ secrets.API_KEY }}
      revision_traffic: 'LATEST=100'

```

This example highlights the integration of various components, from authentication and Docker image building to deployment and traffic management. The use of secrets for sensitive information and the structured approach to environment variables demonstrate best practices for secure and maintainable CI/CD pipelines.

Conclusion

The google-github-actions/deploy-cloudrun action provides a robust and flexible solution for deploying to Google Cloud Run from GitHub Actions. By supporting both services and jobs, offering granular control over traffic routing, and integrating seamlessly with Google Cloud's authentication mechanisms, it empowers teams to build efficient and secure CI/CD pipelines. The ability to manage environment variables, secrets, and labels through a unified interface reduces operational overhead and minimizes the risk of configuration errors. As organizations continue to adopt serverless architectures, the integration of Cloud Run with GitHub Actions will become increasingly important for maintaining agility and reliability in software delivery. Understanding the nuances of authentication, traffic management, and runner compatibility is essential for leveraging this tool to its full potential.

Sources

  1. GitHub Marketplace - Deploy to Cloud Run
  2. Creating a GitHub Action for Deploying to Google Cloud Run Using Docker

Related Posts