Cloud Build kullanarak değişikliklerinizi GitHub'dan Cloud Run'a otomatik olarak dağıtma

1. Giriş

Genel Bakış

Bu codelab'de, kaynak kodu değişikliklerinizi bir GitHub deposuna aktardığınızda Cloud Run'ı uygulamanızın yeni sürümlerini otomatik olarak derleyip dağıtacak şekilde yapılandıracaksınız.

Bu demo uygulaması, kullanıcı verilerini firestore'a kaydeder ancak verilerin yalnızca bir kısmı düzgün şekilde kaydedilir. Sürekli dağıtımlar yapılandıracaksınız. Bu şekilde GitHub deponuza hata düzeltmesi aktardığınızda düzeltme yeni bir düzeltmede otomatik olarak kullanıma sunulacak.

Neler öğreneceksiniz?

  • Cloud Shell Düzenleyici ile Express web uygulaması yazma
  • Sürekli dağıtımlar için GitHub hesabınızı Google Cloud'a bağlayın
  • Uygulamanızı otomatik olarak Cloud Run'a dağıtma
  • HTMX ve TailwindCSS'yi nasıl kullanacağınızı öğrenin

2. Kurulum ve Gereksinimler

Ön koşullar

  • GitHub hesabınız var ve kod oluşturma ve kod depolarına aktarma konusunda bilgi sahibisiniz.
  • Cloud Console'a giriş yaptınız.
  • Daha önce bir Cloud Run hizmeti dağıttınız. Örneğin, başlamak için kaynak kodundan web hizmeti dağıtma başlıklı makaledeki adımları uygulayabilirsiniz.

Cloud Shell'i etkinleştirme

  1. Cloud Console'da, Cloud Shell'i etkinleştir d1264ca30785e435.png simgesini tıklayın.

cb81e7c8e34bc8d.png

Cloud Shell'i ilk kez başlatıyorsanız ne olduğunu açıklayan bir ara ekran gösterilir. Ara bir ekran görüntülendiyse Devam'ı tıklayın.

d95252b003979716.png

Temel hazırlık ve Cloud Shell'e bağlanmak yalnızca birkaç dakika sürer.

7833d5e1c5d18f54.png

Gereken tüm geliştirme araçları bu sanal makinede yüklüdür. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud'da çalışarak ağ performansını ve kimlik doğrulamasını büyük ölçüde iyileştirir. Bu codelab'deki çalışmalarınızın tamamı olmasa bile büyük bir kısmı tarayıcıyla yapılabilir.

Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin proje kimliğinize ayarlandığını göreceksiniz.

  1. Kimlik doğrulamanızın tamamlandığını onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud auth list

Komut çıkışı

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. gcloud komutunun projenizi bildiğini onaylamak için Cloud Shell'de aşağıdaki komutu çalıştırın:
gcloud config list project

Komut çıkışı

[core]
project = <PROJECT_ID>

Doğru değilse aşağıdaki komutla ayarlayabilirsiniz:

gcloud config set project <PROJECT_ID>

Komut çıkışı

Updated property [core/project].

3. API'leri Etkinleştirin ve Ortam Değişkenlerini Ayarlayın

API'leri etkinleştir

Bu codelab'de aşağıdaki API'lerin kullanılması gerekir. Bu API'leri şu komutu çalıştırarak etkinleştirebilirsiniz:

gcloud services enable run.googleapis.com \
    cloudbuild.googleapis.com \
    firestore.googleapis.com \
    iamcredentials.googleapis.com

Ortam değişkenlerini ayarlama

Bu codelab'de kullanılacak ortam değişkenlerini ayarlayabilirsiniz.

REGION=<YOUR-REGION>
PROJECT_ID=<YOUR-PROJECT-ID>
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
SERVICE_ACCOUNT="firestore-accessor"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

4. Hizmet hesabı oluşturma

Bu hizmet hesabı, Cloud Run tarafından Vertex AI Gemini API'yi çağırmak için kullanılır. Bu hizmet hesabı ayrıca Firestore okuma, yazma ve Secret Manager'daki gizli anahtarları okuma iznine de sahip olur.

