การ Publish App ขึ้น Google Play ถือว่าเป็นขั้นตอนที่ต้องทำอยู่ประจำสำหรับทีมพัฒนาที่มีการอัปเดตแอปอยู่ตลอดเวลา และก็เป็นขั้นตอนที่ต้องทำทุกอย่างเหมือนเดิมทุกครั้ง
นั่นจึงทำให้นักพัฒนาสามารถสร้าง Continuous Deployment ขึ้นมาเพื่อช่วยทำขั้นตอนนี้แทนได้ แทนที่จะทำขั้นตอนด้วยตัวเองทั้งหมด ก็แค่กดสั่งทีเดียวเพื่อให้ GitHub Actions จัดการให้แทน
ดังนั้นในบทความนี้จะพูดถึงการสร้าง Continuous Deployment บน GitHub เพื่อทำงานดังกล่าวให้ โดยใช้ GitHub Actions ที่ช่วยให้เราทำ CI/CD ง่ายขึ้น นั่นหมายความว่าโปรเจคของที่จะใช้ในบทความนี้ก็จะเป็นโปรเจคที่ต้องอยู่บน GitHub นั่นเอง
Tools ที่จะใช้ในบทความนี้
- GitHub Actions — เพื่อใช้สร้าง Continuous Deployment
- Google Play Android Developer API บน Google Cloud Platform – เพื่อ Publish App เข้า Play Developer Console
- r0adkll/upload-google-play — Action สำเร็จรูปบน GitHub Actions ที่จะมีชุดคำสั่งของ Publishing API ให้พร้อมแล้ว เราจะได้เขียนคำสั่งง่าย ๆ แทนที่จะต้องเรียกคำสั่งใน Publishing API เองทั้งหมด
- GNU Privacy Guard หรือ GPG — เพื่อ Encrypt Signing Key ที่จะใช้ Sign Android App เพื่อ Publish ขึ้น Google Play
สิ่งที่จะต้องเตรียมให้พร้อม
ก่อนที่จะเริ่มเขียนคำสั่งใน GitHub Actions กัน มีขั้นตอนที่จำเป็นจะต้องทำก่อนดังนี้
- เปิดใช้งาน Google Play Android Developer API บน Google Cloud Platform
- ต้องมี Service Account Key จาก Google Cloud Platform
- เพิ่ม Service Account ของ Google Cloud Platform เข้าไปใน Play Console
- ต้อง Encrypt หรือเข้ารหัส Signing Key สำหรับ App Signing
- ต้องเก็บข้อมูลที่จำเป็นต่อ App Signing และ App Publishing ไว้ใน Repository Secret ของ GitHub
- ต้องกำหนด Signing Config ใน Gradle ให้ใช้ Signing Key ที่มาจาก GitHub Actions
สำหรับผู้อ่านคนใดที่ไม่เคยทำขั้นตอนเหล่านี้มาก่อน ก็สามารถอ่านต่อเพื่อดูวิธีทั้งหมดได้เลย
เปิดใช้งาน Google Play Android Developer API บน Google Cloud Platform
ให้เลือกหรือสร้างโปรเจคบน Google Cloud Platform เพื่อเปิดใช้งาน Google Play Android Developer API เป็นอย่างแรกสุด
โดยโปรเจคนี้จะเป็นโปรเจคที่จะใช้สร้าง Service Account เพื่อใช้ในการ Publish App ขึ้น Play Console นั่นเอง
ต้องมี Service Account Key จาก Google Cloud Platform
หลังจากที่มีโปรเจคบน Google Cloud Platform แล้ว จะต้องสร้าง Service Account ขึ้นมาเพื่อเก็บไว้ให้ GitHub Actions ใช้งานในภายหลัง
ในการสร้าง Service Account จะต้องเข้าไปที่ IAM & Admin > Service Accounts
จากนั้นให้ทำการสร้าง Service Account ขึ้นมาใหม่ด้วยการกดที่ปุ่ม CREATE SERVICE ACCOUNT
ในการสร้าง Service Account ขึ้นมานั้น นักพัฒนาจะต้องใส่ข้อมูลทั้งหมด 3 ส่วนด้วยกันดังนี้
- Service account details
- Grant this service account access to project
- Grant users access to this service account
สำหรับ Service account details ให้กำหนดข้อมูลได้ตามใจชอบ แต่ถ้าจะให้ดีก็ควรเจาะจงให้รู้ว่าเป็น Service Account เพื่อใช้งานกับอะไร เวลากลับมาดูในภายหลังจะได้รู้ทันที
เมื่อกดปุ่ม CREATE AND CONTINUE ก็จะเป็นการสร้าง Service Account ขึ้นมาทันที พร้อมกับให้เรากรอกข้อมูลในส่วนถัดไปได้
ข้อมูลส่วนถัดมาจะเป็นการกำหนด Role สำหรับ Service Account โดยให้กำหนด Role ตามนี้
- Android Management User
- Storage Object Creator
จากนั้นให้กดปุ่ม CONTINUE ต่อ
สำหรับข้อมูลในส่วนสุดท้ายไม่ต้องทำอะไร ให้กดปุ่ม DONE เพื่อจบขั้นตอนการสร้าง Service Account ได้เลย
เมื่อสร้างเสร็จแล้ว ก็จะเห็น Service Account ตัวนั้นแสดงอยู่ในหน้า Service Account
ให้กดเลือกที่ Service Account ตัวนั้น แล้วเลือกไปที่แถบ KEYS และกดปุ่ม ADD KEY > Create new key เพื่อทำการสร้าง Service Account Key สำหรับ GitHub Actions
ให้สร้าง Key แบบ JSON เพราะการใช้งาน r0adkll/upload-google-play จะต้องใช้ Service Account Key ในรูปแบบของ JSON
จากนั้นหน้าเว็ปจะขึ้นหน้าต่างเพื่อดาวน์โหลด Private Key เก็บไว้ในเครื่อง ให้ดาวน์โหลดและเก็บไว้ก่อน เดี๋ยวเราจะต้องเอาไฟล์ดังกล่าวไปใส่ไว้ใน GitHub Actions อีกที
ในกรณีที่ผู้อ่านซีเรียสเรื่องความปลอดภัยและไม่อยากดาวน์โหลดไฟล์ Service Account Key ไปใช้งานโดยตรง ก็สามารถเปลี่ยนไปใช้วิธีที่เรียกว่า Workload Identity Federation แทนได้เช่นกัน โดยสามารถดูวิธีการใช้งานร่วมกับ GitHub Actions ได้จาก Enabling keyless authentication from GitHub Actions [Google Cloud]
เพิ่ม Service Account ของ Google Cloud Platform เข้าไปใน Play Console
เพื่อให้ Service Account สามารถ Publish App เข้าไปใน Play Console ได้ จะต้องเพิ่ม Email ของ Service Account เข้าไปใน Play Console ด้วย
โดย Email จะอยู่ที่หน้าแรกของหน้า Service Account เลย
จากนั้นให้เปิดหน้าแรกสุด Play Console ขึ้นมาเพื่อเข้าเมนู Users and permissions แล้วกดปุ่มเมนูที่อยู่ฝั่งขวามือเพื่อเลือกเมนู Invite new users
จากนั้นให้กรอก Email ของ Service Account และกำหนด App Permission เพื่อเลือกแอปที่ต้องการ Publish ผ่าน สามารถเลือกได้มากกว่า 1 แอป ถ้าต้องการให้ Service Account นั้นสามารถ Publish App มากกว่า 1 แอป
โดย Permission สำหรับ App Permission ที่จะต้องกำหนดให้กับ Service Account จะมีดังนี้
- App access → View app information (read-only)
- App access → View app quality information (read-only)
- Draft apps → Edit and delete draft apps
- Releases → Release to production, exclude devices, and use Play App Signing
- Releases → Release apps to testing tracks
- Releases → Manage testing tracks and edit tester lists
เพียงเท่านี้ Service Account ของเราก็จะพร้อมสำหรับการ Publish App แล้ว
ต้อง Encrypt หรือเข้ารหัส Signing Key สำหรับ App Signing
เนื่องจากเราจะย้ายขั้นตอนการทำ App Signing หรือ Sign Android App ให้เป็นไฟล์ AAB หรือไฟล์ APK ให้ไปอยู่บน GitHub Actions ซึ่งขั้นตอนดังกล่าวจะต้องใช้ Signing Key หรือ Keystore จึงต้องระวังในกรณีที่ไฟล์ดังกล่าวหลุดออกไปภายนอกด้วย
ถ้า Service Account Key ที่ถูกสร้างขึ้นผ่าน Google Cloud Console หลุดออกไปยังภายนอกโดยไม่ได้ตั้งใจ นักพัฒนาก็สามารถเข้าไปลบใน Google Cloud Console และสร้างขึ้นมาใหม่ได้ แต่สำหรับ Signing Key หรือ Keystore นั้นจะไม่สามารถทำแบบนั้นได้ ดังนั้นนักพัฒนาจึงควรเข้ารหัส Signing Key ไว้ตั้งแต่แรก เพื่อเก็บไว้บน GitHub Actions
และนั่นคือที่มาว่าทำไมเราถึงใช้ GNU Privacy Guard (เรียกสั้น ๆ ว่า GPG) โดยบทความนี้จะใช้ GPG เพื่อ Encrypt (เข้ารหัส) Signing Key ด้วย Passphrase แล้วเก็บ Passphrase กับ Encrypted Signing Key ไว้บน GitHub Actions
ด้วยวิธีนี้ถ้า Encrypted Signing Key หลุดออกไปก็ยังสบายใจได้ประมาณนึง แต่ถ้า Passphrase หลุดไปด้วย ก็ขอให้โชคดีละกันครับ
ดังนั้นเราจะต้องทำการ Encrypt (เข้ารหัส) ด้วยตัวเองก่อน แล้วเอาข้อมูลไปเก็บไว้บน Secrets ของ GitHub เพื่อให้ GitHub Actions เรียกใช้งานในภายหลังเพื่อ Decrypt (ถอดรหัส) แล้วนำ Signing Key ที่ได้ไปทำ App Signing ต่อ
การเก็บข้อมูล Service Account Key และ Signing Key บน GitHub แนะนำให้เก็บไว้ใน Secret มากกว่า Variable เพราะข้อมูลที่เก็บไว้ใน Secret จะไม่สามารถกดเข้าไปดูในภายหลังได้ ในขณะที่ Variable สามารถเข้าไปดูได้ ซึ่งจะปลอดภัยน้อยกว่า
โดยเราจะเข้ารหัสด้วย GPG ด้วยคำสั่งแบบนี้
gpg -c --armor <keystore_file>
ยกตัวอย่างเช่น
gpg -c --armor release_keystore.jks
คำสั่งดังกล่าวจะให้เรากำหนด Passphrase เพื่อใช้ในการเข้ารหัส
เมื่อเข้ารหัสเสร็จแล้วก็จะได้ไฟล์ที่มีนามสกุลเป็น .asc
ออกมา ซึ่งเราจะเอาข้อมูลในไฟล์ดังกล่าวและ Passphrase ไปเก็บไว้บน GitHub ทั้งคู่ รวมไปถึงข้อมูลเกี่ยวกับการ Signing App อย่าง Keystore Password, Key Alias และ Key Password ด้วย
ส่วนคำสั่งถอดรหัสของ GPG และแปลงข้อมูลกลับเป็นไฟล์ Keystore (.jks
) ที่จะใส่ไว้ใน GitHub Actions จะใช้คำสั่งแบบนี้
gpg -d --passphrase "<passphrase>" --batch <encrypted_keystore_file>.asc > <keystore_file>
ยกตัวอย่างเช่น
gpg -d --passphrase "1234567890" --batch release_keystore.jks.asc > release_keystore.jks
โดยคำสั่งถอดรหัสจะใช้ตอนที่เขียนคำสั่งใน GitHub Actions ในภายหลัง
ต้องเก็บข้อมูลที่จำเป็นต่อ App Signing และ App Publishing ไว้ใน Repository Secret ของ GitHub
โดยเข้าไปที่ Repository ของเราบน GitHub แล้วเลือกไปที่ “Settings > Secrets and variables > Actions” แล้วกดปุ่ม New repository secret
ให้ใส่ข้อมูลที่จำเป็นสำหรับการ Signing App เก็บไว้ใน Secret ให้ครบทั้งหมด โดยข้อมูลแต่ละตัวจะกำหนดชื่อ Secret ว่าอะไรก็ได้ เพราะขึ้นอยู่กับคำสั่งที่เขียนไว้ใน GitHub Actions อีกที
ถ้าอยากให้เข้าใจง่าย จะตั้งชื่อ Secret แบบเดียวกับในบทความนี้ก็ได้เช่นกัน
ENCRYPTED_KEYSTORE
— ข้อมูล Signing Key ที่เข้ารหัสด้วย GPGKEYSTORE_PASSPHRASE
— Passphrase ที่ใช้ถอดรหัส Encrypted Signing Key (อันเดียวกับที่ใส่ตอนเข้ารหัสด้วย GPG)KEYSTORE_PASSWORD
— รหัสผ่านของ KeystoreKEYSTORE_KEY_ALIAS
— Key Alias ใน KeystoreKEYSTORE_KEY_PASSWORD
— รหัสผ่านของ Key AliasSERVICE_ACCOUNT_JSON
— ข้อมูล Service Account Key จาก Google Cloud Platform ที่อยู่ในรูปของ JSON
ต้องกำหนด Signing Config ใน Gradle ให้ใช้ Signing Key ที่มาจาก GitHub Actions
เพื่อให้ Gradle ในโปรเจคแอนดรอยด์ของเราสามารถใช้ Signing Key จาก GitHub Actions เพื่อใช้ทำ App Signing ได้ จะต้องกำหนด signingConfigs
ใน build.gradle
ของ App Module ไว้แบบนี้
// build.gradle (Module :app)
/* ... */
Properties properties = new Properties()
if (rootProject.file("local.properties").exists()) {
properties.load(rootProject.file("local.properties").newDataInputStream())
}
android {
signingConfigs {
release {
storeFile file(properties.getProperty('keystore_path'))
storePassword properties.getProperty('keystore_password')
keyAlias properties.getProperty('keystore_key_alias')
keyPassword properties.getProperty('keystore_key_password')
}
}
/* ... */
}
/* ... */
โดยเราจะให้ GitHub Actions เก็บค่าจาก Secret ไว้ในไฟล์ที่ชื่อว่า local.properties
แล้วให้ Gradle ดึงค่าดังกล่าวไปกำหนดไว้ใน signingConfigs
สำหรับ Release Build นั่นเอง ซึ่งจะประกอบไปด้วย Variable ดังนี้
keystore_path
— Path ของ Signing Key หรือ Keystorekeystore_password
— รหัสผ่านของ Keystorekeystore_key_alias
— Key Alias ใน Keystorekeystore_key_password
— รหัสผ่านของ Key Alias
ขั้นตอนทั้งหมดเตรียมพร้อมแล้ว ถึงเวลาสร้าง Workflow ใน GitHub Actions
การสร้าง Workflow สำหรับ GitHub Actions นั้นทำได้ไม่ยาก เพราะเขียนเป็นไฟล์ .yml
ไว้ใน <project_directort>/.github/workflows
ได้เลย
เจ้าของบล็อกจะสร้าง Workflow เพื่อทำ App Signing และ Publish ขึ้น Google Play เป็นไฟล์ที่ชื่อว่า publish-google-play.yml
โดยจะแบ่งออกเป็น 2 Job ด้วยกันดังนี้
build
— เพื่อทำ App Signing และได้ออกมาเป็นไฟล์.aab
เพื่อส่งต่อให้ Job ถัดไปpublish
— เอาไฟล์.aab
ที่ได้มาจาก Job ก่อนหน้า ส่งขึ้น Google Play
จึงเขียนคำสั่งออกมาเป็นแบบนี้
# <project_directory>/.github/workflows/publish-google-play.yml
name: Publish App to Google Play
on:
workflow_dispatch
jobs:
build:
name: Build AAB
# Do app signing here
publish:
name: Publish to Google Play
needs: build
# Do app publishing here
ขอย่อคำสั่งบางส่วนไว้ก่อน เพราะจะอธิบายส่วนนั้นเพิ่มในภายหลัง
โดย Workflow ตัวนี้ เจ้าของบล็อกกำหนดให้ทำงานเมื่อกดปุ่ม Run workflow บนหน้าเว็ปของ GitHub จึงกำหนด on
เป็น workflow_dispatch
ถ้าผู้อ่านอยากจะกำหนดเงื่อนไขในการทำงานของ Workflow ตัวนี้ให้เป็นรูปแบบอื่น เช่น ทำงานก็ต่อเมื่อมี Commit หรือ PR Merge เข้า Main Branch หรือใส่ Release Tag เป็นต้น ก็สามารถเปลี่ยนคำสั่งตรงนี้ได้ตามใจชอบ
คำสั่งใน Build Job
เนื่องจาก Job นี้ทำหน้าที่ Sign App ให้เป็นไฟล์ AAB ดังนั้นจึงเลือกใช้ Ubuntu ตัวล่าสุด และจะมีคำสั่ง Decrypt ของ GPG ไว้ใน Job ตัวนี้ด้วย
# <project_directory>/.github/workflows/publish-google-play.yml
# ...
jobs:
build:
name: Build AAB
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
cache: gradle
- name: Prepare Keystore
run: |
mkdir "${GITHUB_WORKSPACE}"/keystore
echo "${{secrets.ENCRYPTED_KEYSTORE}}" > keystore/keystore.asc
gpg -d --passphrase "${{secrets.KEYSTORE_PASSPHRASE}}" --batch keystore/keystore.asc > keystore/keystore.jks
- name: Prepare Keystore variables
run: |
echo "keystore_path=${GITHUB_WORKSPACE}/keystore/keystore.jks" &>> local.properties
echo "keystore_password=${{secrets.KEYSTORE_PASSWORD}}" &>> local.properties
echo "keystore_key_alias=${{secrets.KEYSTORE_KEY_ALIAS}}" &>> local.properties
echo "keystore_key_password=${{secrets.KEYSTORE_KEY_PASSWORD}}" &>> local.properties
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build AAB with Gradle
run: ./gradlew :app:bundleRelease
- name: Update AAB to artifactory
uses: actions/upload-artifact@v3
with:
name: release-app-bundle
path: app/build/outputs/
retention-days: 1
publish:
# ...
คำสั่งที่ใช้ในแต่ละ Step ของ Build Job ก็จะมีดังนี้
- Set up JDK 11 — ติดตั้ง JDK 11
- Prepare Keystore — สร้างไฟล์
keystore.asc
ด้วยข้อมูลจาก Secret (ENCRYPTED_KEYSTORE
) แล้ว Decrypt ด้วย GPG และใช้ Passphrase จาก Secret (KEYSTORE_PASSPHRASE
) โดยจะได้ออกมาเป็นไฟล์keystore/keystore.jks
หรือก็คือ Signing Key ที่ถอดรหัสและพร้อมใช้งานแล้วนั่นเอง - Prepare Keystore variables — กำหนดค่าต่าง ๆ ที่จำเป็นสำหรับ App Signing โดยเก็บไว้ใน
local.properties
ที่จะถูกเรียกใช้งานจาก Gradle อีกทีหนึ่ง - Grant execute permission for gradlew — กำหนดให้
gradlew
หรือ Gradle Executor ในโปรเจคเป็น Executable (เพื่อให้ใช้คำสั่ง./gradlew
ได้) - Build AAB with Gradle — Sign App ให้กลายเป็นไฟล์ AAB ด้วย Gradle
- Update AAB to artifactory — เก็บไฟล์ AAB และไฟล์อื่น ๆ ที่ได้จาก App Signing ไว้ใน Artifactory เพื่อให้ Job ถัดไปเรียกใช้งานต่อได้ โดยกำหนดเป็นชื่อ Artifact ว่า
release-app-bundle
คำสั่งใน Publish Job
เพื่อเอาไฟล์ที่ได้จาก Build Job มา Publish ขึ้น Google Play ใน Job นี้จะมีการเรียกใช้ r0adkll/upload-google-play ที่เป็น Action สำเร็จรูปที่ช่วยให้เรา Publish App ขึ้น Google Play ได้ง่ายขึ้น และเลือกใช้ Ubuntu ตัวล่าสุดเหมือนเดิม
# <project_directory>/.github/workflows/publish-google-play.yml
# ...
jobs:
build:
# ...
publish:
name: Publish to Google Play
needs: build
runs-on: ubuntu-latest
steps:
- name: Download build output from build job
uses: actions/download-artifact@v3
with:
name: release-app-bundle
- name: Upload Android Release to Play Store
uses: r0adkll/upload-google-play@v1
with:
serviceAccountJsonPlainText: ${{secrets.SERVICE_ACCOUNT_JSON}}
releaseFiles: bundle/release/app-release.aab
packageName: com.akexorcist.sleepingforless
track: production
mappingFile: mapping/release/mapping.txt
คำสั่งที่ใช้ในแต่ละ Step ของ Publish Job ก็จะมีดังนี้
- Download build output from build job — ดาวน์โหลด Artifact ที่ชื่อ
release-app-bundle
ที่ได้จาก Job ก่อนหน้ามาจาก Artifactory หรือก็คือไฟล์ทั้งหมดที่ได้จากทำ App Signing ใน Build Job นั่นเอง - Upload Android Release to Play Store — Publish ไฟล์ AAB และไฟล์
mapping.txt
ขึ้น Production Track ของ Google Play โดยใช้ Service Account Key ที่เก็บไว้ใน Secret (SERVICE_ACCOUNT_JSON
)
เพียงเท่านี้ Workflow ของเราก็พร้อมสำหรับการใช้งานแล้ว
อย่าลืมทดสอบการทำงานของ Workflow ด้วย
เพื่อให้มั่นใจว่า Workflow ของ GitHub Action ตัวนี้สามารถทำงานได้อย่างถูกต้อง ก็อย่าลืมทดสอบการทำงานด้วยนะ
และอย่าลืมว่าใน Workflow นี้ได้กำหนดให้ Publish App ขึ้น Production Track ดังนั้นอย่าลืมแก้ไขให้ Publish App ขึ้น Internal Testing Track ก่อน เพื่อทดสอบการทำงาน เมื่อทดสอบผ่านและพร้อมนำไปใช้งานจริงแล้ว ก็ค่อยเปลี่ยนกลับไปเป็น Production Track (จะเป็น Open Track หรือ Closed Track ก็ได้) ในภายหลัง
ตัวอย่างโปรเจคที่ใช้ GitHub Actions ในการ Publish App ขึ้น Google Play
ต้องบอกว่าก่อนที่จะเขียนบทความนี้ขึ้นมา เจ้าของบล็อกได้ลองลงมือทำจริงกับโปรเจคส่วนตัว ซึ่งแอปที่ว่านี้เป็น Public Repository อยู่บน GitHub
ดังนั้นผู้อ่านคนใดที่ทำตามแล้วติดปัญหา หรืออยากจะดูตัวอย่างการทำงานของ Workflow ที่อธิบายไว้ในบทความนี้ ก็สามารถตามเข้าไปดูกันได้ใน Sleeping For Less by Akexorcist [GitHub] กันได้เลย
และเนื่องจากโปรเจคดังกล่าวเป็น Public Repository บน GitHub จึงเป็นที่มาว่าเนื้อหาในบทความนี้มีขั้นตอนและวิธีต่าง ๆ เพื่อป้องกันข้อมูลและไฟล์ที่สำคัญต่อการ Publish App ขึ้น Google Play เพิ่มเข้าไปด้วยนั่นเอง
ลากันทีกับการ Publish App ขึ้น Google Play แบบ Manual
เพียงเท่านี้โปรเจคของเราบน GitHub ก็มี Continuous Deployment ที่สร้างแบบง่าย ๆ ด้วย GitHub Actions แล้ว ซึ่งจะช่วยลดขั้นตอนในการทำงานที่ไม่จำเป็นต้องเสียเวลาลงมือทำด้วยตัวเองทุกครั้ง ทำให้เราสามารถโฟกัสการทำงานในส่วนอื่น ๆ ที่จำเป็นกว่าได้มากขึ้น
นอกจากนี้เรายังสามารถปรับ Workflow ตัวนี้ให้ตรงกับความต้องการมากขึ้นได้อีกด้วย เช่น อยากจะ Publish App ไปที่อื่นนอกเหนือจาก Google Play ก็สามารถทำได้ไม่ยาก หรือถ้าอยากจะแนบข้อมูลสำหรับ What’s new ในหน้าดาวน์โหลดแอป หรือกำหนด Staged Rollout ก็สามารถกำหนดผ่าน Action ของ r0adkll/upload-google-play ได้เลย เพราะรองรับอยู่แล้ว
และถึงแม้ว่าโปรเจคของเราจะมี Continuous Deployment หรือ CD แล้ว แต่ก็ควรพัฒนาและปรับปรุงให้ CI/CD ทำงานได้ครอบคลุมมากขึ้นอยู่ตลอดเวลา เพราะในบทความนี้ก็นำเสนอแค่การทำงานส่วนหนึ่งของ CI/CD ที่แอปบนแอนดรอยด์ส่วนใหญ่ควรจะมีเท่านั้นครับ