Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
path: |
dist/*.exe
dist/*.msi
dist/latest*.yml
dist/*.yml
dist/*.blockmap
retention-days: 5

Expand Down Expand Up @@ -112,7 +112,7 @@ jobs:
path: |
dist/*.AppImage
dist/*.AppImage.zsync
dist/latest*.yml
dist/*.yml
dist/*.blockmap
retention-days: 5

Expand Down Expand Up @@ -151,7 +151,7 @@ jobs:
path: |
dist/*.dmg
dist/*.zip
dist/latest*.yml
dist/*.yml
dist/*.blockmap
retention-days: 5

Expand All @@ -171,6 +171,17 @@ jobs:
id: get_version
run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT

- name: Validate tag matches package version
run: |
TAG_VERSION="${{ steps.get_version.outputs.VERSION }}"
TAG_VERSION="${TAG_VERSION#v}"
PACKAGE_VERSION="$(node -p "require('./package.json').version")"

if [[ "${TAG_VERSION}" != "${PACKAGE_VERSION}" ]]; then
echo "::error::Tag version (${TAG_VERSION}) does not match package.json version (${PACKAGE_VERSION})."
exit 1
fi

- name: Get Changelog Entry
id: changelog_reader
uses: mindsers/changelog-reader-action@32aa5b4c155d76c94e4ec883a223c947b2f02656
Expand Down Expand Up @@ -203,7 +214,8 @@ jobs:
with:
name: Release ${{ steps.get_version.outputs.VERSION }}
body: ${{ steps.changelog_reader.outputs.changes || 'No changelog provided' }}
draft: true
draft: ${{ !contains(steps.get_version.outputs.VERSION, '-alpha') }}
prerelease: ${{ contains(steps.get_version.outputs.VERSION, '-alpha') }}
files: |
artifacts/**
env:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,6 @@ src/renderer/bundle.js

# Test artifacts
/test-results

# Local planning notes (never commit)
docs/plan/
95 changes: 86 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,10 @@
"dependencies": {
"@headlessui/react": "^2.2.9",
"@heroicons/react": "^2.1.1",
"@openfeature/server-sdk": "^1.20.1",
"clsx": "^2.1.0",
"electron-store": "^8.1.0",
"electron-updater": "^6.7.3",
Comment thread
Mehdi-Bl marked this conversation as resolved.
"minimatch": "^9.0.3",
"path-browserify": "^1.0.1",
"process": "^0.11.10",
Expand All @@ -134,6 +136,7 @@
"@babel/preset-typescript": "^7.26.0",
"@electron/rebuild": "^4.0.3",
"@jest/globals": "^29.7.0",
"@tailwindcss/cli": "^4.1.18",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^14.3.1",
"@testing-library/user-event": "^14.6.1",
Expand All @@ -143,7 +146,6 @@
"@types/react-dom": "^18.3.5",
"@typescript-eslint/eslint-plugin": "^8.24.0",
"@typescript-eslint/parser": "^8.24.0",
"@tailwindcss/cli": "^4.1.18",
"autoprefixer": "^10.4.17",
"babel-jest": "^29.7.0",
"babel-loader": "^10.0.0",
Expand Down
47 changes: 41 additions & 6 deletions scripts/sonar-scan.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env node
const { execSync, spawnSync } = require('child_process');
const { execFileSync, spawnSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const sonarqubeScanner = require('sonarqube-scanner');
Expand All @@ -14,6 +14,24 @@ function redactUrlForLogs(rawUrl) {
}
}

function resolveNpmCliPath() {
const npmExecPath = process.env.npm_execpath;
if (npmExecPath && path.isAbsolute(npmExecPath) && fs.existsSync(npmExecPath)) {
return npmExecPath;
}

try {
const resolvedNpmCliPath = require.resolve('npm/bin/npm-cli.js');
if (path.isAbsolute(resolvedNpmCliPath) && fs.existsSync(resolvedNpmCliPath)) {
return resolvedNpmCliPath;
}
} catch (_error) {
// Keep fallback behavior below.
}

return null;
}

function parseEnvValue(rawValue) {
const value = rawValue.trim();
if (
Expand Down Expand Up @@ -275,17 +293,34 @@ if (!sonarToken) {
console.log('SONAR_TOKEN not set; attempting unauthenticated scan');
}

// Run code coverage if it doesn't exist yet
// Generate a fresh coverage report so Sonar never uses stale lcov data.
const shouldGenerateCoverage = process.env.SONAR_GENERATE_COVERAGE !== 'false';
const coveragePath = path.join(__dirname, '..', 'coverage', 'lcov.info');
if (!fs.existsSync(coveragePath)) {
console.log('No coverage data found. Running tests with coverage...');
if (shouldGenerateCoverage) {
const coverageDir = path.join(__dirname, '..', 'coverage');
fs.rmSync(coverageDir, { recursive: true, force: true });
console.log('Generating fresh Jest coverage report for SonarQube...');
try {
execSync('npm test -- --coverage', { stdio: 'inherit' });
const npmCliPath = resolveNpmCliPath();
if (!npmCliPath) {
console.error('Error: Unable to resolve npm CLI path for coverage generation.');
process.exit(1);
}

execFileSync(process.execPath, [npmCliPath, 'test', '--', '--coverage', '--runInBand'], {
stdio: 'inherit',
});
} catch (error) {
console.warn('Warning: Test coverage generation had issues, but continuing with scan.');
console.error('Error: Failed to generate coverage report for SonarQube.');
process.exit(1);
}
}

if (!fs.existsSync(coveragePath)) {
console.error(`Error: Coverage report not found at ${coveragePath}`);
process.exit(1);
}

// Read properties from sonar-project.properties
const propertiesPath = path.join(__dirname, '..', 'sonar-project.properties');
const propertiesContent = fs.readFileSync(propertiesPath, 'utf8');
Expand Down
19 changes: 13 additions & 6 deletions sonar-project.properties
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
# Project identification
sonar.projectKey=ai-code-prep
sonar.projectKey=ai-code-fusion
sonar.projectName=Repository Code Fusion
sonar.projectVersion=0.1.0

# Source directories
sonar.sources=src
sonar.sourceEncoding=UTF-8

# Excluded directories and files
sonar.exclusions=node_modules/**,dist/**,**/*.test.js,**/*.test.jsx,**/*.spec.js,**/*.spec.jsx,coverage/**
# Excluded directories and files (avoid noise from tests, fixtures, generated assets)
sonar.exclusions=node_modules/**,dist/**,coverage/**,tests/**,scripts/**,**/__tests__/**,**/*.test.js,**/*.test.jsx,**/*.test.ts,**/*.test.tsx,**/*.spec.js,**/*.spec.jsx,**/*.spec.ts,**/*.spec.tsx,src/renderer/bundle.js,src/renderer/bundle.js.map,src/renderer/bundle.js.LICENSE.txt,src/renderer/output.css,src/renderer/styles.css

# Test directories
sonar.tests=src/__tests__
sonar.test.inclusions=**/*.test.js,**/*.test.jsx,**/*.spec.js,**/*.spec.jsx
# Test directories (kept for coverage mapping, excluded from issue noise)
sonar.tests=tests,src/__tests__
sonar.test.inclusions=tests/**/*.test.{js,jsx,ts,tsx},tests/**/*.spec.{js,jsx,ts,tsx},src/**/__tests__/**/*.{js,jsx,ts,tsx},src/**/*.test.{js,jsx,ts,tsx},src/**/*.spec.{js,jsx,ts,tsx}

# JavaScript configuration
sonar.javascript.lcov.reportPaths=coverage/lcov.info

# Temporary rule suppression:
# Jest currently fails to resolve `node:` core-module imports in this repo's runtime/tooling setup.
# Keep stable `fs/path` imports and suppress only this stylistic Node import rule.
sonar.issue.ignore.multicriteria=nodeCoreImportStyle
sonar.issue.ignore.multicriteria.nodeCoreImportStyle.ruleKey=typescript:S7772
sonar.issue.ignore.multicriteria.nodeCoreImportStyle.resourceKey=src/**/*
Loading
Loading