Compare commits

...

1 Commits

Author SHA1 Message Date
Shaun Arman
ae3e478034 feat: implement dynamic versioning from Git tags
All checks were successful
Auto Tag / autotag (push) Successful in 6s
Auto Tag / wiki-sync (push) Successful in 6s
Auto Tag / changelog (push) Successful in 42s
Auto Tag / build-macos-arm64 (push) Successful in 2m53s
Auto Tag / build-linux-amd64 (push) Successful in 12m6s
Auto Tag / build-linux-arm64 (push) Successful in 14m10s
Auto Tag / build-windows-amd64 (push) Successful in 14m45s
- Add build.rs to read version from git describe --tags
- Create update-version.mjs script to sync version across files
- Add get_app_version() command to Rust backend
- Update App.tsx to use custom version command
- Run version update in CI before Rust checks
2026-04-13 16:08:58 -05:00
8 changed files with 106 additions and 4 deletions

View File

@ -37,6 +37,10 @@ jobs:
key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-linux-amd64-
- name: Update version from Git
run: |
npm ci --legacy-peer-deps
node scripts/update-version.mjs
- run: cargo fmt --manifest-path src-tauri/Cargo.toml --check
rust-clippy:

View File

@ -0,0 +1,57 @@
#!/usr/bin/env node
import { execSync } from 'child_process';
import { readFileSync, writeFileSync, existsSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const projectRoot = resolve(__dirname, '..');
function getVersionFromGit() {
try {
const output = execSync('git describe --tags --abbrev=0', {
encoding: 'utf-8',
cwd: projectRoot
});
const version = output.trim().replace(/^v/, '');
if (version) {
return version;
}
} catch (e) {
console.warn('Failed to get version from Git tags, using fallback');
}
return '0.2.50';
}
function updateFile(filePath, updater) {
const fullPath = resolve(projectRoot, filePath);
if (!existsSync(fullPath)) {
throw new Error(`File not found: ${fullPath}`);
}
const content = readFileSync(fullPath, 'utf-8');
const updated = updater(content);
writeFileSync(fullPath, updated, 'utf-8');
console.log(`✓ Updated ${filePath}`);
}
const version = getVersionFromGit();
console.log(`Setting version to: ${version}`);
// Update Cargo.toml (Rust)
updateFile('src-tauri/Cargo.toml', (content) => {
return content.replace(/version = "([^"]+)"/, `version = "${version}"`);
});
// Update package.json (Frontend)
updateFile('package.json', (content) => {
return content.replace(/"version": "([^"]+)"/, `"version": "${version}"`);
});
// Update tauri.conf.json
updateFile('src-tauri/tauri.conf.json', (content) => {
return content.replace(/"version": "([^"]+)"/, `"version": "${version}"`);
});
console.log(`✓ All version fields updated to ${version}`);

2
src-tauri/Cargo.lock generated
View File

@ -6139,7 +6139,7 @@ dependencies = [
[[package]]
name = "trcaa"
version = "0.2.50"
version = "0.2.62"
dependencies = [
"aes-gcm",
"aho-corasick",

View File

@ -1,3 +1,30 @@
fn main() {
let version = get_version_from_git();
println!("cargo:rustc-env=APP_VERSION={}", version);
println!("cargo:rerun-if-changed=.git/refs/heads/master");
println!("cargo:rerun-if-changed=.git/refs/tags");
tauri_build::build()
}
fn get_version_from_git() -> String {
if let Ok(output) = std::process::Command::new("git")
.arg("describe")
.arg("--tags")
.arg("--abbrev=0")
.output()
{
if output.status.success() {
let version = String::from_utf8_lossy(&output.stdout)
.trim()
.trim_start_matches('v')
.to_string();
if !version.is_empty() {
return version;
}
}
}
"0.2.50".to_string()
}

View File

@ -4,6 +4,7 @@ use crate::ollama::{
OllamaStatus,
};
use crate::state::{AppSettings, AppState, ProviderConfig};
use std::env;
// --- Ollama commands ---
@ -275,3 +276,11 @@ pub async fn delete_ai_provider(
Ok(())
}
/// Get the application version from build-time environment
#[tauri::command]
pub async fn get_app_version() -> Result<String, String> {
env::var("APP_VERSION")
.or_else(|_| env::var("CARGO_PKG_VERSION"))
.map_err(|e| format!("Failed to get version: {e}"))
}

View File

@ -120,6 +120,7 @@ pub fn run() {
commands::system::get_settings,
commands::system::update_settings,
commands::system::get_audit_log,
commands::system::get_app_version,
])
.run(tauri::generate_context!())
.expect("Error running Troubleshooting and RCA Assistant application");

View File

@ -1,5 +1,4 @@
import React, { useState, useEffect } from "react";
import { getVersion } from "@tauri-apps/api/app";
import { Routes, Route, NavLink, useLocation } from "react-router-dom";
import {
Home,
@ -15,7 +14,7 @@ import {
Moon,
} from "lucide-react";
import { useSettingsStore } from "@/stores/settingsStore";
import { loadAiProvidersCmd, testProviderConnectionCmd } from "@/lib/tauriCommands";
import { getAppVersionCmd, loadAiProvidersCmd, testProviderConnectionCmd } from "@/lib/tauriCommands";
import Dashboard from "@/pages/Dashboard";
import NewIssue from "@/pages/NewIssue";
@ -50,7 +49,7 @@ export default function App() {
void useLocation();
useEffect(() => {
getVersion().then(setAppVersion).catch(() => {});
getAppVersionCmd().then(setAppVersion).catch(() => {});
}, []);
// Load providers and auto-test active provider on startup

View File

@ -486,3 +486,8 @@ export const loadAiProvidersCmd = () =>
export const deleteAiProviderCmd = (name: string) =>
invoke<void>("delete_ai_provider", { name });
// ─── System / Version ─────────────────────────────────────────────────────────
export const getAppVersionCmd = () =>
invoke<string>("get_app_version");