Öncelikle şu komutu çalıştırarak hizmet hesabını oluşturun:

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run access to Firestore"

Şimdi hizmet hesabına Firestore'a okuma ve yazma erişimi verin.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/datastore.user

5. Firebase projesi oluşturma ve yapılandırma

  1. Firebase konsolunda Proje ekle'yi tıklayın.
  2. <YOUR_PROJECT_ID> değerini girin mevcut Google Cloud projelerinizden birine Firebase'i ekleyin
  3. İstenirse Firebase şartlarını inceleyip kabul edin.
  4. Devam'ı tıklayın.
  5. Firebase faturalandırma planını onaylamak için Planı Onayla'yı tıklayın.
  6. Bu codelab için Google Analytics'i etkinleştirmek isteğe bağlıdır.
  7. Firebase'i ekle'yi tıklayın.
  8. Proje oluşturulduktan sonra Continue (Devam) seçeneğini tıklayın.
  9. Build (Derleme) menüsünde, Firestore database'i (Firestore veritabanı) tıklayın.
  10. Create database'i (Veritabanı oluştur) tıklayın.
  11. Konum açılır menüsünden bölgenizi seçip İleri'yi tıklayın.
  12. Varsayılan Üretim modunda başlat seçeneğini kullanın, ardından Oluştur'u tıklayın.

6. Uygulamayı yazma

İlk olarak, kaynak kodu için bir dizin oluşturun ve bu dizin için cd'yi kullanın.

mkdir cloud-run-github-cd-demo && cd $_

Ardından, aşağıdaki içeriğe sahip bir package.json dosyası oluşturun:

{
  "name": "cloud-run-github-cd-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node app.js",
    "nodemon": "nodemon app.js",
    "tailwind-dev": "npx tailwindcss -i ./input.css -o ./public/output.css --watch",
    "tailwind": "npx tailwindcss -i ./input.css -o ./public/output.css",
    "dev": "npm run tailwind && npm run nodemon"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@google-cloud/firestore": "^7.3.1",
    "axios": "^1.6.7",
    "express": "^4.18.2",
    "htmx.org": "^1.9.10"
  },
  "devDependencies": {
    "nodemon": "^3.1.0",
    "tailwindcss": "^3.4.1"
  }
}

İlk olarak aşağıdaki içerikle bir app.js kaynak dosyası oluşturun. Bu dosya, hizmetin giriş noktasını ve uygulamanın ana mantığını içerir.

const express = require("express");
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
const path = require("path");
const { get } = require("axios");

const { Firestore } = require("@google-cloud/firestore");
const firestoreDb = new Firestore();

const fs = require("fs");
const util = require("util");
const { spinnerSvg } = require("./spinnerSvg.js");

const service = process.env.K_SERVICE;
const revision = process.env.K_REVISION;

app.use(express.static("public"));

app.get("/edit", async (req, res) => {
    res.send(`<form hx-post="/update" hx-target="this" hx-swap="outerHTML">
                <div>
  <p>
    <label>Name</label>    
    <input class="border-2" type="text" name="name" value="Cloud">
    </p><p>
    <label>Town</label>    
    <input class="border-2" type="text" name="town" value="Nibelheim">
    </p>
  </div>
  <div class="flex items-center mr-[10px] mt-[10px]">
  <button class="btn bg-blue-500 text-white px-4 py-2 rounded-lg text-center text-sm font-medium mr-[10px]">Submit</button>
  <button class="btn bg-gray-200 text-gray-800 px-4 py-2 rounded-lg text-center text-sm font-medium mr-[10px]" hx-get="cancel">Cancel</button>  
                ${spinnerSvg} 
                </div>
  </form>`);
});

app.post("/update", async function (req, res) {
    let name = req.body.name;
    let town = req.body.town;
    const doc = firestoreDb.doc(`demo/${name}`);

    //TODO: fix this bug
    await doc.set({
        name: name
        /* town: town */
    });

    res.send(`<div hx-target="this" hx-swap="outerHTML" hx-indicator="spinner">
                <p>
                <div><label>Name</label>: ${name}</div>
                </p><p>
                <div><label>Town</label>: ${town}</div>
                </p>
                <button
                    hx-get="/edit"
                    class="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm font-medium mt-[10px]"
                >
                    Click to update
                </button>               
            </div>`);
});

