#!/usr/bin/env node const fs = require("fs"); const path = require("path"); /** * 스토어 메타데이터 자동 업데이트 스크립트 * CHANGELOG.md 기반으로 Google Play Store 및 TestFlight 릴리즈 노트 생성 */ // 설정 const config = { changelogPath: "CHANGELOG.md", androidMetadataDir: "android/metadata/ko-KR/changelogs", // 제한사항 googlePlayLimit: 500, // Google Play Store 릴리즈 노트 최대 길이 testFlightLimit: 4000, // TestFlight 릴리즈 노트 최대 길이 }; /** * 메인 함수 */ async function updateStoreMetadata() { console.log("📝 스토어 메타데이터 업데이트 시작..."); // CHANGELOG.md에서 최신 버전 정보 추출 const changelogContent = readChangelog(); const latestVersion = extractLatestVersion(changelogContent); if (!latestVersion) { console.warn( "⚠️ CHANGELOG.md에서 버전 정보를 찾을 수 없습니다. 기본 메시지를 사용합니다." ); await createDefaultMetadata(); return; } console.log(`📋 최신 버전 추출: ${latestVersion.version}`); // Google Play Store 메타데이터 생성 await createGooglePlayMetadata(latestVersion); // TestFlight 메타데이터는 GitHub Actions에서 직접 처리 console.log( "✅ iOS TestFlight 메타데이터는 CI 파이프라인에서 자동 생성됩니다." ); console.log("✅ 스토어 메타데이터 업데이트 완료"); } /** * CHANGELOG.md 읽기 */ function readChangelog() { if (!fs.existsSync(config.changelogPath)) { console.warn( `⚠️ CHANGELOG.md 파일을 찾을 수 없습니다: ${config.changelogPath}` ); return ""; } return fs.readFileSync(config.changelogPath, "utf8"); } /** * 최신 버전 정보 추출 */ function extractLatestVersion(content) { if (!content) return null; // ## [1.0.0] - 2024-01-01 또는 ## 1.0.0 형식 매칭 const versionRegex = /^## \[?([^\]]+)\]?.*?\n(.*?)(?=\n## |$)/ms; const match = content.match(versionRegex); if (!match) return null; const version = match[1]; let changes = match[2].trim(); // 마크다운 형식 정리 changes = changes .replace(/### (.+)/g, "• $1") // ### 제목을 • 로 변환 .replace(/- (.+)/g, "• $1") // - 리스트를 • 로 변환 .replace(/\n\n+/g, "\n\n") // 연속된 빈 줄 정리 .trim(); return { version, changes }; } /** * Google Play Store 메타데이터 생성 */ async function createGooglePlayMetadata(versionInfo) { console.log("🟢 Google Play Store 메타데이터 생성..."); // 디렉토리 생성 const metadataDir = config.androidMetadataDir; if (!fs.existsSync(metadataDir)) { fs.mkdirSync(metadataDir, { recursive: true }); } // 릴리즈 노트 생성 (Google Play 500자 제한) let releaseNotes = `Zellyy Finance v${versionInfo.version}\n\n${versionInfo.changes}`; // 길이 제한 처리 if (releaseNotes.length > config.googlePlayLimit) { releaseNotes = releaseNotes.substring(0, config.googlePlayLimit - 3) + "..."; } // 파일 저장 const changelogFile = path.join(metadataDir, "default.txt"); fs.writeFileSync(changelogFile, releaseNotes); console.log( `✅ Google Play 릴리즈 노트 저장: ${changelogFile} (${releaseNotes.length}자)` ); // 버전별 체인지로그도 생성 (선택사항) const versionFile = path.join(metadataDir, `${versionInfo.version}.txt`); fs.writeFileSync(versionFile, releaseNotes); console.log(`✅ 버전별 체인지로그 저장: ${versionFile}`); } /** * 기본 메타데이터 생성 */ async function createDefaultMetadata() { console.log("📝 기본 메타데이터 생성..."); const defaultMessage = `Zellyy Finance 새 버전이 출시되었습니다. ✨ 새로운 기능 • 향상된 사용자 인터페이스 • 성능 최적화 및 안정성 개선 🔧 개선사항 • 빠른 로딩 시간 • 더 나은 사용자 경험 자세한 내용은 앱 내에서 확인하세요!`; // Google Play Store const metadataDir = config.androidMetadataDir; if (!fs.existsSync(metadataDir)) { fs.mkdirSync(metadataDir, { recursive: true }); } fs.writeFileSync(path.join(metadataDir, "default.txt"), defaultMessage); console.log("✅ Google Play 기본 메타데이터 생성 완료"); } /** * TestFlight 릴리즈 노트 생성 (미리보기) */ function generateTestFlightNotes(versionInfo) { let notes = `Zellyy Finance v${versionInfo.version} ${versionInfo.changes} 문의사항이 있으시면 개발팀에 연락주세요. 이메일: support@zellyy.finance`; // 길이 제한 처리 if (notes.length > config.testFlightLimit) { notes = notes.substring(0, config.testFlightLimit - 3) + "..."; } return notes; } /** * 사용 예시 출력 */ function printUsage() { console.log(` 📝 Store Metadata Updater Usage: # 기본 실행 (CHANGELOG.md 기반) node scripts/update-store-metadata.cjs 파일 구조: - CHANGELOG.md # 소스 파일 - android/metadata/ko-KR/changelogs/default.txt # Google Play 릴리즈 노트 - android/metadata/ko-KR/changelogs/[버전].txt # 버전별 체인지로그 CHANGELOG.md 형식: ## [1.0.0] - 2024-01-01 ### 새로운 기능 - 기능 1 - 기능 2 ### 버그 수정 - 수정 1 - 수정 2 제한사항: - Google Play Store: 최대 ${config.googlePlayLimit}자 - TestFlight: 최대 ${config.testFlightLimit}자 `); } // 메인 실행 if (require.main === module) { const args = process.argv.slice(2); if (args.includes("--help") || args.includes("-h")) { printUsage(); process.exit(0); } updateStoreMetadata().catch((error) => { console.error("메타데이터 업데이트 실패:", error); process.exit(1); }); } module.exports = { updateStoreMetadata, extractLatestVersion };