نحوه اجرای خودکار تغییرات خود از GitHub به Cloud Run با استفاده از Cloud Build

۱. مقدمه

نمای کلی

در این آزمایشگاه کد، Cloud Run را طوری پیکربندی خواهید کرد که هر زمان که تغییرات کد منبع خود را به مخزن GitHub ارسال می‌کنید، به‌طور خودکار نسخه‌های جدید برنامه شما را بسازد و مستقر کند .

این برنامه آزمایشی داده‌های کاربر را در firestore ذخیره می‌کند، با این حال، تنها بخشی از داده‌ها به درستی ذخیره می‌شوند. شما استقرارهای مداوم را طوری پیکربندی خواهید کرد که وقتی یک رفع اشکال را به مخزن GitHub خود اضافه می‌کنید، به طور خودکار شاهد خواهید بود که رفع اشکال در یک نسخه جدید در دسترس قرار می‌گیرد.

آنچه یاد خواهید گرفت

  • نوشتن یک برنامه وب اکسپرس با ویرایشگر Cloud Shell
  • برای استقرار مداوم، حساب گیت‌هاب خود را به گوگل کلود متصل کنید
  • برنامه خود را به صورت خودکار در Cloud Run مستقر کنید
  • یاد بگیرید چگونه از HTMX و TailwindCSS استفاده کنید

۲. تنظیمات و الزامات

پیش‌نیازها

  • شما یک حساب کاربری GitHub دارید و با ایجاد و ارسال کد به مخازن آشنا هستید.
  • شما وارد کنسول ابری شده‌اید.
  • شما قبلاً یک سرویس Cloud Run را مستقر کرده‌اید. برای مثال، می‌توانید برای شروع ، راهنمای استقرار یک سرویس وب از کد منبع را دنبال کنید.

فعال کردن پوسته ابری

  1. از کنسول ابری، روی فعال کردن پوسته ابری کلیک کنید d1264ca30785e435.png .

cb81e7c8e34bc8d.png

اگر این اولین باری است که Cloud Shell را اجرا می‌کنید، یک صفحه میانی برای توضیح آن به شما نمایش داده می‌شود. اگر با یک صفحه میانی مواجه شدید، روی ادامه کلیک کنید.

d95252b003979716.png

آماده‌سازی و اتصال به Cloud Shell فقط چند لحظه طول می‌کشد.

7833d5e1c5d18f54.png

این ماشین مجازی مجهز به تمام ابزارهای توسعه مورد نیاز است. این ماشین یک دایرکتوری خانگی پایدار ۵ گیگابایتی ارائه می‌دهد و در فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی افزایش می‌دهد. بخش عمده‌ای از کار شما در این آزمایشگاه کد، اگر نگوییم همه، را می‌توان با یک مرورگر انجام داد.

پس از اتصال به Cloud Shell، باید ببینید که احراز هویت شده‌اید و پروژه روی شناسه پروژه شما تنظیم شده است.

  1. برای تأیید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:
gcloud auth list

خروجی دستور

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. دستور زیر را در Cloud Shell اجرا کنید تا تأیید کنید که دستور gcloud از پروژه شما اطلاع دارد:
gcloud config list project

خروجی دستور

[core]
project = <PROJECT_ID>

اگر اینطور نیست، می‌توانید با این دستور آن را تنظیم کنید:

gcloud config set project <PROJECT_ID>

خروجی دستور

Updated property [core/project].

۳. فعال کردن APIها و تنظیم متغیرهای محیطی

فعال کردن APIها

این آزمایشگاه کد به استفاده از API های زیر نیاز دارد. می‌توانید با اجرای دستور زیر این API ها را فعال کنید:

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

متغیرهای محیطی را تنظیم کنید

شما می‌توانید متغیرهای محیطی که در سراسر این آزمایشگاه کد استفاده خواهند شد را تنظیم کنید.

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

۴. یک حساب کاربری سرویس ایجاد کنید

این حساب سرویس توسط Cloud Run برای فراخوانی API مربوط به Vertex AI Gemini استفاده خواهد شد. این حساب سرویس همچنین مجوزهای خواندن و نوشتن در Firestore و خواندن اطلاعات محرمانه از Secret Manager را خواهد داشت.

ابتدا، با اجرای این دستور، حساب کاربری سرویس را ایجاد کنید:

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

اکنون، به حساب سرویس، دسترسی خواندن و نوشتن در Firestore را اعطا کنید.

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

