Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions .github/workflows/mobile-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ jobs:
- name: Enable corepack (pnpm)
run: corepack enable

# Capacitor 8 のテンプレは capacitor.build.gradle で JavaVersion.VERSION_21=JDK 21 必須
# (AGP 8.13 / Gradle 8.14.3)。17 だと Java 21 ターゲットでコンパイルエラーになる。
- uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: temurin
java-version: "17"
java-version: "21"

# 供給網リスク低減: 全ビルド許可せず mobile/pnpm-workspace.yaml の allowBuilds(esbuild のみ)で許可する。
# --ignore-workspace を付けると pnpm-workspace.yaml=allowBuilds が読まれず ignored builds になるので付けない
#(mobile/pnpm-workspace.yaml があるため上位の repo ルート workspace には巻き込まれない)。
- name: Install deps
run: pnpm install --ignore-workspace --config.dangerouslyAllowAllBuilds=true
run: pnpm install

- name: Build web (Vite)
run: pnpm build
Expand All @@ -49,14 +54,18 @@ jobs:
- name: Capacitor sync
run: pnpm exec cap sync android

- name: Add CAMERA permission to AndroidManifest (QR スキャナの getUserMedia 用)
- name: AndroidManifest へ権限注入 (CAMERA=QRスキャナ / BILLING=アプリ内課金)
working-directory: mobile/android
run: |
# 生 getUserMedia でカメラを使うため CAMERA 権限を注入する(Capacitor は自動付与しない)。
# 無いとネイティブビルドの QR スキャンが実行時にパーミッションエラーで失敗する。
# CAMERA: 生 getUserMedia でカメラを使うため注入(Capacitor は自動付与しない)。無いと QR スキャンが
# 実行時にパーミッションエラーで失敗する。
# BILLING: @capgo/native-purchases の課金に com.android.vending.BILLING が要る。Play Billing ライブラリが
# merge するはずだが、library 依存に頼らず明示注入して確実化(manifest merge は重複を 1 つに畳む)。
manifest=app/src/main/AndroidManifest.xml
grep -q 'android.permission.CAMERA' "$manifest" || \
sed -i 's#</manifest># <uses-permission android:name="android.permission.CAMERA" />\n</manifest>#' "$manifest"
grep -q 'com.android.vending.BILLING' "$manifest" || \
sed -i 's#</manifest># <uses-permission android:name="com.android.vending.BILLING" />\n</manifest>#' "$manifest"
echo "--- AndroidManifest.xml の権限 ---"; grep -n 'uses-permission' "$manifest" || true

- name: Gradle assembleDebug
Expand Down
73 changes: 73 additions & 0 deletions .github/workflows/mobile-ios.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# ぺたりん モバイル: iOS ビルド検証(Capacitor 8・Swift Package Manager)。
# web を Vite でビルド → cap add ios(毎回生成・ios/ は gitignore)→ Info.plist に NSCameraUsageDescription を
# 注入(QR スキャナの getUserMedia 用・Android の CAMERA 注入と対称)→ 署名なしで simulator 向けにコンパイル検証。
# 署名・実機 .ipa・App Store 申請は Apple Developer 証明書(macOS/署名)が要るので別途。ここはコンパイルが通るかの検証。
# Capacitor 8 は Xcode 26+ を要求=runner の Xcode 次第(未達ならこの job は環境要件待ちとして赤くなる)。
# Actions はサプライチェーン対策で full commit SHA にピン留め(publish.yml / mobile-android.yml と同方針・Dependabot 更新)。
name: mobile-ios

on:
workflow_dispatch: {}
push:
tags:
- "mobile-v*"

permissions:
contents: read

jobs:
build:
# macos-latest はイメージ更新で Xcode が変わり「Xcode 26+ 必須」を非決定的にするため固定する。
# Cap8 要件の Xcode が無ければこの job は失敗=要件未達が可視化される(必要なら setup-xcode で pin)。
runs-on: macos-15
defaults:
run:
working-directory: mobile
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.0
with:
persist-credentials: false # 読み取り専用ビルド=認証情報を .git/config に残さない

- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0
with:
node-version: 22
package-manager-cache: false # PR 由来の cache poisoning を release に伝播させない

- name: Enable corepack (pnpm)
run: corepack enable

# 供給網リスク低減: 全ビルド許可せず mobile/pnpm-workspace.yaml の allowBuilds(esbuild のみ)で許可する。
# --ignore-workspace を付けると pnpm-workspace.yaml=allowBuilds が読まれず ignored builds になるので付けない
#(mobile/pnpm-workspace.yaml があるため上位の repo ルート workspace には巻き込まれない)。
- name: Install deps
run: pnpm install

- name: Build web (Vite)
run: pnpm build

- name: Add iOS platform
run: pnpm exec cap add ios

- name: Capacitor sync
run: pnpm exec cap sync ios

- name: Info.plist へ NSCameraUsageDescription 注入 (QR スキャナの getUserMedia 用)
working-directory: mobile/ios
run: |
# iOS 14.3+ の WKWebView は getUserMedia 対応だが、Info.plist のカメラ用途説明が無いと実行時に拒否される。
# Android の CAMERA 注入と対称に「生成物に依存せず再現可能」に注入する(Delete→Add で冪等)。
plist=App/App/Info.plist
/usr/libexec/PlistBuddy -c "Delete :NSCameraUsageDescription" "$plist" 2>/dev/null || true
/usr/libexec/PlistBuddy -c "Add :NSCameraUsageDescription string 'QRコードを読み取ってグループに参加するためにカメラを使用します'" "$plist"
echo "--- Info.plist のカメラ用途 ---"; /usr/libexec/PlistBuddy -c "Print :NSCameraUsageDescription" "$plist"