app.get("/cancel", (req, res) => {
    res.send(`<div hx-target="this" hx-swap="outerHTML">
                <p>
                <div><label>Name</label>: Cloud</div>
                </p><p>
                <div><label>Town</label>: Nibelheim</div>
                </p>
                <div>
                <button
                    hx-get="/edit"
                    class="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm font-medium mt-[10px]"
                >
                    Click to update
                </button>                
                </div>
            </div>`);
});

const port = parseInt(process.env.PORT) || 8080;
app.listen(port, async () => {
    console.log(`booth demo: listening on port ${port}`);

    //serviceMetadata = helper();
});

app.get("/helper", async (req, res) => {
    let region = "";
    let projectId = "";
    let div = "";

    try {
        // Fetch the token to make a GCF to GCF call
        const response1 = await get(
            "http://metadata.google.internal/computeMetadata/v1/project/project-id",
            {
                headers: {
                    "Metadata-Flavor": "Google"
                }
            }
        );

        // Fetch the token to make a GCF to GCF call
        const response2 = await get(
            "http://metadata.google.internal/computeMetadata/v1/instance/region",
            {
                headers: {
                    "Metadata-Flavor": "Google"
                }
            }
        );

        projectId = response1.data;
        let regionFull = response2.data;
        const index = regionFull.lastIndexOf("/");
        region = regionFull.substring(index + 1);

        div = `
        <div>
        This created the revision <code>${revision}</code> of the 
        Cloud Run service <code>${service}</code> in <code>${region}</code>
        for project <code>${projectId}</code>.
        </div>`;
    } catch (ex) {
        // running locally
        div = `<div> This is running locally.</div>`;
    }

    res.send(div);
});

spinnerSvg.js adlı bir dosya oluştur

module.exports.spinnerSvg = `<svg id="spinner" alt="Loading..."
                    class="htmx-indicator animate-spin -ml-1 mr-3 h-5 w-5 text-blue-500"
                    xmlns="http://www.w3.org/2000/svg"
                    fill="none"
                    viewBox="0 0 24 24"
                >
                    <circle
                        class="opacity-25"
                        cx="12"
                        cy="12"
                        r="10"
                        stroke="currentColor"
                        stroke-width="4"
                    ></circle>
                    <path
                        class="opacity-75"
                        fill="currentColor"
                        d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
                    ></path>
                </svg>`;

tailwindCSS için bir input.css dosyası oluşturun

@tailwind base;
@tailwind components;
@tailwind utilities;

tailwindCSS için tailwind.config.js dosyasını oluşturun.

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: ["./**/*.{html,js}"],
    theme: {
        extend: {}
    },
    plugins: []
};

Sonra da bir .gitignore dosyası oluşturun.

node_modules/

npm-debug.log
coverage/

package-lock.json

.DS_Store

Şimdi yeni bir public dizini oluşturun.

mkdir public
cd public

