// src/main/update-feed.ts // 자동 업데이트 feed URL SSOT. // // canonical feed는 Forgejo Generic Package Registry의 `d3ro-voice/latest`다. // `publish-forgejo-release.mjs`가 latest.yml + 설치파일 + update-policy.json을 // 게시하면 electron-updater가 이 URL에서 latest.yml을 읽어 업데이트를 감지한다. // // 전제: Forgejo에서 해당 owner/package의 무인증 pull이 허용돼야 한다 // (비활성 시 무인증 다운로드가 401 — 앱은 조용히 업데이트 체크를 건너뜀). // // 빈 문자열이면 UpdateService가 비활성 상태로 동작한다. // 버전 없는 `latest` 패키지를 가리켜야 기존 설치본이 새 릴리스를 계속 찾을 수 있다. export const UPDATE_FEED_URL = 'https://git.chanpaca.net/api/packages/yunchan/generic/d3ro-voice/latest' // GitLab Generic Registry legacy mirror. 2026-08 이전 설치본(0.2.1-alpha)은 // 이 feed를 폴링하므로, 새 설치자가 Forgejo feed를 내장할 때까지 publisher가 // 함께 게시한다. 마이그레이션 완료 후 제거 가능. 런타임은 참조하지 않는다. /** * 로컬 AI 런타임(사이드카 엔진 / ffmpeg) 배포 위치. * 진을 설치본에 넣으면 installer가 Cloudflare 업로드 한도(100MiB)를 넘어 업데이트 * 메타데이터(latest.yml)를 게시할 수 없다. 그래서 런타임은 별도 경로에서 필요할 때 받는다. * 자동 업데이트 채널과 분리된 경로이며 서명이 필요 없다. */ export const RUNTIME_FEED_URL = UPDATE_FEED_URL.replace(/\/latest$/, '/runtime-latest') /** 런타임 인덱스 파일명 (feed 루트) */ export const RUNTIME_INDEX_FILENAME = 'runtime.json' export const LEGACY_UPDATE_FEED_URL = 'https://gitlab.twentyoz.kr:8443/api/v4/projects/1172/packages/generic/d3ro-voice/latest' /** 업데이트 채널. `latest`=stable, `beta`, `alpha` 순으로 불안정. */ export type UpdateChannel = 'latest' | 'beta' | 'alpha' export const UPDATE_CHANNELS: readonly UpdateChannel[] = ['latest', 'beta', 'alpha'] /** 채널별 electron-builder update metadata 파일명. */ export function channelMetadataName(channel: UpdateChannel): string { return channel === 'latest' ? 'latest.yml' : `${channel}.yml` } /** 원격 업데이트 정책 파일명. feed 루트에서 내려받는다. */ export const UPDATE_POLICY_FILENAME = 'update-policy.json' /** 원격 업데이트 정책 URL (없으면 앱 내장 기본 정책으로 폴백). */ export const UPDATE_POLICY_URL = UPDATE_FEED_URL ? `${UPDATE_FEED_URL}/${UPDATE_POLICY_FILENAME}` : '' export function isUpdateChannel(value: unknown): value is UpdateChannel { return typeof value === 'string' && (UPDATE_CHANNELS as readonly string[]).includes(value) }