วิธีนำการเปลี่ยนแปลงจาก GitHub ไปใช้ Cloud Run โดยอัตโนมัติด้วย Cloud Build

1. บทนำ

ภาพรวม

ใน Codelab นี้ คุณจะได้กำหนดค่า Cloud Run ให้สร้างและทำให้ใช้งานได้โดยอัตโนมัติในแอปพลิเคชันเวอร์ชันใหม่ทุกครั้งที่คุณพุชการเปลี่ยนแปลงซอร์สโค้ดไปยังที่เก็บ GitHub

แอปพลิเคชันเดโมนี้จะบันทึกข้อมูลผู้ใช้ไปยัง Firestore แต่จะบันทึกข้อมูลบางส่วนอย่างถูกต้องเท่านั้น คุณจะกำหนดค่าการติดตั้งใช้งานอย่างต่อเนื่องเพื่อให้เมื่อพุชการแก้ไขข้อบกพร่องไปยังที่เก็บ GitHub คุณจะเห็นการแก้ไขพร้อมใช้งานในรีวิชันใหม่โดยอัตโนมัติ

สิ่งที่คุณจะได้เรียนรู้

  • เขียนเว็บแอปพลิเคชัน Express ด้วย Cloud Shell Editor
  • เชื่อมต่อบัญชี GitHub กับ Google Cloud เพื่อการทำให้ใช้งานได้อย่างต่อเนื่อง
  • ทำให้แอปพลิเคชันใช้งานได้ใน Cloud Run โดยอัตโนมัติ
  • ดูวิธีใช้ HTMX และ TailwindCSS

2. การตั้งค่าและข้อกำหนด

ข้อกำหนดเบื้องต้น

เปิดใช้งาน Cloud Shell

  1. จาก Cloud Console ให้คลิกเปิดใช้งาน Cloud Shell d1264ca30785e435.png

cb81e7c8e34bc8d.png

หากคุณเริ่มใช้ Cloud Shell เป็นครั้งแรก คุณจะเห็นหน้าจอระดับกลางที่อธิบายว่า Cloud Shell คืออะไร หากเห็นหน้าจอระดับกลาง ให้คลิกต่อไป

d95252b003979716.png

การจัดสรรและเชื่อมต่อกับ Cloud Shell จะใช้เวลาไม่นาน

7833d5e1c5d18f54.png

เครื่องเสมือนนี้โหลดเครื่องมือพัฒนาซอฟต์แวร์ทั้งหมดที่จำเป็นไว้แล้ว โดยมีไดเรกทอรีหลักแบบถาวรขนาด 5 GB และทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการตรวจสอบสิทธิ์ได้อย่างมาก คุณสามารถทำงานส่วนใหญ่หรือทั้งหมดใน Codelab นี้ได้ด้วยเบราว์เซอร์

เมื่อเชื่อมต่อกับ 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].

3. เปิดใช้ API และตั้งค่าตัวแปรสภาพแวดล้อม

เปิดใช้ API

Codelab นี้กำหนดให้ใช้ 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

4. สร้างบัญชีบริการ

Cloud Run จะใช้บัญชีบริการนี้เพื่อเรียกใช้ Vertex AI Gemini API บัญชีบริการนี้จะมีสิทธิ์อ่านและเขียนไปยัง 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

5. สร้างและกำหนดค่าโปรเจ็กต์ Firebase

  1. ในคอนโซล Firebase ให้คลิกเพิ่มโปรเจ็กต์
  2. ป้อน <YOUR_PROJECT_ID> เพื่อเพิ่ม Firebase ไปยังโปรเจ็กต์ Google Cloud ที่มีอยู่
  3. เมื่อได้รับแจ้ง ให้อ่านและยอมรับข้อกำหนดของ Firebase
  4. คลิกต่อไป
  5. คลิกยืนยันแพ็กเกจเพื่อยืนยันแพ็กเกจการเรียกเก็บเงิน Firebase
  6. คุณจะเปิดใช้ Google Analytics สำหรับ Codelab นี้หรือไม่ก็ได้
  7. คลิกเพิ่ม Firebase
  8. เมื่อสร้างโปรเจ็กต์แล้ว ให้คลิกต่อไป
  9. จากเมนูสร้าง คลิกฐานข้อมูล Firestore
  10. คลิกสร้างฐานข้อมูล
  11. เลือกภูมิภาคจากเมนูแบบเลื่อนลงสถานที่ตั้ง แล้วคลิกถัดไป
  12. ใช้เริ่มต้นในโหมดที่ใช้งานจริงเริ่มต้น แล้วคลิกสร้าง

