mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-23 19:57:09 +00:00
feat: implement centralized version calculation system
- Create versionUtils.js for unified version logic across components - Update UpdateManager to use centralized getCurrentVersion() - Update /api/version endpoint to use centralized logic - Ensures consistent version calculation between update checks and version display - Prevents version fragmentation between different system components This resolves the issue where Settings modal showed inconsistent RC versions by ensuring both the current version display and update checking use the same dynamic git-based calculation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+8
-57
@@ -729,65 +729,16 @@ app.get('/api/alerts/status', (req, res) => {
|
||||
// Version API endpoint
|
||||
app.get('/api/version', async (req, res) => {
|
||||
try {
|
||||
const { execSync } = require('child_process');
|
||||
const packageJson = require('../package.json');
|
||||
const { getCurrentVersionInfo } = require('./versionUtils');
|
||||
|
||||
// Get version info using centralized logic
|
||||
const versionInfo = getCurrentVersionInfo();
|
||||
const currentVersion = versionInfo.version;
|
||||
const gitBranch = versionInfo.gitBranch;
|
||||
const isDevelopment = versionInfo.isDevelopment;
|
||||
|
||||
let currentVersion = packageJson.version || 'N/A';
|
||||
let latestVersion = currentVersion;
|
||||
let updateAvailable = false;
|
||||
let gitBranch = null;
|
||||
|
||||
// Try to detect git branch and calculate dynamic version
|
||||
try {
|
||||
const gitDir = path.join(__dirname, '..');
|
||||
|
||||
// Get current branch
|
||||
gitBranch = execSync('git branch --show-current', {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8'
|
||||
}).trim();
|
||||
|
||||
// If on develop branch, calculate RC version from git
|
||||
if (gitBranch === 'develop') {
|
||||
try {
|
||||
// Get the latest stable release tag
|
||||
const latestStableTag = execSync('git tag -l "v*" | grep -v "rc\\|alpha\\|beta" | sort -V | tail -1', {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8',
|
||||
shell: '/bin/bash'
|
||||
}).trim();
|
||||
|
||||
if (latestStableTag) {
|
||||
// Remove 'v' prefix to get base version
|
||||
const baseVersion = latestStableTag.replace(/^v/, '');
|
||||
|
||||
// Count commits since the latest stable tag
|
||||
const commitsSince = execSync(`git rev-list --count ${latestStableTag}..HEAD`, {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8'
|
||||
}).trim();
|
||||
|
||||
const commitsCount = parseInt(commitsSince, 10);
|
||||
|
||||
if (commitsCount > 0) {
|
||||
// Calculate RC version: base version + rc + commit count
|
||||
currentVersion = `${baseVersion}-rc${commitsCount}`;
|
||||
} else {
|
||||
// No commits since stable, use base version
|
||||
currentVersion = baseVersion;
|
||||
}
|
||||
}
|
||||
} catch (versionError) {
|
||||
console.log("[Version API] Could not calculate RC version from git, using package.json");
|
||||
// Fall back to package.json version
|
||||
currentVersion = packageJson.version;
|
||||
}
|
||||
}
|
||||
} catch (gitError) {
|
||||
// Git not available or not a git repo
|
||||
gitBranch = null;
|
||||
currentVersion = packageJson.version;
|
||||
}
|
||||
|
||||
try {
|
||||
// Try to check for updates, but don't fail if it doesn't work
|
||||
@@ -804,7 +755,7 @@ app.get('/api/version', async (req, res) => {
|
||||
latestVersion: latestVersion,
|
||||
updateAvailable: updateAvailable,
|
||||
gitBranch: gitBranch,
|
||||
isDevelopment: gitBranch === 'develop' || process.env.NODE_ENV === 'development'
|
||||
isDevelopment: isDevelopment
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("[Version API] Error in version endpoint:", error);
|
||||
|
||||
+13
-9
@@ -5,6 +5,7 @@ const path = require('path');
|
||||
const { exec, spawn } = require('child_process');
|
||||
const { promisify } = require('util');
|
||||
const { getUpdateChannelPreference } = require('./configLoader');
|
||||
const { getCurrentVersion } = require('./versionUtils');
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
class UpdateManager {
|
||||
@@ -64,6 +65,9 @@ class UpdateManager {
|
||||
try {
|
||||
console.log('[UpdateManager] Checking for updates...');
|
||||
|
||||
// Get the current version using centralized logic
|
||||
const dynamicCurrentVersion = getCurrentVersion();
|
||||
|
||||
// Use override channel if provided and valid, otherwise use config
|
||||
const configChannel = getUpdateChannelPreference();
|
||||
const updateChannel = (channelOverride && ['stable', 'rc'].includes(channelOverride))
|
||||
@@ -125,8 +129,8 @@ class UpdateManager {
|
||||
if (!latestRelease) {
|
||||
// No newer RC version found
|
||||
const updateInfo = {
|
||||
currentVersion: this.currentVersion,
|
||||
latestVersion: this.currentVersion,
|
||||
currentVersion: dynamicCurrentVersion,
|
||||
latestVersion: dynamicCurrentVersion,
|
||||
updateAvailable: false,
|
||||
isDocker: this.isDockerEnvironment(),
|
||||
releaseNotes: 'No newer RC version available',
|
||||
@@ -135,7 +139,7 @@ class UpdateManager {
|
||||
assets: [],
|
||||
updateChannel: channelDescription
|
||||
};
|
||||
console.log(`[UpdateManager] No RC updates available: ${this.currentVersion}`);
|
||||
console.log(`[UpdateManager] No RC updates available: ${dynamicCurrentVersion}`);
|
||||
return updateInfo;
|
||||
}
|
||||
|
||||
@@ -145,9 +149,9 @@ class UpdateManager {
|
||||
const latestVersion = response.data.tag_name.replace('v', '');
|
||||
|
||||
// For stable channel, also consider "downgrade" from RC as an update
|
||||
const isCurrentRC = this.isReleaseCandidate();
|
||||
const isCurrentRC = this.isReleaseCandidate(dynamicCurrentVersion);
|
||||
const isStableChannel = updateChannel === 'stable';
|
||||
const isDifferentVersion = latestVersion !== this.currentVersion;
|
||||
const isDifferentVersion = latestVersion !== dynamicCurrentVersion;
|
||||
|
||||
let updateAvailable;
|
||||
if (isStableChannel && isCurrentRC && isDifferentVersion) {
|
||||
@@ -155,14 +159,14 @@ class UpdateManager {
|
||||
updateAvailable = true;
|
||||
} else if (updateChannel === 'rc') {
|
||||
// For RC channel, show update if versions differ or if latest is newer
|
||||
updateAvailable = isDifferentVersion || semver.gt(latestVersion, this.currentVersion);
|
||||
updateAvailable = isDifferentVersion || semver.gt(latestVersion, dynamicCurrentVersion);
|
||||
} else {
|
||||
// Normal case: only newer versions
|
||||
updateAvailable = semver.gt(latestVersion, this.currentVersion);
|
||||
updateAvailable = semver.gt(latestVersion, dynamicCurrentVersion);
|
||||
}
|
||||
|
||||
const updateInfo = {
|
||||
currentVersion: this.currentVersion,
|
||||
currentVersion: dynamicCurrentVersion,
|
||||
latestVersion,
|
||||
updateAvailable,
|
||||
isDocker: this.isDockerEnvironment(),
|
||||
@@ -177,7 +181,7 @@ class UpdateManager {
|
||||
}))
|
||||
};
|
||||
|
||||
console.log(`[UpdateManager] Current version: ${this.currentVersion}, Latest version: ${latestVersion}, Channel: ${channelDescription}, Docker: ${updateInfo.isDocker}`);
|
||||
console.log(`[UpdateManager] Current version: ${dynamicCurrentVersion}, Latest version: ${latestVersion}, Channel: ${channelDescription}, Docker: ${updateInfo.isDocker}`);
|
||||
return updateInfo;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Centralized version calculation utility
|
||||
* Used by both /api/version endpoint and UpdateManager to ensure consistency
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Calculate the current version dynamically from git
|
||||
* @returns {Object} Version information including version, branch, and isDevelopment
|
||||
*/
|
||||
function getCurrentVersionInfo() {
|
||||
try {
|
||||
const packageJson = require('../package.json');
|
||||
|
||||
let currentVersion = packageJson.version || 'N/A';
|
||||
let gitBranch = null;
|
||||
let isDevelopment = false;
|
||||
|
||||
// Try to detect git branch and calculate dynamic version
|
||||
try {
|
||||
const gitDir = path.join(__dirname, '..');
|
||||
|
||||
// Get current branch
|
||||
gitBranch = execSync('git branch --show-current', {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8'
|
||||
}).trim();
|
||||
|
||||
// If on develop branch, calculate RC version from git
|
||||
if (gitBranch === 'develop') {
|
||||
isDevelopment = true;
|
||||
try {
|
||||
// Get the latest stable release tag
|
||||
const latestStableTag = execSync('git tag -l "v*" | grep -v "rc\\\\|alpha\\\\|beta" | sort -V | tail -1', {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8',
|
||||
shell: '/bin/bash'
|
||||
}).trim();
|
||||
|
||||
if (latestStableTag) {
|
||||
// Remove 'v' prefix to get base version
|
||||
const baseVersion = latestStableTag.replace(/^v/, '');
|
||||
|
||||
// Count commits since the latest stable tag
|
||||
const commitsSince = execSync(`git rev-list --count ${latestStableTag}..HEAD`, {
|
||||
cwd: gitDir,
|
||||
encoding: 'utf8'
|
||||
}).trim();
|
||||
|
||||
const commitsCount = parseInt(commitsSince, 10);
|
||||
|
||||
if (commitsCount > 0) {
|
||||
// Calculate RC version: base version + rc + commit count
|
||||
currentVersion = `${baseVersion}-rc${commitsCount}`;
|
||||
} else {
|
||||
// No commits since stable, use base version
|
||||
currentVersion = baseVersion;
|
||||
}
|
||||
}
|
||||
} catch (versionError) {
|
||||
console.log('[VersionUtils] Could not calculate RC version from git, using package.json');
|
||||
// Fall back to package.json version
|
||||
currentVersion = packageJson.version;
|
||||
}
|
||||
}
|
||||
} catch (gitError) {
|
||||
// Git not available or not a git repo
|
||||
gitBranch = null;
|
||||
currentVersion = packageJson.version;
|
||||
}
|
||||
|
||||
return {
|
||||
version: currentVersion,
|
||||
gitBranch: gitBranch,
|
||||
isDevelopment: isDevelopment || gitBranch === 'develop' || process.env.NODE_ENV === 'development'
|
||||
};
|
||||
} catch (error) {
|
||||
console.warn('[VersionUtils] Error getting current version:', error.message);
|
||||
const packageJson = require('../package.json');
|
||||
return {
|
||||
version: packageJson.version || 'N/A',
|
||||
gitBranch: null,
|
||||
isDevelopment: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get just the version string (for backwards compatibility)
|
||||
* @returns {string} The current version
|
||||
*/
|
||||
function getCurrentVersion() {
|
||||
return getCurrentVersionInfo().version;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getCurrentVersionInfo,
|
||||
getCurrentVersion
|
||||
};
|
||||
Reference in New Issue
Block a user