Ayrıca bu herkese açık dizinde, kullanıcı arabirimi için htmx kullanacak olan index.html dosyasını oluşturun.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta
            name="viewport"
            content="width=device-width, initial-scale=1.0"
        />
        <script
            src="https://unpkg.com/htmx.org@1.9.10"
            integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC"
            crossorigin="anonymous"
        ></script>

        <link href="./output.css" rel="stylesheet" />
        <title>Demo 1</title>
    </head>
    <body
        class="font-sans bg-body-image bg-cover bg-center leading-relaxed"
    >
        <div class="container max-w-[700px] mt-[50px] ml-auto mr-auto">
            <div class="hero flex items-center">                    
                <div class="message text-base text-center mb-[24px]">
                    <h1 class="text-2xl font-bold mb-[10px]">
                        It's running!
                    </h1>
                    <div class="congrats text-base font-normal">
                        Congratulations, you successfully deployed your
                        service to Cloud Run. 
                    </div>
                </div>
            </div>

            <div class="details mb-[20px]">
                <p>
                    <div hx-trigger="load" hx-get="/helper" hx-swap="innerHTML" hx-target="this">Hello</div>                   
                </p>
            </div>

            <p
                class="callout text-sm text-blue-700 font-bold pt-4 pr-6 pb-4 pl-10 leading-tight"
            >
                You can deploy any container to Cloud Run that listens for
                HTTP requests on the port defined by the
                <code>PORT</code> environment variable. Cloud Run will
                scale automatically based on requests and you never have to
                worry about infrastructure.
            </p>

            <h1 class="text-2xl font-bold mt-[40px] mb-[20px]">
                Persistent Storage Example using Firestore
            </h1>
            <div hx-target="this" hx-swap="outerHTML">
                <p>
                <div><label>Name</label>: Cloud</div>
                </p><p>
                <div><label>Town</label>: Nibelheim</div>
                </p>
                <div>
                <button
                    hx-get="/edit"
                    class="bg-blue-500 text-white px-4 py-2 rounded-lg text-sm font-medium mt-[10px]"
                >
                    Click to update
                </button>                
                </div>
            </div>

            <h1 class="text-2xl font-bold mt-[40px] mb-[20px]">
                What's next
            </h1>
            <p class="next text-base mt-4 mb-[20px]">
                You can build this demo yourself!
            </p>
            <p class="cta">
                <button
                    class="bg-blue-500 text-white px-4 py-2 rounded-lg text-center text-sm font-medium"
                >
                    VIEW CODELAB
                </button>
            </p> 
        </div>
   </body>
</html>

7. Uygulamayı yerel olarak çalıştırma

Bu bölümde, kullanıcı verileri kaydetmeye çalıştığında uygulamada bir hata olduğunu onaylamak için uygulamayı yerel olarak çalıştıracaksınız.

İlk olarak, Firestore'a erişmek için Datastore Kullanıcısı rolüne sahip olmanız gerekir (kimlik doğrulama için kimliğinizi kullanıyorsanız, ör. Cloud Shell'de çalıştırıyorsanız) veya daha önce oluşturulmuş kullanıcı hesabının kimliğine bürünebilirsiniz.

Yerel olarak çalıştırırken ADC kullanma

Cloud Shell'de çalışıyorsanız zaten bir Google Compute Engine sanal makinesinde çalıştırıyorsunuz demektir. Bu sanal makineyle ilişkili kimlik bilgileriniz (gcloud auth list çalıştırıldığında gösterildiği şekilde), otomatik olarak Application Default Credentials (ADC) (Uygulama Varsayılan Kimlik Bilgileri) (ADC) tarafından kullanılacağından gcloud auth application-default login komutunu kullanmanız gerekmez. Bununla birlikte, kimliğinizin Datastore Kullanıcısı rolüne sahip olması gerekir. Uygulamayı yerel olarak çalıştırma bölümüne geçebilirsiniz.

Ancak yerel terminalinizde (ör. Cloud Shell'de değil) çalışıyorsanız Google API'lerinde kimlik doğrulamak için Uygulama Varsayılan Kimlik Bilgilerini kullanmanız gerekir. 1) Kimlik bilgilerinizi kullanarak giriş yapabilirsiniz (Datastore Kullanıcısı rolüne sahipseniz) veya 2) bu codelab'de kullanılan hizmet hesabının kimliğine bürünerek giriş yapabilirsiniz.

1. Seçenek) ADC için kimlik bilgilerinizi kullanma

Kimlik bilgilerinizi kullanmak istiyorsanız gcloud'da kimlik doğrulamanın nasıl yapıldığını doğrulamak için önce gcloud auth list komutunu çalıştırabilirsiniz. Ardından, kimliğinize Vertex AI Kullanıcısı rolünü vermeniz gerekebilir. Kimliğiniz Sahip rolüne sahipse bu Datastore Kullanıcısı kullanıcı rolüne zaten sahipsiniz demektir. Aksi takdirde, kimliğinize Vertex AI kullanıcı rolünü ve Datastore Kullanıcısı rolünü vermek için bu komutu çalıştırabilirsiniz.

