- EXE project kind next to MSIX: formats.exe, new EXE projects, EXE app info (architecture, UpgradeCode), per-kind workspace; EXE builds and signing are still refused explicitly (#9). - Install configuration tabs: registry grid, shortcuts and installer properties with formatted-text checks (#10). - Per-version .isver files: version list, add dialog, lock/unlock, delete with .isver.bak backups, description (#11). - Major/patch versions with cumulative patch checks and automatic kind selection (#12). - 설치화면 tab: setup steps, theme and scripts per version (#13). - Preferences: theme and display language (#14). - 설치파일 tab as an Explorer-style tree: per-row add/remove, Windows folder install locations (FileRule.targetRoot), picked files placed with FileRule.sourceFolder, unsaved-rule file preview (#17). Checks: cargo fmt/clippy/test, 82 frontend tests, Vite build and the msix-studio build pass. npm ci, GUI click tests and real EXE builds were not run. Refs #9 #10 #11 #12 #13 #14 #17 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7.7 KiB
7.7 KiB
EXE 버전과 누적 패치
결정일: 2026-11-09. EXE 프로젝트의 버전을 메이저 버전과 패치 버전으로 나누고, 패치 버전마다 전체 설치 파일과 누적 패치 파일을 함께 만든다. 이 문서는 설계다. 버전 종류·ProductCode 상속·패치 제약 검사는 모델과 화면에 구현했지만 MSI·MSP 생성, Burn 번들, 실제 설치·패치 시험은 EXE 빌드와 함께 후속으로 구현한다.
버전 메타파일의 위치와 형식은 프로젝트 모델, 설치 화면과 Burn 구조는 14 EXE 설치 UI를 따른다.
결정
| 항목 | 결정 |
|---|---|
| 버전 종류 | 버전마다 updateType을 둔다. major는 새 ProductCode를 받고 이전 제품을 제거한 뒤 설치한다(메이저 업그레이드). patch는 아래쪽 메이저 버전의 ProductCode를 그대로 쓴다(마이너 업그레이드). 기존 버전 파일에 값이 없으면 major다. |
| 라인 | 메이저 버전과, 그보다 높고 다음 메이저 버전보다 낮은 패치 버전들을 한 라인으로 본다. 예: 1.0.0(메이저, A)·1.0.1·1.0.2·1.0.3(패치, A) / 1.1.0(메이저, B)·1.1.1(패치, B). |
| 패치 기준 | 누적 패치. 1.0.3 패치 파일 하나가 같은 라인의 이전 버전 모두(1.0.0·1.0.1·1.0.2)를 1.0.3으로 올린다. 이전 패치를 대체(supersede)하므로 사용자는 최신 패치 하나만 설치한다. |
| 산출물 | 메이저 버전: 전체 설치 파일 setup.exe. 패치 버전: 전체 설치 파일 setup.exe(새 PC에서 바로 그 버전 설치)와 패치 파일(누적 MSP와 이를 감싼 패치 EXE) 두 개. |
| 설치 경로 | 같은 라인의 이전 버전이 설치된 PC는 패치 파일로만 업데이트한다. 전체 설치 파일은 그 경우 설치하지 않고 패치 파일을 안내한다. |
| 기준 보존 | 패치가 올릴 이전 버전은 잠가야 한다. 잠긴 버전의 빌드 결과(MSI, .wixpdb, 실제 파일)는 패치 생성의 기준으로 보존하며 지우지 않는다. |
설치 동작
setup.exe와 패치 EXE는 Burn이 설치된 제품(UpgradeCode·ProductCode·버전)을 탐지한 뒤 다음처럼 동작한다. 1.0.3이 패치 버전인 경우다.
| PC 상태 | 1.0.3 전체 설치 파일 | 1.0.3 패치 파일 |
|---|---|---|
| 설치 없음 | 1.0.3을 새로 설치 | 적용 대상 없음, 전체 설치 파일 안내 |
| 1.0.0·1.0.1·1.0.2 (같은 라인) | 설치하지 않고 패치 파일 안내 | 1.0.3으로 업데이트 |
| 1.0.3 | 유지·복구 화면 | 이미 적용됨 |
| 0.9.x (이전 라인, 다른 ProductCode) | 메이저 업그레이드: 0.9.x 제거 후 1.0.3 설치 | 적용 대상 없음, 전체 설치 파일 안내 |
| 1.1.0 이상 (더 높은 버전) | 낮은 버전 설치 거부 | 적용 대상 없음 |
1.0.3 전체 설치 파일로 새로 설치한 PC도 같은 라인이다. 이후의 1.0.4 누적 패치는 1.0.3도 기준에 포함하므로 그대로 적용된다. 따라서 패치 버전의 전체 설치 파일도 출시하면 잠그고 기준으로 보존한다.
누적 패치 생성
- 패치 MSP는 같은 라인의 이전 버전마다 하나씩 기준(WiX
PatchBaseline)을 두고, 각 기준의 빌드 결과에서 이번 버전으로 가는 변환을 한 파일에 담는다. - 같은 라인의 패치는 하나의 패치 계열(
PatchFamily)로 묶고 순서 값을 올려, 새 패치가 이전 패치를 대체한다. - 기준의 빌드 결과는 잠근 시점의 버전 파일 해시, 공유 설정 해시, 파일 목록·해시와 함께
releases/에 둔다. 패치 빌드는 이 해시를 다시 확인하고, 다르면BaselineChanged로 거부한다. 공유 설정(아키텍처·설치 폴더·설치 범위·UpgradeCode·속성)을 출시 후 바꾸면 그 라인의 패치를 만들 수 없다. - MSI 구성 요소 GUID는 설치 경로에서 결정되도록 만들어 같은 경로의 파일이 버전 사이에 같은 구성 요소로 유지되게 한다.
패치 제약
Windows Installer 패치는 이전 버전이 설치한 구성 요소를 지우거나 옮길 수 없다. 입력 검사(validate_version_line)는 버전 파일 수준에서 다음을 확인하며, 규칙은 그대로인데 소스 폴더에서 파일이 사라진 경우는 패치 빌드에서 기준 파일 목록과 비교해 거부한다.
| 코드 | 조건 |
|---|---|
MissingMajorVersion |
패치 버전보다 낮은 메이저 버전이 없다. |
PatchProductCodeMismatch |
패치의 ProductCode가 라인 메이저 버전과 다르다. |
BaselineNotLocked |
패치가 올릴 이전 버전 중 잠기지 않은 버전이 있다. |
PatchRemovesFiles |
이전 버전의 파일 규칙(ID 기준)을 지웠다. |
PatchMovesFiles |
같은 파일 규칙의 소스 또는 설치 위치를 바꿨다. |
PatchRemovesRegistry |
이전 버전의 레지스트리 값을 지웠거나 루트·뷰·키 경로·값 이름을 바꿨다. 형식·데이터 변경은 허용한다. |
PatchRemovesShortcut |
이전 버전의 바로가기를 지웠거나 위치·폴더·이름을 바꿨다. 대상·인수 변경은 허용한다. |
ProductCodeReused |
메이저 버전이 다른 메이저 버전의 ProductCode를 쓴다. |
파일·레지스트리·바로가기 추가, 포함·제외 패턴과 데이터 변경은 허용한다. 지우거나 옮겨야 하면 새 메이저 버전을 만든다.
제작기 화면
- 설치 구성 › 버전 목록에 종류 열(메이저 / 패치 · 라인 메이저 버전)을 둔다.
- 버전 목록 오른쪽 위 버전 추가 팝업에서 새 버전 번호, 종류(번호를 입력할 때마다 자동 선택: 아래쪽 메이저 버전과 Major·Minor가 같으면 패치, 아니면 메이저. 직접 바꿀 수 있지만 아래에 메이저 버전이 없는 최초 버전은 패치 선택지가 비활성화된다), 복사할 버전을 고르고 만들기로 추가한다. 패치는 라인 메이저 버전의 ProductCode를 받고, 낮은 메이저 버전이 없으면
MissingMajorVersion으로 추가하지 않는다. 첫 버전은 항상 메이저다. - 버전 › 일반 탭은 종류를 표시하고, 패치 버전의 ProductCode는 읽기 전용으로 보여 준다(새 GUID 버튼 없음).
- 입력 검사는 선택한 버전에 대해 위 패치 제약을 함께 검사하고 해당 탭으로 이동한다.
구현 범위
| 항목 | 상태 |
|---|---|
ExeVersion.updateType, line_major, patch_baselines, validate_version_line |
구현 |
| 버전 목록 종류 열, 종류 선택 추가, ProductCode 상속, 일반 탭 표시 | 구현 |
기준 빌드 결과 보존·해시 기록, BaselineChanged |
후속 (EXE 빌드) |
| MSI·누적 MSP·Burn 전체 설치/패치 EXE 생성, 설치 상태별 안내 | 후속 (EXE 빌드) |
| 같은 라인 PC에서 전체 설치 파일 거부, 패치 대체 순서 | 후속 (BA 구현) |
| Windows VM 설치·패치·제거 시험 | 미실행 |