6. เขียนแอปพลิเคชัน

ก่อนอื่นให้สร้างไดเรกทอรีสำหรับซอร์สโค้ดและใช้คำสั่ง 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 สำหรับฟรอนท์เอนด์ซึ่งจะใช้ 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>

7. เรียกใช้แอปพลิเคชันในเครื่อง

ในส่วนนี้ คุณจะเรียกใช้แอปพลิเคชันในเครื่องเพื่อยืนยันว่ามีข้อบกพร่องในแอปพลิเคชันเมื่อผู้ใช้พยายามบันทึกข้อมูล

ก่อนอื่น คุณจะต้องมีบทบาทของผู้ใช้ Datastore เพื่อเข้าถึง Firestore (หากใช้ข้อมูลประจำตัวสำหรับการตรวจสอบสิทธิ์ เช่น คุณกำลังเรียกใช้ใน Cloud Shell) หรือจะแอบอ้างเป็นบัญชีผู้ใช้ที่สร้างไว้ก่อนหน้านี้ก็ได้

การใช้ ADC เมื่อเรียกใช้ในเครื่อง

หากคุณใช้งานใน Cloud Shell แสดงว่าคุณกำลังใช้งานเครื่องเสมือนของ Google Compute Engine อยู่แล้ว ข้อมูลรับรองเริ่มต้นของแอปพลิเคชัน (ADC) จะใช้ข้อมูลรับรองที่เชื่อมโยงกับเครื่องเสมือนนี้ (ตามที่แสดงโดยการเรียกใช้ gcloud auth list) โดยอัตโนมัติ จึงไม่จำเป็นต้องใช้คำสั่ง gcloud auth application-default login อย่างไรก็ตาม ตัวตนของคุณยังคงต้องมีบทบาทผู้ใช้ Datastore คุณข้ามไปยังส่วนเรียกใช้แอปในเครื่องได้

อย่างไรก็ตาม หากคุณเรียกใช้ในเทอร์มินัลในเครื่อง (เช่น ไม่ได้อยู่ใน Cloud Shell) คุณจะต้องใช้ข้อมูลรับรองเริ่มต้นของแอปพลิเคชันเพื่อตรวจสอบสิทธิ์ใน Google APIs คุณสามารถ 1) เข้าสู่ระบบโดยใช้ข้อมูลเข้าสู่ระบบ (หากมีบทบาทผู้ใช้ Datastore) หรือ 2) เข้าสู่ระบบโดยการแอบอ้างเป็นบัญชีบริการที่ใช้ในโค้ดแล็บนี้

ตัวเลือกที่ 1) ใช้ข้อมูลเข้าสู่ระบบสำหรับ ADC

หากต้องการใช้ข้อมูลเข้าสู่ระบบ คุณสามารถเรียกใช้ gcloud auth list ก่อนเพื่อตรวจสอบวิธีที่คุณได้รับการตรวจสอบสิทธิ์ใน gcloud จากนั้น คุณอาจต้องให้บทบาทผู้ใช้ Vertex AI แก่ข้อมูลประจำตัว หากข้อมูลประจำตัวของคุณมีบทบาทเจ้าของ คุณจะมีบทบาทผู้ใช้ Datastore นี้อยู่แล้ว หากไม่ได้ ให้เรียกใช้คำสั่งนี้เพื่อมอบบทบาทผู้ใช้ 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

