<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Filip Lindqvist</title>
    <description>The latest articles on DEV Community by Filip Lindqvist (@filip-lindqvist).</description>
    <link>https://dev.to/filip-lindqvist</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3169292%2F526967ca-1668-46da-bea0-ca0d8fddd8bc.png</url>
      <title>DEV Community: Filip Lindqvist</title>
      <link>https://dev.to/filip-lindqvist</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/filip-lindqvist"/>
    <language>en</language>
    <item>
      <title>Push Images To Artifact Registry Using GitHub Actions &amp; Workload Identity</title>
      <dc:creator>Filip Lindqvist</dc:creator>
      <pubDate>Fri, 16 May 2025 13:15:34 +0000</pubDate>
      <link>https://dev.to/filip-lindqvist/google-cloud-artifact-registry-with-github-actions-using-workload-identity-2h8c</link>
      <guid>https://dev.to/filip-lindqvist/google-cloud-artifact-registry-with-github-actions-using-workload-identity-2h8c</guid>
      <description>&lt;p&gt;Day-to-day, I mainly contribute to &lt;a href="https://elva-group.com/" rel="noopener noreferrer"&gt;Elva&lt;/a&gt;, a powerhouse of AWS experts aiming to help our customers elevate their cloud journeys using serverless.&lt;/p&gt;

&lt;p&gt;However, sometimes life brings you into other platforms like Google Cloud in this case (which I also like a lot). This time, I wanted to set up container deploys as a part of a GitHub Action workflow to push images to Google Cloud Artifact Registry.&lt;/p&gt;

&lt;p&gt;In the past, we primarily established our service-to-service (GitHub-to-Google-Cloud) authentication using service accounts with key files. While service account keys are powerful tools, these long-lived keys can present security challenges if not handled with care. The modern way of doing this is using &lt;a href="https://cloud.google.com/iam/docs/workload-identity-federation" rel="noopener noreferrer"&gt;Workload Identity Federation&lt;/a&gt;, which makes it easier and more secure to use Identity and Access Management (IAM) to grant external identities the necessary IAM roles and rights.&lt;/p&gt;

&lt;p&gt;Let's look at how to set up the workflow file and the necessary Google Cloud configurations to achieve this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 0: Create The Identity Workpool
&lt;/h3&gt;

&lt;p&gt;Before we even touch the GitHub Actions YAML, we need to configure Google Cloud to trust our GitHub Actions workflow. This will be a secure way to allow our GitHub Actions to access Google Cloud resources without needing to manage long-lived service account keys.&lt;/p&gt;

&lt;p&gt;Here's a script that sets up everything you need. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important before you start:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Make sure you have the &lt;code&gt;gcloud&lt;/code&gt; CLI installed and configured.

&lt;ul&gt;
&lt;li&gt;You can install it with: &lt;code&gt;brew install google-cloud-sdk&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;  You'll need to replace placeholder values in the script below.
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# 1. Setup&lt;/span&gt;
&lt;span class="c"&gt;# --- Input Variables (UPDATE THESE VALUES!) ---&lt;/span&gt;
&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-gcp-project-id"&lt;/span&gt;
&lt;span class="nv"&gt;GITHUB_REPO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-github-username/your-github-repo-name"&lt;/span&gt;

&lt;span class="c"&gt;# --- Naming Variables ---&lt;/span&gt;
&lt;span class="c"&gt;# Name for the new service account, identity pool and identity provider, change if you want/need but make sure to adhere to the kebab-case without special chars.  &lt;/span&gt;
&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github-deployer-account"&lt;/span&gt;
&lt;span class="nv"&gt;GCLOUD_IDENTITY_POOL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github-deployer-auth-pool"&lt;/span&gt;
&lt;span class="nv"&gt;GCLOUD_IDENTITY_PROVIDER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"github-deployer-auth-provider"&lt;/span&gt;

&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.iam.gserviceaccount.com"&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Starting Workload Identity Federation setup for &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
 project: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; and repo: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GITHUB_REPO&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 2. Enable the IAM Credentials API&lt;/span&gt;
gcloud services &lt;span class="nb"&gt;enable &lt;/span&gt;iamcredentials.googleapis.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error enabling IAM Credentials API. Exiting."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 3. Create a new service account&lt;/span&gt;
gcloud iam service-accounts create &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--display-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"GitHub Actions Deployer Account for &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GITHUB_REPO&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 4. Grant the service account permission to write to Artifact Registry&lt;/span&gt;
gcloud projects add-iam-policy-binding &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"serviceAccount:&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT_EMAIL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/artifactregistry.writer"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error granting Artifact Registry Writer role. Exiting."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 5. Create a Workload Identity Pool&lt;/span&gt;
gcloud iam workload-identity-pools create &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_IDENTITY_POOL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"global"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--display-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"GitHub Actions Auth Pool"&lt;/span&gt;

