// scripts/generate-version.js // // public/version.json üretir. Bu dosya uygulamanın tek sürüm kaynağıdır: // - `buildId` : HER deploy'da değişir (commit + build zamanı). Uygulama açık // sekmede ve açılışta yeni deploy'u bununla anlar; git tag // atılmamış olsa bile güncelleme algılanır. // - `version` : Kullanıcıya gösterilen sürüm (en güncel release). // - `releases` : Changelog kaynağı. Git tag'lerinden okunur; HEAD tag'li // değilse son tag'den bu yana atılan commit'ler "yayınlanmamış" // sürüm olarak en üste eklenir, böylece her deploy'un notu olur. import fs from 'fs' import path from 'path' import { fileURLToPath } from 'url' import { execSync } from 'child_process' function safeExec(cmd) { try { return execSync(cmd, { stdio: ['pipe', 'pipe', 'ignore'], shell: true }).toString().trim() } catch { return null } } const scriptDir = path.dirname(fileURLToPath(import.meta.url)) const uiRoot = path.resolve(scriptDir, '..') const outputFile = path.join(uiRoot, 'public', 'version.json') const pkg = JSON.parse(fs.readFileSync(path.join(uiRoot, 'package.json'), 'utf8')) const packageVersion = pkg.version || '0.0.0' const buildTime = new Date().toISOString() const buildDate = buildTime.slice(0, 10) const hasGit = !!safeExec('git rev-parse --is-inside-work-tree') /** * Docker imajı içinde `.git` yoktur; sürüm bilgisi host'ta (deploy script'i ile) * üretilip `public/version.json` olarak kopyalanır. Bu durumda dosyayı yeniden * üretmek gerçek changelog'u ve `buildId`'yi silip yerine "yerel derleme" * yazardı; bu yüzden mevcut dosya korunur. */ if (!hasGit && fs.existsSync(outputFile)) { const existing = JSON.parse(fs.readFileSync(outputFile, 'utf8')) const version = existing.version ?? existing.releases?.[0]?.version ?? packageVersion const buildId = existing.buildId ?? existing.commit ?? `${packageVersion}.${Date.now().toString(36)}` if (!existing.buildId || !existing.version) { existing.buildId = buildId existing.version = version fs.writeFileSync(outputFile, JSON.stringify(existing, null, 2)) } console.log(`> mevcut version.json korundu: v${version} (${buildId})`) process.exit(0) } const shortCommit = process.env.GIT_COMMIT || (hasGit ? safeExec('git rev-parse --short HEAD') : null) const commit = shortCommit || 'local' /** Tag mesajını changelog satırlarına çevirir. */ const toChangeLog = (raw) => (raw ?? '') .split('\n') .map((line) => line.replace(/^\s*[-*]\s*/, '').trim()) .filter(Boolean) let releases = [] if (hasGit) { // Sıralama tag adına göre (creatordate değil): sunucuda sonradan atılmış bir // tag listeyi başa geçirip yanlış sürüm göstermesin. const rawTags = safeExec('git tag --list --sort=-v:refname') const tags = rawTags ? rawTags.split('\n').filter(Boolean) : [] releases = tags .map((tag) => { const version = tag.replace(/^v/, '') const date = safeExec(`git log -1 --format=%ad --date=short ${tag}`) const commitId = safeExec(`git rev-list -n 1 ${tag}`) const changeLog = toChangeLog(safeExec(`git tag -l --format="%(contents)" ${tag}`)) return { version, buildDate: date || buildDate, commit: commitId, changeLog: changeLog.length ? changeLog : ['Bu sürüm için not girilmemiş'], } }) // Changelog yalnızca tag'lerden oluşur. Tag'siz commit'ler için sahte bir // sürüm üretilmez; sürüm notlarını tag mesajı belirler. Deploy algılaması // sürüm numarasına değil, her derlemede değişen `buildId`'ye bakar. } if (releases.length === 0) { releases = [ { version: packageVersion, buildDate, commit, changeLog: ['Yerel geliştirme derlemesi', 'Git bilgisi bulunamadı, package.json sürümü kullanıldı'], }, ] } const versionInfo = { // Her derlemede değişir; uygulamanın deploy algılaması buna bakar. buildId: `${commit}.${Date.now().toString(36)}`, buildTime, buildDate, commit, packageVersion, version: releases[0].version, releases, } fs.mkdirSync(path.dirname(outputFile), { recursive: true }) fs.writeFileSync(outputFile, JSON.stringify(versionInfo, null, 2)) console.log(`> version.json: v${versionInfo.version} (${versionInfo.buildId})`)