- name: Xcode で署名なしコンパイル検証 (simulator)
working-directory: mobile/ios/App
run: |
# 署名・provisioning は Apple Developer 証明書が要るので CI ではコンパイル検証のみ(simulator SDK)。
# 実機 .ipa / App Store 申請は別(証明書を Secrets に入れてから署名ビルドを足す)。
# In-App Purchase(StoreKit2) は entitlement 不要=App Store Connect の product 登録で機能する。
set -o pipefail
xcodebuild -project App.xcodeproj -scheme App -configuration Debug \
-sdk iphonesimulator -destination 'generic/platform=iOS Simulator' \
CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO build | tail -40
16 changes: 9 additions & 7 deletions mobile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ PC 拡張の同期エンジンをそのまま再利用し、**クラウド同期
- `src/storage-shim.js` … `chrome.storage.local` / `onChanged` を 1 プロセス KV で再現(バックエンド注入式)
- `src/preferences-backend.js` … シムの裏付け(Capacitor Preferences)
- `src/sync-orchestrator.js` … 拡張 `background.js` のモバイル版(reconcile スケジューリング+realtime WS)
- `src/iap.js` … 買い切り課金(解禁ゲート。ネイティブ配線は TODO
- `src/iap.js` … 買い切り課金の解禁ゲート(`@capgo/native-purchases` で StoreKit2 / Play Billing を実配線。所有判定はストア照会+Preferences キャッシュ。web は dev 解錠フラグ
- `vite.config.js` … `@shared` → `../src/shared`(同期エンジンを**単一ソース**で参照)

同期エンジン(`vault.js`/`sync.js`/`relay-transport.js`/`storage.js`/`markdown.js`)はコピーせず拡張と共有する。
Expand Down Expand Up @@ -39,12 +39,14 @@ pnpm -C mobile exec cap sync

## ビルド(CI)

- Android: [`.github/workflows/mobile-android.yml`](../.github/workflows/mobile-android.yml)(ubuntu・JDK17・Gradle)。署名は未設定=当面 debug APK。
- iOS: macOS runner + 署名証明書(App Store Connect API key / provisioning)を Secrets に投入してから有効化する(TODO)。
Capacitor 8(Android: minSdk24 / compileSdk36 / Gradle 8.14.3 / **JDK21**、iOS: deployment target 15 / **Xcode26+** / SPM)。

- Android: [`.github/workflows/mobile-android.yml`](../.github/workflows/mobile-android.yml)(ubuntu・JDK21)。`cap add android`→CAMERA/BILLING 権限を AndroidManifest へ注入→`assembleDebug`→APK artifact。署名は未設定=当面 debug APK(release 署名は keystore を Secrets 投入後に追加)。
- iOS: [`.github/workflows/mobile-ios.yml`](../.github/workflows/mobile-ios.yml)(macOS runner・SPM)。`cap add ios`→Info.plist へ NSCameraUsageDescription 注入→署名なし simulator コンパイル検証。実機 .ipa/署名/申請は Apple Developer 証明書を Secrets 投入後に追加。

## 残 TODO

- IAP プラグイン配線(`src/iap.js`:product id `jp.nephilim.petarin.sync` を App Store / Play に non-consumable で登録 → restore/purchase)。
- 付箋の新規作成/編集 UI(現状は同期表示が主・閲覧中心)。
- 本番 relay は Custom Domain へ(拡張側と共通課題)。
- iOS 署名と CI、ストア申請(`/vava` 連携)。
- ストア側 product 登録: App Store Connect / Google Play で `jp.nephilim.petarin.sync` を non-consumable(¥500)登録(ストア側手作業)。
- ネイティブ実機の目視確認(iPhone/Android で付箋 CRUD・ペアリング・カメラ QR・購入フロー)。
- iOS 署名証明書(App Store Connect API key / provisioning)を Secrets 投入して署名ビルド/ストア申請(`/vava` 連携)。
- 課金 enforcement の強化(当面はクライアント側のストア所有判定=`iap.js`、後段で relay 側 enforcement へ)。
13 changes: 7 additions & 6 deletions mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@
"open:ios": "cap open ios"
},
"dependencies": {
"@capacitor/android": "^6.1.0",
"@capacitor/app": "^6.0.1",
"@capacitor/core": "^6.1.0",
"@capacitor/ios": "^6.1.0",
"@capacitor/preferences": "^6.0.1",
"@capacitor/android": "^8.4.1",
"@capacitor/app": "^8.1.0",
"@capacitor/core": "^8.4.1",
"@capacitor/ios": "^8.4.1",
"@capacitor/preferences": "^8.0.1",
"@capgo/native-purchases": "^8.4.6",
"jsqr": "^1.4.0",
"qrcode-generator": "^2.0.4"
},
"devDependencies": {
"@capacitor/cli": "^6.1.0",
"@capacitor/cli": "^8.4.1",
"@vitejs/plugin-basic-ssl": "1.2.0",
"vite": "^5.4.0"
}
Expand Down
Loading