USER=<YOUR_PRINCIPAL_EMAIL>

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member user:$USER \
  --role=roles/datastore.user

Ardından aşağıdaki komutu çalıştırın

gcloud auth application-default login

2. Seçenek) ADC için Bir Hizmet Hesabının Kimliğine Bürünme

Bu codelab'de oluşturulan hizmet hesabını kullanmak istiyorsanız kullanıcı hesabınızın Hizmet Hesabı Jetonu Oluşturucu rolüne sahip olması gerekir. Bu rolü almak için şu komutu çalıştırın:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member user:$USER \
  --role=roles/iam.serviceAccountTokenCreator

Ardından, ADC'yi hizmet hesabıyla kullanmak için aşağıdaki komutu çalıştıracaksınız

gcloud auth application-default login --impersonate-service-account=$SERVICE_ACCOUNT_ADDRESS

Uygulamayı yerel olarak çalıştırma

Ardından, codelab'iniz için cloud-run-github-cd-demo kök dizininde olduğunuzdan emin olun.

cd .. && pwd

Şimdi bağımlılıkları yükleyeceksiniz.

npm install

Son olarak, aşağıdaki komut dosyasını çalıştırarak uygulamayı başlatabilirsiniz. Bu komut dosyası, tailwindCSS'den çıkış.css dosyasını da oluşturur.

npm run dev

Şimdi web tarayıcınızı açarak http://localhost:8080 adresine gidin. Cloud Shell'deyseniz Web Önizlemesi düğmesini açıp Önizleme Bağlantı Noktası 8080'i seçerek web sitesini açabilirsiniz.

web önizlemesi - 8080 bağlantı noktasında önizle düğmesi

Ad ve şehir giriş alanlarına metin girip Kaydet'e basın. Ardından sayfayı yenileyin. Kasaba alanının aktif olmadığını göreceksiniz. Bu hatayı sonraki bölümde düzelteceksiniz.

