50-editor-window
暂无简介
- License 许可
- MIT
- 最近更新
- 2026-04-12
- Stars
- ★ 0
- Forks
- 0
03 SKILL.md 正文
50-editor-window — Build Operation GUI
Status: ACTIVE AppliesTo: v11
Unity EditorWindow로 구현하는 빌드 및 릴리스 운영 GUI. 설정 편집, 빌드 실행, 릴리스(버전 게시 + 심볼 업로드), 실시간 로그를 하나의 창에서 제공한다.
Window 구조
EditorWindow는 4개 탭으로 구성한다:
┌──────────────────────────────────────────────────┐
│ [Settings] [Pipeline] [Release] [Log] ● Running │
├──────────────────────────────────────────────────┤
│ │
│ (탭별 내용, ScrollView) │
│ │
└──────────────────────────────────────────────────┘
메뉴 접근: Devian > Build Automation
Tab 1: Settings
BuildAutomationSettings ScriptableObject를 인라인 편집한다.
각 섹션은 EditorStyles.helpBox VerticalScope GroupBox로 시각적으로 묶는다.
┌─ Settings ───────────────────────────────────────┐
│ │
│ ┌─ General ─────────────────────────────────┐ │
│ │ Build Output Dir [Builds ] [...] │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ┌─ Android ─────────────────────────────────┐ │
│ │ ☐ Include ARMv7 │ │
│ │ Keystore Path [ ] [...] │ │
│ │ Firebase App ID [1:xxx:android:xx] │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ┌─ iOS ─────────────────────────────────────┐ │
│ │ Firebase App ID [1:xxx:ios:xxxxx] │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ┌─ Release ────────────────────────────────┐ │
│ │ Remote CDN URL [https://d3...net] │ │
│ │ Release Repo Root [ ] [...] │ │
│ │ AOS Version JSON [release/v_aos ] [...] │ │
│ │ iOS Version JSON [release/v_ios ] [...] │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ┌─ Addressables ──────────────────────────────┐ │
│ │ Exclude Groups [▼ Select Group ] [+] │ │
│ │ ● Built In Data │ │
│ │ ● LocalStaticAssets │ │
│ │ [Clear All] │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─ CLI Paths ───────────────────────────────┐ │
│ │ 비워두면 자동 탐색. 'which firebase'로 확인 │ │
│ │ Firebase CLI [ ] [...] │ │
│ └───────────────────────────────────────────┘ │
│ │
│ ── Prerequisites ── │
│ ✅ Firebase SDK │
│ ✅ Firebase Android App ID │
│ ✅ Firebase iOS App ID │
│ ✅ google-services.json │
│ ✅ GoogleService-Info.plist │
│ ✅ Firebase CLI → /usr/local/bin/firebase │
│ ✅ Build Output Dir │
│ ✅ Android Module │
│ ✅ iOS Module │
│ ✅ Addressables │
│ [Refresh] │
│ │
└──────────────────────────────────────────────────┘
Prerequisites 상태는 OnEditorUpdate에서 10초 간격으로 갱신한다 (OnGUI 내부 금지).
플랫폼 모듈 미설치 시 해당 항목은 — (모듈 미설치)로 표시 (DrawStatusRow(string, bool?) null 오버로드).
Tab 2: Pipeline
2개 섹션으로 구성: Version Info / Build.
Settings/Pipeline/Release 탭은 공용 _mainScroll ScrollView로 감싼다.
Version Info SSOT: PlayerSettings.bundleVersion (Application prefab의 serialized field가 아님).
LoadVersion()이 PlayerSettings.bundleVersion을 VersionNumber.TryParse()로 파싱하여 편집 필드에 채운다.
ApplyVersion()은 PlayerSettings.bundleVersion에 직접 기록한다.
┌─ Pipeline ───────────────────────────────────────┐
│ │
│ ── Version Info ── │
│ App Version [1].[0].[0] │
│ Android Code [1 ] │
│ iOS Build [1.0.0 ] │
│ [Apply] [Revert] Current: 1.0.0 │
│ ───────────────────────────────────────────── │
│ │
│ ── Build ── │
│ ☑ Android ☑ iOS (readiness 기반 editable) │
│ ☑ Build App Bundle (AAB) │
│ ☑ Build Addressable Bundles │
│ ☐ Development Build (Debug Mode) │
│ [▶ Build] │
│ │
│ ── (실행 중일 때만) ── │
│ ████████████░░░░░░ 75% Building... │
│ [■ Cancel] │
│ │
└──────────────────────────────────────────────────┘
플랫폼 Readiness
플랫폼 토글은 3단계 개념으로 분리한다:
| 개념 | 변수 | 판정 기준 | 용도 |
|---|---|---|---|
| Module Supported | _androidSupported / _iosSupported |
BuildPipeline.IsBuildTargetSupported() |
Version 섹션 DisabledScope, Prerequisites 표시 |
| Build Ready | _androidReady / _iosReady |
supported AND firebaseAppIdSet |
토글 editable 여부 결정 |
| Build Selected | _buildAndroid / _buildIos |
사용자가 체크 (ready일 때만 editable) | 실제 빌드 실행 대상 |
- Ready가 아닌 플랫폼: 토글
false+DisabledScope(읽기 전용) - Ready인 플랫폼: 토글 editable, 초기값
true RefreshPrerequisites()에서 readiness 재계산. not ready로 바뀌면_buildAndroid = false강제.
실행 로직
Build App Bundle (AAB) 체크박스: EditorUserBuildSettings.buildAppBundle을 토글한다. 스냅샷 _guiAppBundle 사용. _guiBuildAndroid가 false이면 비활성화. 실행 중에는 비활성화.
Development Build 체크박스: settings.developmentBuild를 토글한다. 스냅샷 _guiDevBuild 사용. 실행 중에는 비활성화.
Build Addressable Bundles 체크박스: _buildAddressables 토글. 체크 시 앱 빌드 전에 BundleBuildRunner.Run() 호출. 실행 중에는 비활성화.
Build 버튼: EditorApplication.delayCall로 OnGUI 밖에서 RunBuild() 실행 (OnGUI 내 BuildPlayer 호출 시 GUI 레이아웃 에러 방지).
RunBuild() 실행 흐름:
- Phase 1 (메인 스레드, 동기):
_buildAddressables가 true이면: a.BundleBuildRunner.Run(excludedGroups)— 번들 빌드 b. 성공 시BundleUploadRunner.Run(settings, ct)— 빌드 산출물을 release repo에 복사 + git commit c. Bundle Copy 실패 시 경고 로그만 출력하고 앱 빌드는 계속 진행 - Phase 2 (메인 스레드, 동기):
_buildAndroid/_buildIos가 true인 플랫폼만 앱 빌드 - 빌드 성공 시
AutoFillSymbolPaths()로 심볼 경로 자동 입력
Tab 3: Release
3개 섹션으로 구성: Version Publish / Bundle Upload / Symbol Upload.
┌─ Release ────────────────────────────────────────┐
│ │
│ ── Version Publish ── │
│ │
│ ── Android ── │
│ Last Published current: 1.2.3 min: 1.0.0 │
│ Current Version [1.2.3 ] │
│ Min Version [1.0.0 ] │
│ [▶ Publish] │
│ │
│ ── iOS ── │
│ Last Published current: 1.2.3 min: 1.0.0 │
│ Current Version [1.2.3 ] │
│ Min Version [1.0.0 ] │
│ [▶ Publish] │
│ ───────────────────────────────────────────── │
│ │
│ ── Bundle Upload ── │
│ Release Repo Root ../release-repo │
│ Remote Groups: 3개 감지 │
│ [⬆ Upload Bundles to Git] │
│ ───────────────────────────────────────────── │
│ │
│ ── Symbol Upload ── │
│ Android Symbols [/abs/path/symbols.zip] [...] │
│ iOS dSYMs [/abs/path/dSYMs ] [...] │
│ [⬆ Upload Symbols] │
│ │
│ ── (실행 중일 때만) ── │
│ ████████████░░░░░░ 75% Uploading... │
│ [■ Cancel] │
│ │
└──────────────────────────────────────────────────┘
Version Publish 실행 로직
Version JSON 경로: Settings 탭의 BuildAutomationSettings에 저장. Release 탭에서는 읽기 전용 표시.
플랫폼별 독립 Publish:
- Last Published: JSON에서 읽은 현재 저장값 (readonly).
RefreshLastVersions()로 갱신. - Current Version / Min Version: 편집 가능 TextField (
_editVersionAOS/_editVersionIOS) - Publish 버튼: 항상 활성화 (실행 중이거나 JSON 경로 미설정 시만 비활성). 플랫폼 readiness와 무관.
- 각 플랫폼 Publish 버튼 →
RunVersionPublish(platform):- editInfo vs lastInfo 비교하여 변경 여부 판정
UpdateVersionJson(path, VersionCheckConfig)— currentVersion, minVersion 업데이트- 변경 없으면 → commit 스킵, 로그만 출력
- 변경 있으면 →
GitRunner.Commit()— git add → commit (push 하지 않음) - commit message: title + body (변경 전후 currentVersion, minVersion 기록)
Bundle Upload 실행 로직
Remote Groups 표시: AddressableAssetSettingsDefaultObject.Settings.groups에서 Remote group 수를 감지하여 읽기 전용 표시.
Upload Bundles to Git 버튼 (RunBundleUpload()):
BundleUploadRunner.Run(settings, ct)호출- Remote group의 빌드 산출물을
releaseRepoRoot/v{bundleVersion}/{BuildTarget}/에 복사 GitRunner.Commit()으로 git add → commit (push 하지 않음)
Symbol Upload 실행 로직
Upload Symbols 버튼 (RunSymbolUploadOnly()):
- 심볼 경로 필드가 비어있으면 에러 로그
- 경로가 지정되어 있으면
SymbolUploader.UploadAndroid/UploadIOS에 절대 경로 전달
심볼 경로 관리
_androidSymbolPath/_iosSymbolPath: EditorWindow 런타임 상태- 빌드 성공 후
AutoFillSymbolPaths()가buildOutputDir에서 자동 탐색 [...]버튼으로 파일/폴더 수동 선택 가능 (Android: 파일, iOS: 폴더)
Tab 4: Log
실시간 빌드/릴리스 로그 표시. 자체 ScrollView 사용 (메인 ScrollView와 별도).
┌─ Log ────────────────────────────────────────────┐
│ [Clear] [Copy All] Filter: [__________] │
│ ☑ Auto-scroll │
│ │
│ [15:30:01] [INFO] === Build started === │
│ [15:30:02] [INFO] Android Build... │
│ [15:30:45] [INFO] Build succeeded. 45.2 MB │
│ [15:30:46] [INFO] symbol path auto-filled: ... │
│ [15:31:00] [INFO] === Publish Version === │
│ [15:31:02] [INFO] git commit done │
│ │
└──────────────────────────────────────────────────┘
IMGUI 스냅샷 패턴
IMGUI는 Layout → Repaint 두 패스를 실행한다.
async continuation이 두 패스 사이에 상태를 변경하면 컨트롤 수 불일치로 EndLayoutGroup 에러가 발생한다.
해결: Layout 패스에서 컨트롤 수에 영향을 주는 모든 상태를 스냅샷으로 캡처하고, OnGUI 전체에서 스냅샷만 사용한다.
// Layout 패스에서 캡처
if (Event.current.type == EventType.Layout)
{
_guiIsRunning = _isRunning;
_guiPhaseLabel = _currentPhaseLabel;
_guiProgress = _progress;
_guiTab = _currentTab;
_guiPrereqStatus = _prereqStatus;
_guiVersionDirty = _versionDirty;
_guiDevBuild = _settings != null && _settings.developmentBuild;
_guiAppBundle = EditorUserBuildSettings.buildAppBundle;
_guiAndroidReady = _androidReady;
_guiIosReady = _iosReady;
_guiBuildAndroid = _buildAndroid;
_guiBuildIos = _buildIos;
_guiBuildAddressables = _buildAddressables;
_guiRemoteGroupCount = _remoteGroupCount;
_guiLastVersionAOS = _lastVersionAOS;
_guiLastVersionIOS = _lastVersionIOS;
_guiEditVersionAOS = _editVersionAOS;
_guiEditVersionIOS = _editVersionIOS;
}
조건부 컨트롤은 항상 동일한 수를 그린다 (else 분기에서 빈 컨트롤 사용).
BuildAutomationLogger
스레드 안전한 중앙 로그 시스템.
- 타입:
BuildLogLevel(Info/Warning/Error),BuildLogEntry - 메인 스레드:
_entries에 직접 추가 - 백그라운드 스레드:
_pendingEntries큐에 추가 →FlushPendingEvents()에서 메인 스레드로 이동 - EditorWindow는
EditorApplication.update에서FlushPendingEvents()호출 후, 로그 수 변경 시Repaint() - 로그 스냅샷: Layout 패스에서
_logSnapshot배열로 복사하여 Repaint 중 안정성 보장
파일 목록
Samples~/MobilePackage/Editor/BuildAutomation/
├── BuildAutomationSettings.cs # ScriptableObject (10-settings)
├── BuildAutomationSettingsEditor.cs # Custom Editor (helpBox GroupBox, 경로 브라우저)
├── BuildAutomationUtil.cs # 공통 유틸 (Settings 로드, CLI 해석, Prerequisites)
├── BuildAutomationLogger.cs # 로그 시스템 (스레드 안전)
├── BuildAutomationWindow.cs # EditorWindow 본체 (4탭)
├── AndroidBuildRunner.cs # Build - Android
├── IOSBuildRunner.cs # Build - iOS
├── BuildReportAnalyzer.cs # Build - 리포트 분석
├── BundleBuildRunner.cs # Pipeline - Addressable 번들 빌드
├── BundleUploadRunner.cs # Release - 번들 git 업로드
├── GitRunner.cs # Release - git CLI wrapper
└── SymbolUploader.cs # Release - Symbol Upload
Related
- 00-overview — 그룹 개요
- 10-settings — BuildAutomationSettings 정의
- 20-build — Build 로직
- 30-symbol-upload — Symbol Upload
- 21-bundle-build — Bundle Build
- 22-bundle-upload — Bundle Upload
- 40-version-publish — Version Publish