d3ro-voice/docs/deployment/release-guide.md
2026-08-29 19:19:19 +09:00

9.3 KiB

D3RO Voice 릴리스 가이드

기준일: 2026-08-29. 이 문서는 desktop GitLab 패키지·자동 업데이트와 mobile store release의 경계를 분리한다. 태그 생성이나 HTTP 200 하나만으로 배포 완료를 선언하지 않는다.

현재 release identity

항목 정본 현재 판정
제품 버전 release/product-version.json: 1.1.0 source SSOT 확정
Android versionCode 1010001 production AAB 미생성
iOS build 1010001 production archive 미검증
Android upload key alias d3ro-upload-20260821, cert SHA-256 4F:AC:69:24:...:15:2B:54 external PKCS12·user-only ACL·Credential Manager·private-key readback GREEN; CI secret·복구 백업·AAB signer 대조 대기
release evidence Ed25519 public release/mobile-release-evidence-public.pem, keyId 2797d3e6...4a890b7f external private key ACL·roundtrip GREEN; CI private-key secret·복구 백업 대기
desktop offline license Ed25519 public apps/desktop/resources/license/production-public.pem, keyId 5c52b765...81a887f 새 전용 keypair·external private ACL·roundtrip·desktop production build GREEN; admin ADMIN_LICENSE_PRIVATE_KEY secret 주입 대기
Windows Authenticode external public-trust code-signing certificate 현재 local 1.1.0 installer·unpacked app은 NotSigned; production PFX·CI secret·signed artifact GREEN 전까지 게시 금지
Firebase Console u/0, u/1 모두 D3RO project 없음 사용자 승인 후 project·Android app 생성 필요
AdMob app ca-app-pub-1039714767792854~6427959892; banner /9840591290; rewarded /2255790918 SSOT 확정. 검토 필요·광고 게재 제한·store 미연결·결제 프로필 미완료
updater feed https://gitlab.twentyoz.kr:8443/api/v4/projects/1172/packages/generic/d3ro-voice/latest public latest.yml은 아직 0.2.1-alpha; 1.1.0 미배포
release notes CHANGELOG.md ## [1.1.0] 태그 전 확정·검증 필수

source SSOT와 live updater metadata의 버전이 다르므로 아직 1.1.0 배포 완료가 아니다.

GitLab desktop 파이프라인

authoritative release commit
  → version/check/test/build GREEN
  → tag v1.1.0
  → package-windows  (build-win-x64)
  → package-macos    (build-mac-arm64)
  → publish-release  (build-linux-x64)
       ├─ packages/generic/d3ro-voice/1.1.0/  버전별 보존
       ├─ packages/generic/d3ro-voice/latest/ latest updater feed
       └─ GitLab Release + CHANGELOG release notes
  • scripts/ci/sync-version.mjs --check --tag v1.1.0는 태그, release/product-version.json, package/lockfile, Android/iOS 버전 면의 일치를 fail-closed로 검증한다.
  • scripts/ci/verify-release-metadata.mjs는 배포 메타데이터와 CI/publisher 계약을 검증한다.
  • 같은 gate는 desktop license public key가 Ed25519이고 release/product-version.jsondesktopLicensePublicKeyId와 일치하는지 검증한다. electron.vite.config.ts는 이 파일을 직접 읽으므로 누락·손상된 키로는 build가 시작되지 않는다.
  • scripts/ci/publish-gitlab-release.mjs는 버전별 패키지를 먼저 올리고, latest 파일에서 설치 자산 참조를 검증한 후 update metadata를 마지막에 게시한다.
  • Windows installer와 latest.yml은 필수다. macOS 산출물이 없는 Windows-only release를 의도했다면 그 판단을 release record에 남긴다.
  • package-windows는 external public-trust code-signing PFX를 protected file variable WIN_CSC_PFX_FILE로, 암호와 exact certificate subject를 protected WIN_CSC_KEY_PASSWORD, WIN_CSC_EXPECTED_SIGNER_SUBJECT로 받아야 한다. GitHub Release도 WIN_CSC_LINK, WIN_CSC_KEY_PASSWORD, WIN_CSC_EXPECTED_SIGNER_SUBJECT가 모두 없으면 실패한다.
  • scripts/ci/verify-windows-release-artifact.ps1는 installer와 unpacked app의 Authenticode Valid, exact signer subject, non-self-signed code-signing EKU, PE version, latest.yml path/size/SHA-512를 검증한다. 로컬 self-signed Everything2EverythingDev는 production 신뢰 인증서가 아니며 gate에서 명시적으로 거부한다.
  • 현재 GitLab Linux runner는 Shell executor이므로 job의 image:를 툴체인 근거로 간주하지 않는다. .gitlab-ci.ymlscripts/ci/bootstrap-linux-toolchain.sh를 source해 .NET 10.0.302, Deno 2.8.1, Microsoft OpenJDK 17.0.20.1, Android command-line tools 15859902를 고정 해시로 검증·캐시한 뒤 실행한다.

자동 업데이트 계약