&lt;span class="c"&gt;# 6. Get the full ID of the Workload Identity Pool&lt;/span&gt;
&lt;span class="nv"&gt;GCLOUD_WORKLOAD_IDENTITY_POOL_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud iam workload-identity-pools describe &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_IDENTITY_POOL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"global"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value(name)"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_WORKLOAD_IDENTITY_POOL_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error fetching Workload Identity Pool ID. Exiting."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 7. Create an OIDC Workload Identity Provider in the pool..."&lt;/span&gt;
gcloud iam workload-identity-pools providers create-oidc &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_IDENTITY_PROVIDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"global"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--workload-identity-pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_IDENTITY_POOL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--display-name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"GitHub Actions Auth Provider"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attribute-mapping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"google.subject=assertion.sub,attribute.actor=assertion.actor,attribute.repository=assertion.repository"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--issuer-uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://token.actions.githubusercontent.com"&lt;/span&gt;

&lt;span class="c"&gt;# 8. Allow authentications from the GitHub OIDC provider to impersonate the Google Cloud service account&lt;/span&gt;
&lt;span class="c"&gt;# This binds the GitHub repo to the service account via the WIF pool and provider.&lt;/span&gt;
gcloud iam service-accounts add-iam-policy-binding &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT_EMAIL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"roles/iam.workloadIdentityUser"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--member&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"principalSet://iam.googleapis.com/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_WORKLOAD_IDENTITY_POOL_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/attribute.repository/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GITHUB_REPO&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error binding service account for impersonation. Exiting."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# 9. Get the full ID of the Workload Identity Provider (needed for GitHub Secrets)&lt;/span&gt;
&lt;span class="nv"&gt;GCP_WORKLOAD_IDENTITY_PROVIDER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gcloud iam workload-identity-pools providers describe &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_IDENTITY_PROVIDER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"global"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--workload-identity-pool&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_IDENTITY_POOL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value(name)"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCP_WORKLOAD_IDENTITY_PROVIDER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Error fetching Workload Identity Provider ID. Exiting."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"--- GitHub Secrets ---"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Add these to your GitHub repository secrets:"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"GCP_PROJECT_ID: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_PROJECT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"GCP_WORKLOAD_IDENTITY_PROVIDER_ID: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCP_WORKLOAD_IDENTITY_PROVIDER_ID&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"GCP_SERVICE_ACCOUNT_EMAIL: &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GCLOUD_SERVICE_ACCOUNT_EMAIL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Setup complete!"&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What this script does:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Setup&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;GCLOUD_PROJECT&lt;/code&gt;: You &lt;strong&gt;must&lt;/strong&gt; set this to your Google Cloud Project ID.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;GITHUB_REPO&lt;/code&gt;: You &lt;strong&gt;must&lt;/strong&gt; set this to your GitHub repository in the format &lt;code&gt;username/repository-name&lt;/code&gt; (e.g., &lt;code&gt;my-cool-user/my-awesome-app&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Enables IAM Credentials API&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This API is necessary for your GitHub Action to mint short-lived credentials for the service account.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Creates a Service Account&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This is the Google Cloud identity that your GitHub Action will impersonate. It's like a robot user for your automation.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Grants Artifact Registry Permissions&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This gives the newly created service account permission to push images to Google Cloud Artifact Registry.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Creates a Workload Identity Pool&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This pool is a container for identity providers. It helps organize how external identities (like those from GitHub) are managed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Gets the Workload Identity Pool ID&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This retrieves the unique identifier for the pool, which is needed in later steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Creates an OIDC Workload Identity Provider&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This is the key part. It tells Google Cloud to trust OIDC tokens issued by GitHub Actions (&lt;code&gt;https://token.actions.githubusercontent.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  The attribute-mapping tells Google Cloud how to map information from the GitHub OIDC token (like the repository name) to attributes Google Cloud can understand. This allows you to restrict which GitHub repositories can use this identity provider.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Allows GitHub to Impersonate the Service Account&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  This crucial step links everything together. It says that principals (in this case, your GitHub Action running in the specified &lt;code&gt;GITHUB_REPO&lt;/code&gt;) that authenticate through the OIDC provider are allowed to impersonate the service account we created. The &lt;code&gt;principalSet&lt;/code&gt; specifically targets your repository.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Outputs IDs for GitHub Secrets&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  The script will print out the &lt;code&gt;GCP_PROJECT_ID&lt;/code&gt;, &lt;code&gt;GCP_WORKLOAD_IDENTITY_PROVIDER_ID&lt;/code&gt; (this will be the full path like &lt;code&gt;projects/your-gcp-project-id/locations/global/workloadIdentityPools/github-deployer-auth-pool/providers/github-deployer-auth-provider&lt;/code&gt;), and &lt;code&gt;GCP_SERVICE_ACCOUNT_EMAIL&lt;/code&gt;. You must add these as secrets in your GitHub repository settings so the Action workflow can use them. You do this by going to your Github repo, then &lt;code&gt;Settings &amp;gt; Secrets and variables &amp;gt; Actions &amp;gt; New repository secret&lt;/code&gt;. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After running this script successfully and setting up the GitHub secrets accordingly, Google Cloud will be ready for your GitHub Action to authenticate by itself. &lt;/p&gt;

