릴리즈 v0.2.7: 시스템 환경 정보 시각화 및 캐싱 보정
This commit is contained in:
parent
6ad6084ef2
commit
98b52c390e
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "smartims",
|
"name": "smartims",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.2.6",
|
"version": "0.2.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@ -364,6 +364,9 @@ app.get('/api/health', (req, res) => {
|
|||||||
res.json({
|
res.json({
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
version: packageJson.version,
|
version: packageJson.version,
|
||||||
|
node_version: process.version,
|
||||||
|
platform: process.platform,
|
||||||
|
arch: process.arch,
|
||||||
timestamp: new Date().toISOString().replace('T', ' ').split('.')[0]
|
timestamp: new Date().toISOString().replace('T', ' ').split('.')[0]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.2.6",
|
"version": "0.2.7",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -435,18 +435,30 @@ router.get('/version/remote', isAuthenticated, hasRole('admin'), async (req, res
|
|||||||
const currentVersion = packageJson.version;
|
const currentVersion = packageJson.version;
|
||||||
|
|
||||||
// Run git fetch to update tags from remote
|
// Run git fetch to update tags from remote
|
||||||
exec('git fetch --tags', (err) => {
|
exec('git fetch --tags', (err, stdout, stderr) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Git fetch failed:', err);
|
console.error('Git fetch failed:', err);
|
||||||
|
console.error('Stderr:', stderr);
|
||||||
return res.json({
|
return res.json({
|
||||||
current: currentVersion,
|
current: currentVersion,
|
||||||
latest: null,
|
latest: null,
|
||||||
error: '원격 저장소에 연결할 수 없습니다. Git 설정을 확인하세요.'
|
error: `원격 저장소 동기화 실패: ${stderr || err.message}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the latest tag
|
// Get the latest tag (Simplified for cross-platform compatibility)
|
||||||
exec('git describe --tags $(git rev-list --tags --max-count=1)', (err, stdout) => {
|
// git describe --tags --abbrev=0 is more robust across shells
|
||||||
|
exec('git describe --tags --abbrev=0', (err, stdout, stderr) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Git describe failed:', err);
|
||||||
|
return res.json({
|
||||||
|
current: currentVersion,
|
||||||
|
latest: null,
|
||||||
|
needsUpdate: false,
|
||||||
|
error: '태그 정보를 찾을 수 없습니다.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const latestTag = stdout ? stdout.trim() : null;
|
const latestTag = stdout ? stdout.trim() : null;
|
||||||
res.json({
|
res.json({
|
||||||
current: currentVersion,
|
current: currentVersion,
|
||||||
|
|||||||
@ -6,6 +6,9 @@ import { Info, Cpu, Database, Server, Hash, Calendar, RefreshCw, AlertTriangle,
|
|||||||
interface VersionInfo {
|
interface VersionInfo {
|
||||||
status: string;
|
status: string;
|
||||||
version: string;
|
version: string;
|
||||||
|
node_version: string;
|
||||||
|
platform: string;
|
||||||
|
arch: string;
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +30,8 @@ export function VersionPage() {
|
|||||||
const fetchVersion = async () => {
|
const fetchVersion = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
const res = await apiClient.get('/health');
|
// Add timestamp to prevent caching
|
||||||
|
const res = await apiClient.get(`/health?t=${Date.now()}`);
|
||||||
setHealthInfo(res.data);
|
setHealthInfo(res.data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Failed to fetch version info', err);
|
console.error('Failed to fetch version info', err);
|
||||||
@ -75,10 +79,14 @@ export function VersionPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use values from healthIcon if available, otherwise fallback to local constants
|
// Client/Frontend version fixed at build time
|
||||||
const currentVersion = healthIcon?.version || '0.2.6';
|
const frontendVersion = '0.2.7';
|
||||||
const buildDate = '2026-01-24';
|
const buildDate = '2026-01-24';
|
||||||
|
|
||||||
|
// Check if update is needed based on frontend version vs remote tag
|
||||||
|
const needsUpdate = remoteInfo?.latest ?
|
||||||
|
(remoteInfo.latest.replace(/^v/, '') !== frontendVersion) : false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page-container p-6 max-w-4xl mx-auto">
|
<div className="page-container p-6 max-w-4xl mx-auto">
|
||||||
<div className="flex justify-between items-start mb-8">
|
<div className="flex justify-between items-start mb-8">
|
||||||
@ -96,8 +104,8 @@ export function VersionPage() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Update Alert Banner */}
|
{/* Update Alert Banner - Based on Frontend Version comparison */}
|
||||||
{remoteInfo?.needsUpdate && !updateResult && (
|
{needsUpdate && !updateResult && (
|
||||||
<div className="mb-8 p-4 bg-amber-50 border border-amber-200 rounded-xl flex items-center justify-between animate-in fade-in slide-in-from-top-4 duration-500">
|
<div className="mb-8 p-4 bg-amber-50 border border-amber-200 rounded-xl flex items-center justify-between animate-in fade-in slide-in-from-top-4 duration-500">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="p-2 bg-amber-100 text-amber-600 rounded-lg">
|
<div className="p-2 bg-amber-100 text-amber-600 rounded-lg">
|
||||||
@ -105,7 +113,7 @@ export function VersionPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-bold text-amber-900">새로운 시스템 업데이트가 가능합니다!</h4>
|
<h4 className="font-bold text-amber-900">새로운 시스템 업데이트가 가능합니다!</h4>
|
||||||
<p className="text-sm text-amber-700">현재 버전: v{currentVersion} → 최신 버전: <span className="font-bold">{remoteInfo.latest}</span></p>
|
<p className="text-sm text-amber-700">현재 플랫폼 버전: v{frontendVersion} → 최신 배포 버전: <span className="font-bold">{remoteInfo?.latest}</span></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@ -146,7 +154,7 @@ export function VersionPage() {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
||||||
<span className="text-slate-500 text-sm flex items-center gap-2"><Info size={14} /> 현재 버전</span>
|
<span className="text-slate-500 text-sm flex items-center gap-2"><Info size={14} /> 현재 버전</span>
|
||||||
<span className="font-bold text-indigo-600 bg-indigo-50 px-3 py-1 rounded-full text-xs">v{currentVersion}</span>
|
<span className="font-bold text-indigo-600 bg-indigo-50 px-3 py-1 rounded-full text-xs">v{frontendVersion}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
||||||
<span className="text-slate-500 text-sm flex items-center gap-2"><Calendar size={14} /> 빌드 일자</span>
|
<span className="text-slate-500 text-sm flex items-center gap-2"><Calendar size={14} /> 빌드 일자</span>
|
||||||
@ -176,19 +184,25 @@ export function VersionPage() {
|
|||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
||||||
<span className="text-slate-500 text-sm flex items-center gap-2"><Info size={14} /> API 버전</span>
|
<span className="text-slate-500 text-sm flex items-center gap-2"><Cpu size={14} /> 런타임 환경</span>
|
||||||
<span className="font-bold text-emerald-600 bg-emerald-50 px-3 py-1 rounded-full text-xs">
|
<span className="font-medium text-slate-700 text-sm">
|
||||||
{loading ? 'Checking...' : healthIcon?.version ? `v${healthIcon.version}` : 'N/A'}
|
{loading ? 'Checking...' : healthIcon?.node_version ? `Node.js ${healthIcon.node_version}` : 'N/A'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
||||||
|
<span className="text-slate-500 text-sm flex items-center gap-2"><Server size={14} /> 운영 체제</span>
|
||||||
|
<span className="font-medium text-slate-700 text-sm uppercase">
|
||||||
|
{loading ? '...' : healthIcon?.platform ? `${healthIcon.platform} (${healthIcon.arch})` : 'Unknown'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
<div className="flex justify-between items-center py-2 border-b border-slate-50">
|
||||||
<span className="text-slate-500 text-sm flex items-center gap-2"><Calendar size={14} /> 서버 타임스탬프</span>
|
<span className="text-slate-500 text-sm flex items-center gap-2"><Calendar size={14} /> 서버 타임스탬프</span>
|
||||||
<span className="font-medium text-slate-700 text-sm truncate max-w-[150px]">
|
<span className="font-medium text-slate-700 text-sm">
|
||||||
{loading ? '...' : healthIcon?.timestamp || 'Unknown'}
|
{loading ? '...' : healthIcon?.timestamp || 'Unknown'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center py-2">
|
<div className="flex justify-between items-center py-2">
|
||||||
<span className="text-slate-500 text-sm flex items-center gap-2"><Server size={14} /> 엔진 상태</span>
|
<span className="text-slate-500 text-sm flex items-center gap-2"><RefreshCw size={14} /> 엔진 상태</span>
|
||||||
<span className={`font-bold text-xs uppercase ${healthIcon?.status === 'ok' ? 'text-emerald-500' : 'text-red-500'}`}>
|
<span className={`font-bold text-xs uppercase ${healthIcon?.status === 'ok' ? 'text-emerald-500' : 'text-red-500'}`}>
|
||||||
{loading ? '...' : healthIcon?.status === 'ok' ? 'Running' : 'Offline'}
|
{loading ? '...' : healthIcon?.status === 'ok' ? 'Running' : 'Offline'}
|
||||||
</span>
|
</span>
|
||||||
@ -219,17 +233,26 @@ export function VersionPage() {
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{[
|
{[
|
||||||
{
|
{
|
||||||
version: '0.2.5',
|
version: '0.2.7',
|
||||||
date: '2026-01-24',
|
date: '2026-01-24',
|
||||||
title: '플랫폼 보안 모듈 및 시스템 자동 업데이트 엔진 도입',
|
title: '시스템 환경 정보 시각화 및 캐싱 보정',
|
||||||
changes: [
|
changes: [
|
||||||
'Git Tag 기반 시스템 자동 업데이트 관리 모듈 신규 도입',
|
'백엔드 서비스 엔진 카드에 실제 런타임(Node.js) 및 OS 정보 표시',
|
||||||
'최고관리자 전용 업데이트 실행 UI 구축',
|
'버전 정보 조회 시 브라우저 API 캐싱 보정 로직 적용',
|
||||||
'데이터베이스 및 암호화 마스터 키 자가 관리 엔진 고도화',
|
'플랫폼 업데이트 판단 기준을 프론트엔드 빌드 버전으로 일원화'
|
||||||
'사용자 관리 UI 디자인 및 권한 계층 로직 일원화'
|
|
||||||
],
|
],
|
||||||
type: 'feature'
|
type: 'feature'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
version: '0.2.6',
|
||||||
|
date: '2026-01-24',
|
||||||
|
title: '시스템 자동 업데이트 엔진 도입 (Hotfix)',
|
||||||
|
changes: [
|
||||||
|
'Git Tag 기반 시스템 자동 업데이트 관리 모듈 신규 도입',
|
||||||
|
'최고관리자 전용 업데이트 실행 UI 구축'
|
||||||
|
],
|
||||||
|
type: 'fix'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: '0.2.1',
|
version: '0.2.1',
|
||||||
date: '2026-01-22',
|
date: '2026-01-22',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user