Ekspres uygulamanın yerel olarak çalışmasını durdurun (ör. MacOS'te Ctrl^c).

8. GitHub Deposu Oluştur

Yerel dizininizde varsayılan dal adı ana olan yeni bir depo oluşturun.

git init
git branch -M main

Hatayı içeren mevcut kod tabanını taahhüt edin. Sürekli dağıtım yapılandırıldıktan sonra hatayı düzeltirsiniz.

git add .
git commit -m "first commit for express application"

GitHub'a gidin ve size özel veya herkese açık olan boş bir depo oluşturun. Bu codelab'de, deponuz cloud-run-auto-deploy-codelab olarak adlandırılabilir. Boş bir depo oluşturmak için varsayılan ayarların tümünü işaretlenmemiş olarak bırakır veya hiç içerik olmamasını sağlarsınız. Böylece, oluşturulan içerikler varsayılan olarak depoda yer almaz (ör.

GitHub varsayılan ayarları

Bu adımı doğru bir şekilde tamamladıysanız boş depo sayfasında aşağıdaki talimatları göreceksiniz:

Boş GitHub deposu talimatları

Şu komutları çalıştırarak mevcut bir depoyu komut satırından aktarma talimatlarını uygulayın:

Öncelikle şu komutu çalıştırarak uzak depoyu ekleyin:

git remote add origin <YOUR-REPO-URL-PER-GITHUB-INSTRUCTIONS>

ana dalı yukarı akış deposuna aktarın.

git push -u origin main

9. Sürekli Dağıtımı Ayarla

Artık bir GitHub'da kodunuz olduğuna göre sürekli dağıtım oluşturabilirsiniz. Cloud Run için Cloud Console'a gidin.

  • Hizmet Oluştur'u tıklayın.
  • Repository'den sürekli olarak dağıt'ı tıklayın
  • CLOUD BUILD'I KUR'u tıklayın.
    • kod deposu altında
    • Kod Deposu Sağlayıcı olarak GitHub'ı seçin
    • Depoya Cloud Build erişimini yapılandırmak için Bağlı depoları yönet'i tıklayın.
    • Deponuzu seçip Next'i (İleri) tıklayın
  • Derleme Yapılandırması Altında
    • Şubeyi ^main$ olarak bırak
    • Derleme Türü için Google Cloud'un derleme paketleri aracılığıyla Go, Node.js, Python, Java, .NET Core, Ruby veya PHP'yi seçin
  • Derleme bağlamı dizinini / olarak bırakın
  • Kaydet'i tıklayın
  • Kimlik Doğrulama altında
    • Kimliği doğrulanmayan çağrılara izin ver'i tıklayın
  • Kapsayıcılar, Birimler, Ağ İletişimi, Güvenlik'in altında
    • Güvenlik sekmesinin altında, önceki bir adımda oluşturduğunuz hizmet hesabını seçin (ör. Cloud Run access to Firestore.
  • OLUŞTUR'u tıklayın.

Bu işlem, bir sonraki bölümde düzelteceğiniz hatayı içeren Cloud Run hizmetini dağıtacaktır.

10. Hatayı düzelt

Koddaki hatayı düzeltin

Cloud Shell Düzenleyici'de app.js dosyasını açın ve //TODO: fix this bug yazan yoruma gidin.

aşağıdaki satırı şununla değiştir:

 //TODO: fix this bug
    await doc.set({
        name: name
    });

-

//fixed town bug
    await doc.set({
        name: name,
        town: town
    });

Düzeltmeyi doğrulamak için

npm run start

web tarayıcınızı açın. Verileri yeniden şehir için kaydedin ve yenileyin. Yeni girilen şehir verilerinin, yenileme sonrasında doğru şekilde korunduğunu görürsünüz.

Düzeltmenizi doğruladığınıza göre, artık dağıtıma hazırsınız. Önce düzeltmeyi uygulayın.

git add .
git commit -m "fixed town bug"

ve GitHub'daki yukarı akış deposuna aktarıyorum.

git push origin main

Cloud Build, değişikliklerinizi otomatik olarak dağıtır. Dağıtım değişikliklerini izlemek için Cloud Run hizmetinize ait Cloud Console'a gidebilirsiniz.

Üretimde düzeltmeyi doğrulayın

Cloud Run hizmetinizin Cloud Console'u gösterdiğinde ikinci bir düzeltme şu anda% 100 trafik sunuyor (ör. https://console.cloud.google.com/run/detail/<YOUR_REGION>/<YOUR_SERVICE_NAME>/revisions tarayıcınızda Cloud Run hizmet URL'sini açabilir ve sayfayı yeniledikten sonra yeni girilen şehir verilerinin silinmediğini doğrulayabilirsiniz.

11. Tebrikler!

Tebrikler, codelab'i tamamladınız.

Cloud Run ve git'ten sürekli dağıtım belgelerini incelemenizi öneririz.

İşlediklerimiz

  • Cloud Shell Düzenleyici ile Express web uygulaması yazma
  • Sürekli dağıtımlar için GitHub hesabınızı Google Cloud'a bağlayın
  • Uygulamanızı otomatik olarak Cloud Run'a dağıtma
  • HTMX ve TailwindCSS'yi nasıl kullanacağınızı öğrenin

12. Temizleme

Yanlışlıkla yapılan ücretleri önlemek için (örneğin, Cloud Run hizmetleri yanlışlıkla ücretsiz katmandaki aylık Cloud Run çağırma tahsisinizden daha fazla kez çağrıldıysa) Cloud Run'ı silebilir veya 2. adımda oluşturduğunuz projeyi silebilirsiniz.

Cloud Run hizmetini silmek için https://console.cloud.google.com/run adresinden Cloud Run Cloud Console'a gidin ve bu codelab'de oluşturduğunuz Cloud Run hizmetini silin (ör. cloud-run-auto-deploy-codelab hizmetini silin.

Projenin tamamını silmeyi tercih ederseniz https://console.cloud.google.com/cloud-resource-manager adresine gidip 2. adımda oluşturduğunuz projeyi, ardından Sil'i seçebilirsiniz. Projeyi silerseniz Cloud SDK'nızdaki projeleri değiştirmeniz gerekir. gcloud projects list komutunu çalıştırarak mevcut tüm projelerin listesini görüntüleyebilirsiniz.