&lt;p&gt;Now, let's look at the GitHub Actions workflow YAML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Container&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="c1"&gt;# Permissions are important for the worklaod identity federation to work&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;read'&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;write'&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... our steps will go here&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This initial block defines the basic triggers (when the workflow runs) and the environment (Ubuntu) for our job. It will run when we push to the main branch or when a pull request that targets the main branch.&lt;/p&gt;

&lt;p&gt;The important part to note is the permissions block. We need contents: 'read' to allow the action to read your repository's content (which &lt;code&gt;actions/checkout&lt;/code&gt; does). More importantly, &lt;code&gt;id-token: 'write'&lt;/code&gt; is crucial. This permission allows the GitHub Actions runner to request an OIDC (OpenID Connect) token, which we'll use to securely authenticate with Google Cloud, thanks to the Workload Identity Federation setup we just did.&lt;/p&gt;

&lt;p&gt;Now for the actual steps involved in the job.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Checkout Code And Set Up Docker&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First things first, we need to get our code and prepare Docker for building our image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This initial part combines two actions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;actions/checkout@v4&lt;/code&gt;: This action checks out your repository.&lt;/li&gt;
&lt;li&gt; &lt;code&gt;docker/setup-buildx-action@v3&lt;/code&gt;: This action installs and configures Docker.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Authenticate to Google Cloud&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To push our Docker image to Google Cloud Artifact Registry, our GitHub Action needs to authenticate with Google Cloud. &lt;br&gt;
This step uses the Workload Identity Federation we configured in Step 0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;google-github-actions/auth@v2'&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auth&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;token_format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;access_token&lt;/span&gt;
        &lt;span class="na"&gt;project_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GCP_PROJECT_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;workload_identity_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;service_account&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;id: auth&lt;/code&gt;: We give this step an ID, auth. This is useful because this action outputs an access token that we can use in subsequent steps. See &lt;code&gt;steps.auth.outputs.*&lt;/code&gt; in the next step. &lt;/li&gt;
