./build.sh 一つで Flutter・Tauri・Xcode iOS・Android/Kotlin/Gradle・React/Next/Node を検出し、人・CI・AI・MCP が同じ手順でビルドするオーケストレーター
現在のディレクトリが単一プロジェクトかモノレポかを判定し、ビルド可能なプロジェクトを検出して、重複する内部プロジェクトを除外したうえで適切なアダプターを実行します。
3.3 では Python 3 が Node workspace、Flutter path、Gradle composite、明示設定から依存関係を推論し、topological layer 順に実行します。Xcode-only iOS adapter と、外部 package 不要の root 制限付き stdio MCP server も含みます。
| 観点 | 既定動作 |
|---|---|
| 実行 | 非対話・CI セーフ |
| バージョン | 明示しない限り変更しない |
| モノレポ | 依存関係の topological 順にビルド |
| Flutter | macOS は AAB+IPA、その他は AAB |
| Tauri | OS 標準バンドル、macOS 署名完備時は .pkg |
| 失敗 | 他プロジェクトを続行し最後に集計 |
| UBS 更新 | 通常ビルドとは完全に分離 |
curl -fsSL https://raw.githubusercontent.com/Loop-Suite/Universal-Build-Script/main/install.sh | bash
./build.sh detect
./build.sh audit
./build.sh plan --json
./build.sh graph --json
./build.shPython 3.9 以上は必須、Rust は任意です。
./scripts/build-rust-helper.sh
# または install.sh を UBS_BUILD_RUST_HELPER=true で実行2.x から 3.x への更新:
UBS_FORCE=trueで installer を一度実行してください。3.x 以降は./build.sh updateが 25 個の管理ファイルを更新します。
installer は不変の current release ref を既定で使います。UBS_INSTALL_REF、UBS_JOBS、UBS_INSTALL_MODE、UBS_MANAGE_GITIGNORE、UBS_GRADLE_FLAGS、UBS_GRADLE_OPTIMIZE を設定できます。
成果物レポートを含む例:
./build.sh \
--flutter-outputs appbundle,web \
--version-bump none \
--report-json .ubs/build-report.jsonflowchart TD
U["人 / CI / AI / MCP"] --> B["build.sh エントリーポイント"]
B --> D["プロジェクト検出・重複除外"]
D --> P["依存 graph・topological 計画"]
P --> A{"アダプター"}
A -->|"Tauri"| T["OS バンドル / macOS 署名 pkg"]
A -->|"Flutter"| F["AAB / APK / IPA / Web"]
A -->|"Gradle"| G["Android / Kotlin / KMP"]
A -->|"Node"| N["React / Next / Node"]
A -->|"Xcode"| X["Release archive / 任意 IPA export"]
T --> R["終了状態・成果物レポート"]
F --> R
G --> R
N --> R
X --> R
flowchart LR
R["ディレクトリ"] --> T{"Tauri 設定?"}
T -->|"はい"| TA["Tauri として登録し frontend 重複除外"]
T -->|"いいえ"| F{"Flutter pubspec?"}
F -->|"はい"| FL["Flutter として登録し platform 重複除外"]
F -->|"いいえ"| X{"Xcode workspace/project?"}
X -->|"はい"| XI["Xcode-only iOS"]
X -->|"いいえ"| G{"Gradle 設定?"}
G -->|"はい"| GR["Android / KMP / Kotlin / Gradle 分類"]
G -->|"いいえ"| N{"package.json + scripts.build?"}
N -->|"はい"| NO["Next / React / Node 分類"]
N -->|"いいえ"| S["子ディレクトリ走査"]
優先順位は Tauri → Flutter → Xcode → Gradle → Node です。Tauri/Flutter 内部 project を二重検出しません。
flowchart TB
E["薄い ./build.sh"] --> P["Python 3: 引数・検出・計画・並列・Node・Gradle"]
P --> S["Bash: Flutter・Tauri・install・recovery"]
P --> N["Node package manager"]
P --> G["Gradle"]
S --> F["Flutter CLI"]
S --> T["Tauri/Cargo + Apple tooling"]
P --> R["Rust: manifest 一括 hash・検証"]
P --> J["機械可読 JSON"]
F --> A["成果物"]
T --> A
G --> A
--jobs N で独立 project を制限付き並列実行できます。Node は package/lock 入力が同じ場合 install を省略し、UBS_INSTALL_MODE=always で再実行できます。Rust helper がなければ portable fallback を使います。
stateDiagram-v2
[*] --> Detect
Detect --> Select
Select --> Build
Build --> Success: exit 0
Build --> Failed: non-zero
Success --> More
Failed --> Stop: fail-fast
Failed --> More: 既定
More --> Build: 次あり
More --> Aggregate: 完了
Stop --> Aggregate
Aggregate --> [*]
| 種類 | 検出条件 | 既定ビルド | 主な成果物 |
|---|---|---|---|
| Tauri 2 | src-tauri/tauri.conf.json |
tauri build |
OS 標準バンドル、macOS .pkg |
| Flutter | Flutter SDK を宣言した pubspec.yaml |
選択した release 出力 | AAB、分割 APK、IPA、Web、symbols |
| Xcode iOS | *.xcworkspace / *.xcodeproj |
Release archive | XCArchive、任意 IPA |
| Android | Android Gradle plugin | app は bundleRelease |
Gradle 設定依存 |
| Kotlin/KMP/Gradle | Gradle plugin・settings | build |
JAR・ターゲット別成果物 |
| Next/React/Node | 文字列の scripts.build |
package manager build | .next、dist、build 等 |
.git、node_modules、build、dist、target、.gradle、.dart_tool、.next は再帰検出から除外します。
./build.sh detect --json /workspace
./build.sh audit --json /workspace
./build.sh plan --json /workspace
./build.sh graph --json /workspace
./build.sh build --project apps/mobile
./build.sh build --all --type flutter
./build.sh --flutter-outputs appbundle,apk,ipa,web
./build.sh --fail-fast
./build.sh --report-json .ubs/build-report.json| オプション | 内容 |
|---|---|
| `--version-bump none | build |
| `--flutter-outputs auto | LIST` |
--project PATH |
指定 project と検出された先行依存 project を実行 |
--all --type TYPE |
モノレポを種類で絞り込み |
--clean / --skip-clean |
Flutter キャッシュ方針 |
--report-json PATH |
プロジェクト別状態・成果物を保存 |
終了コードは、全成功が 0、検出/ビルド失敗または対象なしが 1、不正引数が 2 です。
選択した全プロジェクトの処理後、ローカルの対話端末では成功した成果物の場所を Finder、Explorer、または xdg-open で開きます。Flutter は build/、Tauri は bundle または署名 package、Gradle は outputs/libs、Node は dist/build/.next、Xcode は build/ubs を対象にします。
flowchart LR
B["選択 project を build"] --> S{"成功成果物あり?"}
S -->|"なし"| E["status のみ出力"]
S -->|"あり"| M{"UBS_OPEN_OUTPUT"}
M -->|"auto + local TTY"| D["成果物 folder を正規化"]
M -->|"true"| D
M -->|"false / CI / pipe"| E
D --> O["Finder / Explorer / xdg-open"]
既定の UBS_OPEN_OUTPUT=auto は CI や非対話 pipe で GUI を開きません。強制する場合は true、無効化する場合は false、互換スイッチは UBS_NO_OPEN=true です。folder を開けなくても成功済み build は失敗にならず、UBS_NO_NOTIFY は macOS 通知だけを制御します。
flowchart TD
S["出力選択"] --> A{"auto?"}
A -->|"macOS"| MI["AAB + IPA"]
A -->|"その他"| AN["AAB"]
A -->|"明示リスト"| E["AAB / APK / IPA / Web の組み合わせ"]
MI --> I{"IPA を含む?"}
E --> I
I -->|"はい"| P{"アプリ固有 ExportOptions.plist?"}
P -->|"あり"| O["アプリ設定を使用"]
P -->|"なし"| T["管理された一般テンプレート"]
O --> B["release + symbol 分離"]
T --> B
AN --> B
ネイティブ出力には release、obfuscation、split debug info を適用します。Flutter Web は release 最適化対象ですが、ネイティブ Dart obfuscation の対象ではありません。
flowchart TD
B["tauri build"] --> O{"ホスト OS"}
O -->|"Windows"| W["MSI / NSIS 等"]
O -->|"Linux"| L["deb / AppImage / rpm 等"]
O -->|"macOS"| M{"package mode"}
M -->|"unsigned"| A[".app"]
M -->|"auto"| C{"署名設定完備?"}
M -->|"signed"| V{"署名設定完備?"}
C -->|"いいえ"| A
C -->|"はい"| P["codesign 検証 + 署名 .pkg"]
V -->|"はい"| P
V -->|"いいえ"| E["パッケージ前に失敗"]
通常ビルドは UBS コードをダウンロードしません。
./build.sh update --check
./build.sh update --dry-run
./build.sh update
./build.sh update --check --json
./build.sh update --prune-backups 30sequenceDiagram
participant C as 呼び出し元
participant U as Updater
participant H as HTTPS 配布元
participant B as Backup
participant F as 管理ファイル
C->>U: check / dry-run / apply
U->>H: manifest 取得
U->>U: SemVer・許可パス・重複・欠落検査
U->>F: local SHA-256 比較
alt check / dry-run
U-->>C: 変更一覧のみ
else apply
U->>H: 全変更ファイル取得
U->>U: 全 SHA-256 を先に検証
U->>B: 既存ファイル保存
U->>F: 一時ファイル + rename
alt 途中失敗
B-->>F: ロールバック
end
end
パストラバーサル、シンボリックリンク先、同時更新、許可されない downgrade を遮断します。manifest は ECDSA(P-256/SHA-256)署名で保護されており、install.sh/scripts/lib/update.sh に埋め込まれた公開鍵で scripts/update-manifest.txt.sig を検証します — 署名が無い、または不正な場合はチェックサムが全て一致していてもインストール・更新を拒否します。署名用の秘密鍵はこのリポジトリにはなく、リリース担当者のローカルマシンにのみ保管します(CI secret にはしません — アカウント/リポジトリ侵害時に一緒に漏洩し、防御目的が無意味になるため)。
.gitignore は実 .env、Apple/Android 署名資料、サービス設定、キャッシュ、生成パッケージを除外します。example ファイルにはプレースホルダーだけを保存してください。
flowchart LR
D["開発端末"] --> E["placeholder example"]
D --> S["秘密・署名資料"]
D --> O["生成成果物"]
E -->|"追跡"| G["Git / PR"]
S -->|"ignore"| L["ローカル / secret store"]
O -->|"ignore"| L
G --> C["CI privacy 検査"]
Ignore は既に追跡されたファイルやコミット作成者情報を消去しません。漏えいした資格情報は履歴操作より先に無効化・再発行してください。
同梱の skills/universal-build は次の安全な順序を使用します。
detect --json → audit --json → plan --json → 明示承認 → build --report-json
python3 /ABSOLUTE/PATH/scripts/ubs_mcp.py で外部 package 不要の stdio server を起動し、UBS_MCP_ROOT で許可 workspace を固定できます。既定 tool は ubs_detect、ubs_audit、ubs_plan、ubs_graph、ubs_update_check のみです。ubs_build は UBS_MCP_ALLOW_BUILD=true の場合だけ公開され、実 build は confirm=true も必要です。
./build.sh graph --json は Node package、Flutter path:、Gradle includeBuild(...) と ubs.dependencies.json から nodes・edges・topological layers を返します。循環と workspace 外 path は拒否します。
{"schema_version":1,"dependencies":{"apps/web":["packages/ui"]}}Xcode-only root は ios-xcode として検出し、macOS で Release archive を作成します。複数 scheme は UBS_XCODE_SCHEME、IPA export は UBS_XCODE_EXPORT=true と UBS_XCODE_EXPORT_OPTIONS を指定します。
bash -n build.sh install.sh scripts/*.sh scripts/lib/*.sh tests/*.sh
python3 tests/test_python_core.py
python3 tests/test_mcp.py
bash tests/test-detection.sh
bash tests/test-install.sh
bash tests/test-python-adapters.sh
bash tests/test-update.sh
bash tests/test-rust-helper.shテストは一時 fixture とモック CLI を使います。実 SDK、署名、成果物レベルの逆解析確認は各プロジェクトで別途必要です。
- 既定は逐次実行です。
--jobs Nは各 topological layer 内の非競合 project だけを並列化します。 - 自動依存推論外の生成 code・custom task 関係は
ubs.dependencies.jsonが必要です。 - 複数 Xcode scheme が曖昧な場合は
UBS_XCODE_SCHEMEが必要です。 - Gradle flavor、カスタム task、KMP 配布 task は override が必要な場合があります。
- Tauri JS 難読化は frontend の
dist/を前提にします。 - 成果物レポートは既知の標準出力パスを検索します。
- 自動 folder open も同じ検出規則を使うため、custom 出力先は手動で開く場合があります。
- 更新 manifest は外部 hash pin を提供しますが、独立署名・透明性ログはありません。
MIT License — Copyright © 2026 kimdzhekhon