۵. ایجاد و پیکربندی یک پروژه Firebase

  1. در کنسول Firebase ، روی افزودن پروژه کلیک کنید.
  2. برای اضافه کردن Firebase به یکی از پروژه‌های Google Cloud موجود خود، <YOUR_PROJECT_ID> را وارد کنید.
  3. در صورت درخواست، شرایط Firebase را بررسی و بپذیرید.
  4. روی ادامه کلیک کنید.
  5. برای تأیید طرح پرداخت Firebase ، روی تأیید طرح کلیک کنید.
  6. فعال کردن گوگل آنالیتیکس برای این codelab اختیاری است.
  7. روی افزودن فایربیس کلیک کنید.
  8. وقتی پروژه ایجاد شد، روی ادامه کلیک کنید.
  9. از منوی Build ، روی پایگاه داده Firestore کلیک کنید.
  10. روی ایجاد پایگاه داده کلیک کنید.
  11. منطقه خود را از منوی کشویی Location انتخاب کنید، سپس روی Next کلیک کنید.
  12. از حالت پیش‌فرض Start در حالت تولید استفاده کنید، سپس روی Create کلیک کنید.

۶. درخواست را بنویسید

ابتدا، یک دایرکتوری برای کد منبع ایجاد کنید و با دستور cd به آن دایرکتوری بروید.

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

سپس، یک فایل package.json با محتوای زیر ایجاد کنید:

{
  "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"
  }
}