ตัวเลือกที่ 2) การแอบอ้างบัญชีบริการสำหรับ ADC

หากต้องการใช้บัญชีบริการที่สร้างขึ้นใน Codelab นี้ บัญชีผู้ใช้ของคุณจะต้องมีบทบาทผู้สร้างโทเค็นบัญชีบริการ คุณจะได้รับบทบาทนี้โดยการเรียกใช้คำสั่งต่อไปนี้

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 คุณจะเปิดเว็บไซต์ได้โดยเปิดปุ่มแสดงตัวอย่างเว็บแล้วเลือก "แสดงตัวอย่างพอร์ต 8080"

ตัวอย่างเว็บ - ปุ่มแสดงตัวอย่างบนพอร์ต 8080

ป้อนข้อความสำหรับช่องป้อนข้อมูลชื่อและเมือง แล้วกดบันทึก จากนั้นรีเฟรชหน้าเว็บ คุณจะเห็นว่าระบบไม่ได้บันทึกช่องเมือง คุณจะแก้ไขข้อบกพร่องนี้ได้ในส่วนถัดไป

หยุดแอป Express ไม่ให้ทำงานในเครื่อง (เช่น Ctrl^c ใน MacOS)

8. สร้างที่เก็บ GitHub

สร้างที่เก็บใหม่ในไดเรกทอรีในเครื่องโดยใช้ main เป็นชื่อสาขาเริ่มต้น

git init
git branch -M main

คอมมิตฐานของโค้ดปัจจุบันที่มีข้อบกพร่อง คุณจะแก้ไขข้อบกพร่องหลังจากกำหนดค่าการทำให้ใช้งานได้อย่างต่อเนื่องแล้ว

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

ไปที่ GitHub แล้วสร้างที่เก็บที่ว่างเปล่าซึ่งเป็นแบบส่วนตัวหรือสาธารณะ Codelab นี้แนะนําให้ตั้งชื่อที่เก็บว่า cloud-run-auto-deploy-codelab หากต้องการสร้างที่เก็บที่ว่างเปล่า ให้ปล่อยการตั้งค่าเริ่มต้นทั้งหมดไว้โดยไม่ต้องเลือก หรือตั้งค่าเป็น "ไม่มี" เพื่อให้ไม่มีเนื้อหาใดๆ ในที่เก็บโดยค่าเริ่มต้นเมื่อสร้าง เช่น

การตั้งค่าเริ่มต้นของ GitHub

หากทำขั้นตอนนี้ถูกต้อง คุณจะเห็นวิธีการต่อไปนี้ในหน้าพื้นที่เก็บข้อมูลที่ว่างเปล่า

วิธีการสำหรับที่เก็บ GitHub ที่ว่างเปล่า

คุณจะทำตามวิธีการพุชที่เก็บที่มีอยู่จากบรรทัดคำสั่งโดยการเรียกใช้คำสั่งต่อไปนี้

ก่อนอื่น ให้เพิ่มที่เก็บข้อมูลระยะไกลโดยเรียกใช้

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

จากนั้นพุชกิ่งหลักไปยังที่เก็บต้นน้ำ

git push -u origin main

9. ตั้งค่าการทำให้ใช้งานได้อย่างต่อเนื่อง