&lt;li&gt;  &lt;code&gt;project_id&lt;/code&gt;: Your Google Cloud Project ID. This comes from the &lt;code&gt;GCP_PROJECT_ID&lt;/code&gt; secret you created from the script's output.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;workload_identity_provider&lt;/code&gt;: The full identifier of your Workload Identity Provider. This comes from the &lt;code&gt;WORKLOAD_IDENTITY_PROVIDER_ID&lt;/code&gt; secret.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;service_account&lt;/code&gt;: The email address of the Google Cloud service account that GitHub Actions will impersonate. This comes from the &lt;code&gt;GCP_SERVICE_ACCOUNT_EMAIL&lt;/code&gt; secret.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Log in to Google Cloud Artifact Registry&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we have an access token from Google Cloud, we can use it to log in to Artifact Registry. &lt;br&gt;
Artifact Registry uses standard Docker authentication mechanisms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;europe-docker.pkg.dev&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oauth2accesstoken&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.auth.outputs.access_token&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;registry&lt;/code&gt;: This is the hostname of the Artifact Registry you want to push to. For example, if your images are in the europe region, it would be &lt;code&gt;europe-docker.pkg.dev&lt;/code&gt;. Adjust this based on your registry's region.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;username&lt;/code&gt;: When using an OAuth2 access token with Google Artifact Registry, the username is always &lt;code&gt;oauth2accesstoken&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;password&lt;/code&gt;: This is where we use the access token obtained in the previous step. &lt;code&gt;${{ steps.auth.outputs.access_token }}&lt;/code&gt; refers to the output named &lt;code&gt;access_token&lt;/code&gt; from the step with the ID &lt;code&gt;auth&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Build and Push Docker Image&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, we get to the part where we build our Docker image and push it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push Docker image&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v6&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
        &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64,linux/arm64&lt;/span&gt;
        &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.ref == 'refs/heads/main' &amp;amp;&amp;amp; github.event_name != 'pull_request' }}&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;europe-docker.pkg.dev/${{secrets.GCP_PROJECT_ID }}/images/my-container-name:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;platforms: linux/amd64,linux/arm64&lt;/code&gt;: This is an example of building for multiple platforms. Buildx makes this easy. You can adjust this to the platforms you need.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;push: ${{ github.ref == 'refs/heads/main' &amp;amp;&amp;amp; github.event_name != 'pull_request' }}&lt;/code&gt;: This is a crucial part for controlling when the image is actually pushed. We only want to push if the current Git reference is &lt;code&gt;refs/heads/main&lt;/code&gt; (i.e., we're on the main branch) AND the event that triggered the workflow is &lt;em&gt;not&lt;/em&gt; a pull_request. This prevents pushing images for every commit on a pull request branch, but still builds them (which can be useful for testing).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;tags&lt;/code&gt;: This specifies the tag for your Docker image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Optimizing Builds with Caching&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Docker builds can sometimes be slow, especially if you have a large image or many dependencies. Caching can significantly speed up this process by reusing layers from previous builds. The &lt;code&gt;docker/build-push-action&lt;/code&gt; supports caching with GitHub Actions cache.&lt;/p&gt;

&lt;p&gt;Let's update our step to include GitHub-powered caching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push Docker image&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v6&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# ... add these lines&lt;/span&gt;
        &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=gha&lt;/span&gt;
        &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=gha,mode=max&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;cache-from: type=gha&lt;/code&gt;: This tells the action to attempt to pull cache layers from the GitHub Actions cache.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;cache-to: type=gha,mode=max&lt;/code&gt;: This tells the action to save the build cache to the GitHub Actions cache. Additionally, &lt;code&gt;mode=max&lt;/code&gt; adds it will include all layers, which provides the best potential for cache hits on subsequent runs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using &lt;code&gt;type=gha&lt;/code&gt; is convenient because it uses the built-in GitHub Actions caching mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Wrapping Up: The Complete Workflow&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;So, putting it all together, here's our final YAML for the GitHub Action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build Container&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;read'&lt;/span&gt;
      &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;write'&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v3&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;google-github-actions/auth@v2'&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;auth&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;token_format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;access_token&lt;/span&gt;
        &lt;span class="na"&gt;project_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.GCP_PROJECT_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;workload_identity_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER_ID }}&lt;/span&gt;
        &lt;span class="na"&gt;service_account&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GCP_SERVICE_ACCOUNT_EMAIL }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;europe-docker.pkg.dev&lt;/span&gt;
        &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oauth2accesstoken&lt;/span&gt;
        &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.auth.outputs.access_token&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push Docker image&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v6&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
        &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux/amd64,linux/arm64&lt;/span&gt;
        &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.ref == 'refs/heads/main' &amp;amp;&amp;amp; github.event_name != 'pull_request' }}&lt;/span&gt;
        &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;europe-docker.pkg.dev/${{secrets.GCP_PROJECT_ID }}/images/my-container-name:latest&lt;/span&gt;
        &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=gha&lt;/span&gt;
        &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=gha,mode=max&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it! &lt;/p&gt;

&lt;p&gt;First, ensure you've run the setup script (Step 0) in your Google Cloud environment and configured the necessary GitHub secrets. &lt;/p&gt;

&lt;p&gt;Then, this workflow will check out your code, authenticate to Google Cloud, log in to Artifact Registry, and then build and push your Docker image, complete with caching to speed things up. &lt;/p&gt;

&lt;p&gt;Remember to replace placeholder values like &lt;code&gt;europe-docker.pkg.dev&lt;/code&gt; and &lt;code&gt;my-container-name&lt;/code&gt; with your own values.&lt;br&gt;
You'll also need to ensure your Dockerfile is in the root of your repository (&lt;code&gt;context: .&lt;/code&gt;) or adjust the path accordingly.&lt;/p&gt;

&lt;p&gt;This setup provides a secure and efficient way to manage your Docker image deployments to Google Cloud.&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>githubactions</category>
      <category>devops</category>
      <category>workloadidentity</category>
    </item>
  </channel>
</rss>