ابتدا، یک فایل منبع app.js با محتوای زیر ایجاد کنید. این فایل شامل نقطه ورود سرویس و منطق اصلی برنامه است.

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 ایجاد کنید.

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>`;

یک فایل input.css برای tailwindCSS ایجاد کنید

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

و فایل tailwind.config.js را برای tailwindCSS ایجاد کنید

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

و یک فایل .gitignore ایجاد کنید.

node_modules/

npm-debug.log
coverage/

package-lock.json

.DS_Store

حالا، یک دایرکتوری public جدید ایجاد کنید.

mkdir public
cd public

و درون آن دایرکتوری عمومی، فایل index.html را برای بخش کاربری (front end) ایجاد کنید که از htmx استفاده خواهد کرد.

<!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>

۷. اجرای برنامه به صورت محلی

در این بخش، برنامه را به صورت محلی اجرا خواهید کرد تا هنگام تلاش کاربر برای ذخیره داده‌ها، وجود اشکال در برنامه تأیید شود.

اول، برای دسترسی به Firestore یا باید نقش کاربری Datastore را داشته باشید (اگر از هویت خود برای احراز هویت استفاده می‌کنید، مثلاً در Cloud Shell در حال اجرا هستید) یا می‌توانید حساب کاربری که قبلاً ایجاد شده است را جعل هویت کنید.

استفاده از ADC هنگام اجرای محلی

اگر در Cloud Shell اجرا می‌کنید، در حال حاضر روی یک ماشین مجازی Google Compute Engine در حال اجرا هستید. اعتبارنامه‌های شما که با این ماشین مجازی مرتبط هستند (همانطور که با اجرای gcloud auth list نشان داده شده است) به طور خودکار توسط Application Default Credentials (ADC) استفاده می‌شوند، بنابراین نیازی به استفاده از دستور gcloud auth application-default login نیست. با این حال، هویت شما همچنان به نقش کاربر Datastore نیاز دارد. می‌توانید به بخش Run the app locally بروید.

با این حال، اگر در ترمینال محلی خود (یعنی نه در Cloud Shell) اجرا می‌کنید، برای تأیید اعتبار در APIهای گوگل باید از Application Default Credentials استفاده کنید. می‌توانید ۱) با استفاده از اعتبارنامه‌های خود وارد شوید (به شرطی که نقش کاربر Datastore را داشته باشید) یا ۲) می‌توانید با جعل هویت حساب سرویس مورد استفاده در این codelab وارد شوید.

گزینه ۱) استفاده از اعتبارنامه‌هایتان برای ADC

اگر می‌خواهید از اعتبارنامه‌های خود استفاده کنید، ابتدا می‌توانید gcloud auth list اجرا کنید تا نحوه احراز هویت خود در gcloud را تأیید کنید. در مرحله بعد، ممکن است لازم باشد به هویت خود نقش Vertex AI User را اعطا کنید. اگر هویت شما نقش Owner را دارد، از قبل این نقش کاربری Datastore User را دارید. در غیر این صورت، می‌توانید این دستور را اجرا کنید تا نقش کاربری Vertex AI و نقش کاربری Datastore را به هویت خود اعطا کنید.

USER=<YOUR_PRINCIPAL_EMAIL>

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

سپس دستور زیر را اجرا کنید

gcloud auth application-default login

گزینه ۲) جعل هویت یک حساب کاربری سرویس برای ADC

اگر می‌خواهید از حساب کاربری سرویس ایجاد شده در این codelab استفاده کنید، حساب کاربری شما باید نقش Service Account Token Creator را داشته باشد. می‌توانید این نقش را با اجرای دستور زیر به دست آورید:

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

در مرحله بعد، دستور زیر را برای استفاده از ADC با حساب سرویس اجرا خواهید کرد.

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

اجرای برنامه به صورت محلی

در مرحله بعد، مطمئن شوید که در دایرکتوری ریشه cloud-run-github-cd-demo مربوط به codelab خود هستید.

cd .. && pwd

اکنون، وابستگی‌ها را نصب خواهید کرد.

npm install

در نهایت، می‌توانید برنامه را با اجرای اسکریپت زیر شروع کنید. این اسکریپت همچنین فایل output.css را از tailwindCSS تولید می‌کند.

npm run dev

اکنون مرورگر وب خود را باز کنید و آدرس http://localhost:8080 را وارد کنید. اگر در Cloud Shell هستید، می‌توانید با باز کردن دکمه پیش‌نمایش وب و انتخاب پیش‌نمایش پورت ۸۰۸۰، وب‌سایت را باز کنید.

پیش‌نمایش وب - دکمه پیش‌نمایش روی پورت ۸۰۸۰

متن مربوط به فیلدهای نام و شهر را وارد کنید و ذخیره را بزنید. سپس صفحه را رفرش کنید. متوجه خواهید شد که فیلد شهر باقی نمانده است. این اشکال را در بخش بعدی برطرف خواهید کرد.

اجرای محلی برنامه‌ی اکسپرس را متوقف کنید (مثلاً Ctrl^c در MacOS).

۸. یک مخزن گیت‌هاب ایجاد کنید

در دایرکتوری محلی خود، یک مخزن جدید با نام شاخه پیش‌فرض main ایجاد کنید.

git init
git branch -M main

کدبیس فعلی که حاوی اشکال است را کامیت کنید. پس از پیکربندی استقرار مداوم، اشکال را برطرف خواهید کرد.

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

به گیت‌هاب بروید و یک مخزن خالی ایجاد کنید که یا برای شما خصوصی باشد یا عمومی. این codelab توصیه می‌کند مخزن خود را cloud-run-auto-deploy-codelab نامگذاری کنید. برای ایجاد یک مخزن خالی، تمام تنظیمات پیش‌فرض را بدون علامت بگذارید یا روی none تنظیم کنید تا هیچ محتوایی هنگام ایجاد به طور پیش‌فرض در مخزن وجود نداشته باشد، مثلاً

تنظیمات پیش‌فرض گیت‌هاب

اگر این مرحله را به درستی انجام داده باشید، دستورالعمل‌های زیر را در صفحه مخزن خالی مشاهده خواهید کرد:

دستورالعمل‌های خالی کردن مخزن گیت‌هاب

شما با اجرای دستورات زیر ، یک مخزن موجود را از طریق دستورالعمل‌های خط فرمان، push خواهید کرد:

ابتدا، با اجرای دستور زیر، مخزن راه دور را اضافه کنید.

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

سپس شاخه اصلی را به مخزن بالادستی (upstream repo) منتقل کنید.

git push -u origin main

۹. راه‌اندازی استقرار مداوم

حالا که کد را در گیت‌هاب دارید، می‌توانید استقرار مداوم را تنظیم کنید. برای Cloud Run به کنسول ابری بروید.

  • روی ایجاد سرویس کلیک کنید
  • روی «استقرار مداوم از مخزن» کلیک کنید
  • روی «راه‌اندازی ساخت ابری» کلیک کنید.
  • تحت مخزن منبع
    • گیت‌هاب را به عنوان ارائه‌دهنده مخزن انتخاب کنید
    • برای پیکربندی دسترسی Cloud Build به مخزن، روی مدیریت مخازن متصل کلیک کنید.
    • مخزن خود را انتخاب کنید و روی Next کلیک کنید
  • تحت پیکربندی ساخت
    • شاخه را به عنوان ^main$ رها کنید
    • برای نوع ساخت (Build Type)، از طریق بسته‌های ساخت گوگل کلود، Go، Node.js، Python، Java، .NET Core، Ruby یا PHP را انتخاب کنید.
  • دایرکتوری زمینه ساخت را به صورت / رها کنید
  • روی ذخیره کلیک کنید
  • تحت احراز هویت
    • روی «مجاز کردن فراخوانی‌های احراز هویت نشده» کلیک کنید
  • زیر کانتینر(ها)، ولوم‌ها، شبکه، امنیت
    • در زیر برگه امنیت (Security)، حساب کاربری سرویسی که در مرحله قبل ایجاد کرده‌اید را انتخاب کنید، مثلاً Cloud Run access to Firestore
  • روی ایجاد کلیک کنید

این کار سرویس Cloud Run را که حاوی اشکالی است که در بخش بعدی برطرف خواهید کرد، مستقر می‌کند.

۱۰. اشکال را برطرف کنید

اشکال موجود در کد را برطرف کنید

در ویرایشگر Cloud Shell، فایل app.js را باز کنید و به کامنتی که می‌گوید //TODO: fix this bug بروید.

خط زیر را از

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

به

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

با اجرای دستور زیر، رفع مشکل را تأیید کنید.

npm run start

و مرورگر وب خود را باز کنید. دوباره اطلاعات مربوط به شهر را ذخیره کنید و صفحه را رفرش کنید. خواهید دید که اطلاعات شهر تازه وارد شده، پس از رفرش شدن، به درستی نمایش داده می‌شود.

حالا که اصلاحیه خود را تأیید کرده‌اید، آماده‌ی پیاده‌سازی آن هستید. ابتدا، اصلاحیه را کامیت کنید.

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

و سپس آن را به مخزن بالادستی در GitHub ارسال کنید.

git push origin main

Cloud Build به طور خودکار تغییرات شما را اعمال می‌کند. می‌توانید برای نظارت بر تغییرات استقرار، به Cloud Console سرویس Cloud Run خود مراجعه کنید.

رفع مشکل در محیط عملیاتی را تأیید کنید

زمانی که کنسول ابری سرویس Cloud Run شما نشان دهد که نسخه دوم اکنون ۱۰۰٪ ترافیک را ارائه می‌دهد، مثلاً https://console.cloud.google.com/run/detail/<YOUR_REGION>/<YOUR_SERVICE_NAME>/revisions، می‌توانید URL سرویس Cloud Run را در مرورگر خود باز کنید و پس از رفرش کردن صفحه، تأیید کنید که داده‌های شهر تازه وارد شده همچنان پابرجا هستند.

۱۱. تبریک می‌گویم!

تبریک می‌گویم که آزمایشگاه کد را تمام کردید!

توصیه می‌کنیم مستندات Cloud Run و استقرار مداوم را از git بررسی کنید.

آنچه ما پوشش داده‌ایم

  • نوشتن یک برنامه وب اکسپرس با ویرایشگر Cloud Shell
  • برای استقرار مداوم، حساب گیت‌هاب خود را به گوگل کلود متصل کنید
  • برنامه خود را به صورت خودکار در Cloud Run مستقر کنید
  • یاد بگیرید چگونه از HTMX و TailwindCSS استفاده کنید

۱۲. تمیز کردن

برای جلوگیری از هزینه‌های ناخواسته، (برای مثال، اگر سرویس‌های Cloud Run سهواً بیشتر از تخصیص فراخوانی ماهانه Cloud Run شما در سطح رایگان فراخوانی شوند)، می‌توانید Cloud Run یا پروژه‌ای را که در مرحله 2 ایجاد کرده‌اید، حذف کنید.

برای حذف سرویس Cloud Run، به کنسول ابری Cloud Run به آدرس https://console.cloud.google.com/run بروید و سرویس Cloud Run که در این codelab ایجاد کرده‌اید را حذف کنید، مثلاً سرویس cloud-run-auto-deploy-codelab حذف کنید.

اگر تصمیم به حذف کل پروژه دارید، می‌توانید به آدرس https://console.cloud.google.com/cloud-resource-manager بروید، پروژه‌ای را که در مرحله ۲ ایجاد کرده‌اید انتخاب کنید و گزینه Delete را انتخاب کنید. اگر پروژه را حذف کنید، باید پروژه‌ها را در Cloud SDK خود تغییر دهید. می‌توانید با اجرای gcloud projects list لیست تمام پروژه‌های موجود را مشاهده کنید.