diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index fa50091e..7b431a10 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -37,11 +37,12 @@ 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 + - name: Install dependencies + run: npm install --legacy-peer-deps + - name: Update version from Git + run: node scripts/update-version.mjs + - run: cargo generate-lockfile --manifest-path src-tauri/Cargo.toml + - run: cargo fmt --manifest-path src-tauri/Cargo.toml --check rust-clippy: runs-on: ubuntu-latest @@ -76,7 +77,7 @@ jobs: key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ 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: runs-on: ubuntu-latest @@ -111,7 +112,7 @@ jobs: key: ${{ runner.os }}-cargo-linux-amd64-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ 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: runs-on: ubuntu-latest diff --git a/package.json b/package.json index 63d46fe2..20f212f2 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "tftsr", "private": true, - "version": "0.2.50", + "version": "0.2.62", "type": "module", "scripts": { "dev": "vite", "build": "tsc && vite build", + "version:update": "node scripts/update-version.mjs", "preview": "vite preview", "tauri": "tauri", "test": "vitest", diff --git a/scripts/update-version.mjs b/scripts/update-version.mjs index de91f1ed..d8300674 100644 --- a/scripts/update-version.mjs +++ b/scripts/update-version.mjs @@ -9,49 +9,118 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); 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() { try { const output = execSync('git describe --tags --abbrev=0', { encoding: 'utf-8', cwd: projectRoot }); - const version = output.trim().replace(/^v/, ''); - if (version) { - return version; + let version = output.trim(); + + // Remove v prefix + version = version.replace(/^v/, ''); + + // 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 version; } catch (e) { - console.warn('Failed to get version from Git tags, using fallback'); + console.warn('Failed to get version from Git tags, using fallback: 0.2.50'); + return '0.2.50'; } - return '0.2.50'; } -function updateFile(filePath, updater) { - const fullPath = resolve(projectRoot, filePath); +function updatePackageJson(version) { + const fullPath = resolve(projectRoot, 'package.json'); 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 json = JSON.parse(content); + json.version = version; + + // 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(); 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}"`); -}); +updatePackageJson(version); +updateTOML('src-tauri/Cargo.toml', version); +updateTOML('src-tauri/tauri.conf.json', version); +updateCargoLock(version); console.log(`✓ All version fields updated to ${version}`); diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f8de467c..5e1d8bd9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -7710,3 +7710,5 @@ checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ "zune-core", ] + + diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index aa83b3c3..298db0c9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trcaa" -version = "0.2.50" +version = "0.2.62" edition = "2021" [lib] @@ -52,3 +52,5 @@ mockito = "1.2" [profile.release] opt-level = "s" strip = true + + diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9baf1d1f..888de4f4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -6,7 +6,7 @@ "frontendDist": "../dist", "devUrl": "http://localhost:1420", "beforeDevCommand": "npm run dev", - "beforeBuildCommand": "npm run build" + "beforeBuildCommand": "npm run version:update && npm run build" }, "app": { "security": { @@ -41,4 +41,5 @@ "shortDescription": "Troubleshooting and RCA Assistant", "longDescription": "Structured AI-backed assistant for IT troubleshooting, 5-whys root cause analysis, and post-mortem documentation with offline Ollama support." } -} \ No newline at end of file +} +