Idea to Open Testing
Pipeline tự động · Flutter

Từ ý tưởng đến Open Testing

Chín chặng AI chạy sau khi người dùng gõ một ý tưởng vào — mỗi chặng nêu rõ skill nào lo, sinh ra file gì, và chỗ nào bắt buộc phải có con người bấm nút.

Nguồn: github.com/shipflutter/skills @ develop (commit 01/07/2026) — 11 skill
Đối chiếu thực tế: dự án Call Blocker trong session này
Soạn 02/09/2026

Toàn cảnh

Đánh số ở đây là thông tin thật, không phải trang trí: mỗi chặng ăn đầu ra của chặng trước. Chặng tô cam là chỗ pipeline dừng lại chờ người.

00
Thu thập đầu vào
01
Ý tưởng → đặc tả
02
Phân tích chức năng
03
Dựng ứng dụng
04
Unity Ads
05
Firebase + GA
06
Keystore & secrets
07
Landing Cloudflare
08
Open testing CH Play
AI chạy trọn, không cần hỏi AI chạy, cần người duyệt một bước Người phải tự làm — AI không thay được

Chi tiết từng chặng

Mỗi chặng có cùng cấu trúc: skill dùng, việc AI làm, file sinh ra, và điều kiện để đi tiếp.

00

Thu thập đầu vào — hỏi một lần duy nhất

ai-studio-mobile references/intake.md PLAN.md

Trước khi viết dòng code nào, AI hỏi trọn bộ câu hỏi rồi chốt. Skill ai-studio-mobile quy định rõ: hỏi đủ đầu vào, xác nhận, rồi mới chạy từng phase — và giữ PLAN.md làm nguồn sự thật duy nhất, tick ✅ sau mỗi phase.

AI hỏi

  • Tên app + tiêu đề store (tên store là duy nhất toàn cầu — cần phương án dự phòng ≤30 ký tự)
  • Application id, ví dụ com.theyourlist.callblocker
  • Thị trường, ngôn ngữ, mô hình kiếm tiền
  • Có sẵn Firebase / Unity / Play Console chưa

Sinh ra

  • PLAN.md — checklist các phase
  • Bản chốt đầu vào để các chặng sau không phải hỏi lại
01

Ý tưởng → đặc tả chi tiết

add-feat assets/templates/

AI nở ý tưởng một dòng thành bộ tài liệu có cấu trúc, dùng đúng 5 template của skill. Đây là chặng biến “tôi muốn app chặn cuộc gọi rác” thành các user story đánh mã EPxx.US### có tiêu chí nghiệm thu.

Template dùng

  • feature-brief.md
  • user-story-template.md
  • technical-design-template.md
  • screen-layout-template.md

Sinh ra

  • resources/user-story/
  • resources/technial-design/
  • resources/screens/ — layout ASCII kèm mục ## Events để suy ra luồng
02

Phân tích chức năng — SRS ba khung nhìn

add-srs resources/srs.sh

Từ cùng một bộ nguồn ở chặng 01, skill dựng srs-index.html với ba khung nhìn liên thông. Đây là chỗ AI tự soát: story nào chưa có màn hình, màn hình nào chưa nối vào luồng.

Ba khung nhìn

  • Docs — SRS đầy đủ, mục lục dính
  • Flow — canvas mockup ASCII nối bằng mũi tên suy ra từ ## Events
  • Board — kanban đọc từ dòng Status: của user story

Lưu ý vận hành

  • Copy skills/add-srs/assets/srs.sh sang resources/srs.sh, đừng viết lại
  • Sửa tiêu đề sidebar hardcode sang tên dự án
  • Story thiếu Status: mặc định là Done
03

Dựng ứng dụng — UI → bloc → usecase → repository

add-feat flutter-unit-test-coverage flutter-integration-test flutter-driver-screenshot-test

Skill quy định thứ tự triển khai và bắt buộc mỗi tầng có test riêng. Ba skill test chạy nối tiếp: unit/widget có coverage, integration trên máy ảo, rồi driver chụp màn hình dựng e2e-index.html và tự mở.