apps/desktop/src/main/update-feed.tsapps/desktop/electron-builder.yml은 버전 없는 같은 public Generic Package Registry URL을 가리켜야 한다.

https://gitlab.twentyoz.kr:8443/api/v4/projects/1172/packages/generic/d3ro-voice/latest

아래 면이 하나라도 깨지면 release를 중단한다.

  1. package registry의 무인증 public pull이 허용됐다.
  2. latest.ymlversion이 태그와 일치한다.
  3. latest.yml URL/path가 같은 latest 경로의 실제 installer를 참조한다.
  4. installer 파일명에 공백이 없다: D3RO-Voice-Setup-<version>-x64.exe.
  5. metadata SHA-512와 다운로드한 installer가 일치한다.
  6. installer와 win-unpacked/D3RO Voice.exe 모두 external public-trust certificate의 Authenticode Valid이고, signer subject가 protected CI identity와 정확히 일치한다.
  7. 이전 실제 설치본이 feed를 탐지하고, 다운로드·재시작·버전 상승을 끝까지 완료한다.

2026-08-29 live latest.yml의 버전은 0.2.1-alpha다. 이는 updater endpoint가 응답한다는 증거일 뿐 1.1.0 게시 증거가 아니다.

1.1.0 릴리스 절차

  1. release/product-version.json의 version/build 값과 모든 버전 면을 npm run version:check로 대조한다.
  2. CHANGELOG.md ## [1.1.0] - 2026-08-29 섹션을 사용자 변경점 중심으로 확정한다. publisher는 이 섹션이 없으면 실패해야 한다.
  3. dirty/untracked 작업을 임의로 reset·clean하지 말고, release 범위만 검토 가능한 authoritative commit으로 보존한다.
  4. 같은 commit에서 lint, typecheck, test, build, release metadata·security·artifact gate를 전부 GREEN으로 만든다. Windows는 production Authenticode PFX를 주입한 CI build와 verify-windows-release-artifact.ps1 GREEN이 필수다.
  5. desktop offline license를 제공한다면 external private key를 admin의 ADMIN_LICENSE_PRIVATE_KEY secret로 주입하고, 저장소 public key와 sign/verify roundtrip 및 발급 감사 로그를 확인한다.
  6. 이전 버전보다 높은 태그 v1.1.0을 생성해 push한다. 태그는 게이트를 시작하는 후속 단계지 검증을 대체하지 않는다.
  7. GitLab에서 package-windows, package-macos, publish-release와 의도한 mobile job 상태를 모두 확인한다. pending/stuck/skipped를 GREEN으로 기록하지 않는다.
  8. 버전별 package, GitLab Release note/asset, latest.yml, installer hash를 외부 public URL에서 다시 검증한다.
  9. 이전 설치본에서 자동 업데이트 E2E를 실행하고 실행 중 버전·프로세스·사용자 데이터 보존을 확인한다.

mobile release와의 경계

Desktop GitLab Release를 게시해도 Android production 출시가 자동으로 완료되지 않는다. Android는 다음을 별도로 증명한다.

  • 준비된 local upload/evidence key와 AdMob identity를 protected CI secret에 주입하고, 사용자 승인 후 생성한 production Firebase config와 함께 version 1.1.0, versionCode 1010001 AAB 생성
  • package/config/upload signer/ABI/16 KB page size/signed provenance GREEN
  • public APK 게시 없이 Play internal track에 제한 업로드
  • Play-signed 실기기 E2E, 12명·연속 14일 closed test, production access 승인
  • Data safety/App content/production 선언은 사용자의 action-time 검토·승인 후에만 제출

현재 local upload/evidence key는 존재하지만 CI secret 주입·복구 백업·production Firebase·AAB가 없고 Play production access도 disabled이므로 Android production 출시는 RED다.

rollback

  • Desktop: 게시 전이면 latest metadata를 바꾸지 않는다. 이미 업데이트된 클라이언트는 downgrade하지 말고 더 높은 patch 버전으로 forward-fix한다.
  • Play: staged rollout을 중단하고 더 높은 versionCode의 수정 AAB를 새로 검증·배포한다.
  • 복구 작업도 release record에 artifact hash, 시각, 판단자, 영향 범위를 남긴다.

참고 파일

  • release/product-version.json — 제품 version/build SSOT
  • release/android-release-identity.json — Play app/package/certificate identity
  • release/mobile-release-evidence-public.pem — release evidence public key
  • apps/desktop/resources/license/production-public.pem — desktop offline license public key SSOT
  • scripts/ci/sync-version.mjs — 버전 면 동기화·검증
  • scripts/ci/verify-release-metadata.mjs — release metadata 자가 검증
  • scripts/ci/verify-windows-release-artifact.ps1 — Windows version·updater metadata·Authenticode gate
  • scripts/ci/publish-gitlab-release.mjs — registry·Release·updater feed publisher
  • apps/desktop/src/main/update-feed.ts — runtime updater URL SSOT
  • apps/desktop/electron-builder.yml — builder publish URL·artifact contract
  • docs/v3/play/04-release-checklist.md — Play Console·AAB·closed test·production gate