เมื่อมีโค้ดใน GitHub แล้ว คุณก็ตั้งค่าการติดตั้งใช้งานต่อเนื่องได้ ไปที่ Cloud Console สำหรับ Cloud Run

  • คลิกสร้างบริการ
  • คลิกทำให้ใช้งานได้อย่างต่อเนื่องจากที่เก็บ
  • คลิกตั้งค่า Cloud Build
  • ในส่วนที่เก็บซอร์ส
    • เลือก GitHub เป็นผู้ให้บริการที่เก็บ
    • คลิกจัดการที่เก็บที่เชื่อมต่อเพื่อกำหนดค่าการเข้าถึงที่เก็บของ Cloud Build
    • เลือกที่เก็บ แล้วคลิกถัดไป
  • ในส่วนการกำหนดค่าบิลด์
    • ปล่อยให้ Branch เป็น ^main$
    • สำหรับประเภทบิลด์ ให้เลือก Go, Node.js, Python, Java, .NET Core, Ruby หรือ PHP ผ่าน Buildpack ของ Google Cloud
  • ปล่อยไดเรกทอรีบริบทบิลด์ไว้เป็น /
  • คลิกบันทึก
  • ในส่วนการตรวจสอบสิทธิ์
    • คลิกอนุญาตการเรียกใช้ที่ไม่ผ่านการตรวจสอบสิทธิ์
  • ในส่วน Container(s), Volumes, Networking, Security
    • ในแท็บความปลอดภัย ให้เลือกบัญชีบริการที่คุณสร้างในขั้นตอนก่อนหน้า เช่น Cloud Run access to Firestore
  • คลิกสร้าง

ซึ่งจะทําให้ระบบติดตั้งใช้งานบริการ Cloud Run ที่มีข้อบกพร่องซึ่งคุณจะแก้ไขในส่วนถัดไป

10. แก้ไขข้อบกพร่อง

แก้ไขข้อบกพร่องในโค้ด

ใน Cloud Shell Editor ให้เปิดไฟล์ 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 Console สำหรับบริการ Cloud Run แสดงว่ารุ่นที่ 2 กำลังให้บริการการรับส่งข้อมูล 100% เช่น https://console.cloud.google.com/run/detail/<YOUR_REGION>/<YOUR_SERVICE_NAME>/revisions คุณจะเปิด URL ของบริการ Cloud Run ในเบราว์เซอร์และยืนยันได้ว่าระบบจะบันทึกข้อมูลเมืองที่ป้อนใหม่หลังจากรีเฟรชหน้าเว็บ

11. ยินดีด้วย

ขอแสดงความยินดีที่ทำ Codelab นี้เสร็จสมบูรณ์

เราขอแนะนำให้อ่านเอกสารประกอบ Cloud Run และการติดตั้งใช้งานอย่างต่อเนื่องจาก Git

สิ่งที่เราได้พูดถึง

  • เขียนเว็บแอปพลิเคชัน Express ด้วย Cloud Shell Editor
  • เชื่อมต่อบัญชี GitHub กับ Google Cloud เพื่อการทำให้ใช้งานได้อย่างต่อเนื่อง
  • ทำให้แอปพลิเคชันใช้งานได้ใน Cloud Run โดยอัตโนมัติ
  • ดูวิธีใช้ HTMX และ TailwindCSS

12. ล้างข้อมูล

หากต้องการหลีกเลี่ยงการเรียกเก็บเงินโดยไม่ตั้งใจ (เช่น หากมีการเรียกใช้บริการ Cloud Run โดยไม่ตั้งใจมากกว่าการจัดสรรการเรียกใช้ Cloud Run รายเดือนในระดับฟรี) คุณสามารถลบ Cloud Run หรือลบโปรเจ็กต์ที่สร้างในขั้นตอนที่ 2 ได้

หากต้องการลบบริการ Cloud Run ให้ไปที่ Cloud Console ของ Cloud Run ที่ https://console.cloud.google.com/run แล้วลบบริการ Cloud Run ที่คุณสร้างใน Codelab นี้ เช่น ลบบริการ cloud-run-auto-deploy-codelab

หากเลือกที่จะลบทั้งโปรเจ็กต์ ให้ไปที่ https://console.cloud.google.com/cloud-resource-manager เลือกโปรเจ็กต์ที่สร้างในขั้นตอนที่ 2 แล้วเลือก "ลบ" หากลบโปรเจ็กต์ คุณจะต้องเปลี่ยนโปรเจ็กต์ใน Cloud SDK คุณดูรายการโปรเจ็กต์ทั้งหมดที่พร้อมใช้งานได้โดยเรียกใช้ gcloud projects list