Bố cục code

  • lib/presentation/ · lib/integration/
  • test/ · integration_test/ · test_driver/
  • screenshots/

Cổng chất lượng

  • flutter analyze sạch
  • run_test.sh --report → lcov + HTML
  • e2e.sh → ảnh chụp + báo cáo
04

Tích hợp Unity Ads

không có skill — AI tự làm com.unity3d.ads:unity-ads:4.7.0

Repo shipflutter không có skill nào cho Unity Ads. AI phải tự dựng: thêm dependency, viết cầu nối Kotlin cho interstitial/rewarded, và một PlatformView cho banner vì banner là view Android thật, không đi qua MethodChannel được.

AI làm được

  • Tạo app trên dashboard, lấy Game ID
  • Tạo 3 placement Interstitial_Android · Rewarded_Android · Banner_Android
  • Đưa id vào cấu hình đọc qua --dart-define
  • Trả lời COPPA theo bản chất app

Người phải làm

  • Payout profile — cần thông tin thuế và ngân hàng. Thiếu nó thì tiền quảng cáo không về tài khoản
  • app-ads.txt đặt lên domain, thiếu sẽ bị giảm giá quảng cáo

Mặc định phải là test mode

Để testMode = true làm mặc định, chỉ tắt bằng cờ build tường minh --dart-define=UNITY_TEST_MODE=false. Như vậy một bản release quên cấu hình sẽ chạy quảng cáo test, chứ không vô tình phát quảng cáo thật sai tài khoản.

05

Firebase và Google Analytics

firebase-basics google-services.json

Skill firebase-basics lo phần CLI: đăng nhập, chọn project, tải file cấu hình. Việc nối GA sang Unity thì nằm ở Unity Dashboard, đường dẫn dễ tìm nhầm nhất trong cả pipeline.

Trình tự bắt buộc

  • Tạo Firebase project, bật Google Analytics ngay lúc tạo
  • Thêm app Android theo đúng package name
  • google-services.jsonandroid/app/, nhớ gitignore
  • Áp plugin google-services có điều kiện, để clone mới vẫn build được khi thiếu file

Đường dẫn nối GA ↔ Unity

  • Development → project → SettingsDeveloper Data → Google Analytics (Firebase) → Create link
  • Xong phải thấy LinkedSpecial services: 2 Authorized

Cổng người: scope OAuth rộng hơn tưởng

Unity xin analytics.readonly, analytics.manage.userscloud-platform — cái cuối là toàn quyền Google Cloud, không giới hạn ở Analytics. Popup OAuth cũng thường bị chặn trong browser nhúng. Để người tự đọc và tự bấm Allow.

06

App key, keystore và secrets

appdist .app_dist/ scripts/prepare.sh

Chặng người phải nhúng tay sâu nhất. AI dựng được khung và script, nhưng mật khẩu keystore thì người tự đặt, và file .jks thì người tự cất.

File cần có trong .app_dist/

  • <app>.jks — keystore ký release
  • playstore-service-account.json — khoá API Play Console
  • iOS: .p12, .mobileprovision, WWDR cert

AI làm được

  • Sinh lệnh keytoolandroid/key.properties
  • Chạy prepare.sh → base64 cho GitHub Secrets
  • Dựng .github/workflows/deploy-uat.yml
  • Kiểm tra .gitignore đã chặn *.jks, .env.prod, .app_dist/

Mất keystore là mất app

Không có cách khôi phục. Mất file .jks đồng nghĩa mất vĩnh viễn quyền cập nhật app đã phát hành — phải đăng package name mới. Sao lưu trước khi chạy tiếp.

07

Trang thông tin ứng dụng trên Cloudflare Pages

store-release/store-preview marketing-app-banner universal-download-link deploy: không có skill

Ba skill lo phần nội dung trang, nhưng không skill nào đụng tới Cloudflare. AI phải tự deploy bằng Wrangler hoặc nối Git integration.

Skill sinh ra sẵn

  • store-preview/listing.json, mockup SVG điện thoại và tablet, index.html
  • app-banner.js — thanh “Get the app” tự nhận iOS/Android
  • get-index.html + gen-qr.py — một link và một QR cho cả hai store

