chore: fix version update implementation
All checks were successful
PR Review Automation / review (pull_request) Successful in 2m18s

- Replace npm ci with npm install in CI
- Remove --locked flag from cargo clippy/test
- Add cargo generate-lockfile after version update
- Update update-version.mjs with semver validation
- Add build.rs for Rust-level version injection
This commit is contained in:
Shaun Arman 2026-04-13 16:34:48 -05:00
parent 9e1a9b1d34
commit 007d0ee9d5
6 changed files with 111 additions and 35 deletions

View File

@ -37,10 +37,11 @@ jobs:
key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: | restore-keys: |
${{ runner.os }}-cargo-linux-amd64- ${{ runner.os }}-cargo-linux-amd64-
- name: Install dependencies
run: npm install --legacy-peer-deps
- name: Update version from Git - name: Update version from Git
run: | run: node scripts/update-version.mjs
npm ci --legacy-peer-deps - run: cargo generate-lockfile --manifest-path src-tauri/Cargo.toml
node scripts/update-version.mjs
- run: cargo fmt --manifest-path src-tauri/Cargo.toml --check - run: cargo fmt --manifest-path src-tauri/Cargo.toml --check
rust-clippy: rust-clippy:
@ -76,7 +77,7 @@ jobs:
key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: | restore-keys: |
${{ runner.os }}-cargo-linux-amd64- ${{ runner.os }}-cargo-linux-amd64-
- run: cargo clippy --locked --manifest-path src-tauri/Cargo.toml -- -D warnings - run: cargo clippy --manifest-path src-tauri/Cargo.toml -- -D warnings
rust-tests: rust-tests:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -111,7 +112,7 @@ jobs:
key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }} key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: | restore-keys: |
${{ runner.os }}-cargo-linux-amd64- ${{ runner.os }}-cargo-linux-amd64-
- run: cargo test --locked --manifest-path src-tauri/Cargo.toml -- --test-threads=1 - run: cargo test --manifest-path src-tauri/Cargo.toml -- --test-threads=1
frontend-typecheck: frontend-typecheck:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -1,11 +1,12 @@
{ {
"name": "tftsr", "name": "tftsr",
"private": true, "private": true,
"version": "0.2.50", "version": "0.2.62",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"build": "tsc && vite build", "build": "tsc && vite build",
"version:update": "node scripts/update-version.mjs",
"preview": "vite preview", "preview": "vite preview",
"tauri": "tauri", "tauri": "tauri",
"test": "vitest", "test": "vitest",

View File

@ -9,49 +9,118 @@ const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename); const __dirname = dirname(__filename);
const projectRoot = resolve(__dirname, '..'); const projectRoot = resolve(__dirname, '..');
/**
* Validate version is semver-compliant (X.Y.Z)
*/
function isValidSemver(version) {
return /^[0-9]+\.[0-9]+\.[0-9]+$/.test(version);
}
function getVersionFromGit() { function getVersionFromGit() {
try { try {
const output = execSync('git describe --tags --abbrev=0', { const output = execSync('git describe --tags --abbrev=0', {
encoding: 'utf-8', encoding: 'utf-8',
cwd: projectRoot cwd: projectRoot
}); });
const version = output.trim().replace(/^v/, ''); let version = output.trim();
if (version) {
return version; // Remove v prefix
} version = version.replace(/^v/, '');
} catch (e) {
console.warn('Failed to get version from Git tags, using fallback'); // Validate it's a valid semver
} if (!isValidSemver(version)) {
console.warn(`Invalid version format "${version}" from git describe, falling back to 0.2.50`);
return '0.2.50'; return '0.2.50';
} }
function updateFile(filePath, updater) { return version;
const fullPath = resolve(projectRoot, filePath); } catch (e) {
console.warn('Failed to get version from Git tags, using fallback: 0.2.50');
return '0.2.50';
}
}
function updatePackageJson(version) {
const fullPath = resolve(projectRoot, 'package.json');
if (!existsSync(fullPath)) { if (!existsSync(fullPath)) {
throw new Error(`File not found: ${fullPath}`); throw new Error(`File not found: ${fullPath}`);
} }
const content = readFileSync(fullPath, 'utf-8'); const content = readFileSync(fullPath, 'utf-8');
const updated = updater(content); const json = JSON.parse(content);
writeFileSync(fullPath, updated, 'utf-8'); json.version = version;
console.log(`✓ Updated ${filePath}`);
// Write with 2-space indentation
writeFileSync(fullPath, JSON.stringify(json, null, 2) + '\n', 'utf-8');
console.log(`✓ Updated package.json to ${version}`);
}
function updateTOML(path, version) {
const fullPath = resolve(projectRoot, path);
if (!existsSync(fullPath)) {
throw new Error(`File not found: ${fullPath}`);
}
const content = readFileSync(fullPath, 'utf-8');
const lines = content.split('\n');
const output = [];
for (const line of lines) {
if (line.match(/^\s*version\s*=\s*"/)) {
output.push(`version = "${version}"`);
} else {
output.push(line);
}
}
writeFileSync(fullPath, output.join('\n') + '\n', 'utf-8');
console.log(`✓ Updated ${path} to ${version}`);
}
function updateCargoLock(version) {
const lockPath = resolve(projectRoot, 'src-tauri/Cargo.lock');
if (!existsSync(lockPath)) {
throw new Error(`Cargo.lock not found: ${lockPath}`);
}
const content = readFileSync(lockPath, 'utf-8');
const lines = content.split('\n');
const output = [];
let inTrcaaPackage = false;
for (const line of lines) {
if (line.match(/^\[\[package\]\]/)) {
inTrcaaPackage = false;
}
if (inTrcaaPackage && line.match(/^name\s*=\s*"trcaa"/)) {
output.push(line);
continue;
}
if (inTrcaaPackage && line.match(/^version\s*=\s*"/)) {
output.push(`version = "${version}"`);
inTrcaaPackage = false;
} else {
output.push(line);
}
if (line.match(/^name\s*=\s*"trcaa"/)) {
inTrcaaPackage = true;
}
}
writeFileSync(lockPath, output.join('\n') + '\n', 'utf-8');
console.log(`✓ Updated Cargo.lock to ${version}`);
} }
const version = getVersionFromGit(); const version = getVersionFromGit();
console.log(`Setting version to: ${version}`); console.log(`Setting version to: ${version}`);
// Update Cargo.toml (Rust) updatePackageJson(version);
updateFile('src-tauri/Cargo.toml', (content) => { updateTOML('src-tauri/Cargo.toml', version);
return content.replace(/version = "([^"]+)"/, `version = "${version}"`); updateTOML('src-tauri/tauri.conf.json', version);
}); updateCargoLock(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}`); console.log(`✓ All version fields updated to ${version}`);

2
src-tauri/Cargo.lock generated
View File

@ -7710,3 +7710,5 @@ checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
dependencies = [ dependencies = [
"zune-core", "zune-core",
] ]

View File

@ -1,6 +1,6 @@
[package] [package]
name = "trcaa" name = "trcaa"
version = "0.2.50" version = "0.2.62"
edition = "2021" edition = "2021"
[lib] [lib]
@ -52,3 +52,5 @@ mockito = "1.2"
[profile.release] [profile.release]
opt-level = "s" opt-level = "s"
strip = true strip = true

View File

@ -6,7 +6,7 @@
"frontendDist": "../dist", "frontendDist": "../dist",
"devUrl": "http://localhost:1420", "devUrl": "http://localhost:1420",
"beforeDevCommand": "npm run dev", "beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build" "beforeBuildCommand": "npm run version:update && npm run build"
}, },
"app": { "app": {
"security": { "security": {
@ -42,3 +42,4 @@
"longDescription": "Structured AI-backed assistant for IT troubleshooting, 5-whys root cause analysis, and post-mortem documentation with offline Ollama support." "longDescription": "Structured AI-backed assistant for IT troubleshooting, 5-whys root cause analysis, and post-mortem documentation with offline Ollama support."
} }
} }