AI tự bù phần deploy

  • npx wrangler pages deploy ./site
  • Trang bắt buộc: /, /privacy, /get/, /app-ads.txt
  • Lấy URL privacy để điền vào Play Console ở chặng 08

Privacy policy là đường găng

Play bắt buộc có URL chính sách công khai, và app đọc danh bạ hay lọc cuộc gọi sẽ bị soát kỹ hơn. Trang này phải deploy xong trước khi mở form khai báo ở chặng 08, nếu không pipeline sẽ kẹt ở đó.

08

Submit Open Testing lên CH Play

store-release appdist upload-playstore.py

Open testing trong Google Play Developer API là track beta — không phải internal (mặc định của skill) cũng không phải alpha (closed testing). Đây là chi tiết dễ sai nhất ở chặng cuối.

Bốn track của API

  • internal — nội bộ
  • alpha — closed testing
  • betaopen testing
  • production — phát hành chính thức

Người phải làm trước

  • Tạo app trong Play Console, đóng phí tài khoản
  • Service account: Setup → API access → quyền Release manager → tải JSON
  • Khai App content: privacy policy, Data safety, content rating, target audience, khai app có quảng cáo
# đẩy AAB lên track open testing
python skills/appdist/scripts/upload-playstore.py \
  --track beta \
  --aab build/app/outputs/bundle/release/app-release.aab

# hoặc qua fastlane
PLAYSTORE_TRACK=beta bundle exec fastlane android beta

Kiểm tra điều kiện lên production riêng

Google có yêu cầu về số lượng tester và thời gian chạy thử trước khi tài khoản cá nhân được lên production — điều kiện này thay đổi theo thời điểm và theo loại tài khoản. Đọc lại trong Play Console trước khi hứa mốc phát hành, đừng suy đoán.

Những chỗ AI không thay được người

Tổng hợp các cổng chặn. Pipeline nên dừng đúng những chỗ này và nói rõ lý do, thay vì cố lách.

ChặngViệcVì sao AI không làm
05Bấm Allow trên màn hình OAuth GoogleLà hành vi xác thực, và cấp scope cloud-platform rất rộng
06Đặt mật khẩu keystore, cất file .jksBí mật dài hạn, mất là mất app vĩnh viễn
04Payout profile UnityThông tin thuế và tài khoản ngân hàng
08Đăng ký tài khoản Play, đóng phíTạo tài khoản và thanh toán
08Ký các khai báo pháp lý về nội dungLà cam kết pháp lý của chủ tài khoản

Hai khoảng trống của bộ skill

Nói thẳng để không kỳ vọng sai: repo phủ rất tốt phần đặc tả, test và phát hành, nhưng hở hai chỗ mà yêu cầu này cần.

Khoảng trốngRepo có gì gần nhấtAI phải tự bù
Unity Ads Không có skill nào nhắc tới Unity Ads Toàn bộ: cầu nối Kotlin, PlatformView banner, cấu hình placement, nhịp hiển thị quảng cáo
Cloudflare Pages Sinh được nội dung trang qua store-preview, marketing-app-banner, universal-download-link Bước deploy: Wrangler hoặc Git integration, domain, DNS

Chuỗi lệnh rút gọn

Chạy từ gốc repo, sau khi chặng 00 đã chốt đầu vào.

# 02 — dựng SRS
cp .claude/skills/add-srs/assets/srs.sh resources/srs.sh
bash resources/srs.sh

# 03 — cổng chất lượng
flutter analyze
bash .claude/skills/flutter-unit-test-coverage/scripts/run_test.sh --report
bash .claude/skills/flutter-driver-screenshot-test/scripts/e2e.sh

# 06 — hạ tầng phát hành
cp -r .claude/skills/appdist/assets/app_dist_template .app_dist
cp .claude/skills/appdist/assets/.env.example .env.prod
bash .claude/skills/appdist/scripts/prepare.sh

# 07 — landing
npx wrangler pages deploy ./site

# 08 — open testing
flutter build appbundle --release --dart-define=UNITY_TEST_MODE=false
python .claude/skills/appdist/scripts/upload-playstore.py --track beta