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
4 changes: 0 additions & 4 deletions .github/codeql/codeql-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,3 @@ paths-ignore:
- 'build/**'
- 'coverage/**'
- 'dist/**'
- 'src/renderer/bundle.js'
- 'src/renderer/bundle.js.map'
- 'src/renderer/bundle.js.LICENSE.txt'
- 'src/renderer/output.css'
9 changes: 9 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ jobs:
- name: Prepare build
run: node scripts/prepare-build.js windows

- name: Build CSS
run: npm run build:css

- name: Build Webpack
run: npm run build:webpack

Expand Down Expand Up @@ -101,6 +104,9 @@ jobs:
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
"

- name: Build CSS
run: npm run build:css

- name: Build Webpack
run: npm run build:webpack

Expand Down Expand Up @@ -142,6 +148,9 @@ jobs:
- name: Prepare build
run: node scripts/prepare-build.js mac

- name: Build CSS
run: npm run build:css

- name: Build Webpack
run: npm run build:webpack

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
-Dsonar.sources=src
-Dsonar.tests=tests,src/__tests__
-Dsonar.test.inclusions=tests/**/*.test.{js,jsx,ts,tsx},tests/**/*.spec.{js,jsx,ts,tsx},tests/**/*.stress.test.{js,jsx,ts,tsx},src/**/__tests__/**/*.{js,jsx,ts,tsx},src/**/*.test.{js,jsx,ts,tsx},src/**/*.spec.{js,jsx,ts,tsx}
-Dsonar.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
-Dsonar.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/styles.css
-Dsonar.cpd.exclusions=tests/**,scripts/**,src/**/__tests__/**,**/*.test.js,**/*.test.jsx,**/*.test.ts,**/*.test.tsx,**/*.spec.js,**/*.spec.jsx,**/*.spec.ts,**/*.spec.tsx,**/*.stress.test.js,**/*.stress.test.jsx,**/*.stress.test.ts,**/*.stress.test.tsx

- name: SonarCloud quality gate
Expand Down
6 changes: 0 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
/build

# Build outputs
/src/renderer/index.js
/src/renderer/index.js.map
/src/renderer/output.css
/.tmp*
/temp

Expand Down Expand Up @@ -70,9 +67,6 @@ $RECYCLE.BIN/
start/
start/*
/signed/
src/renderer/bundle.js.LICENSE.txt
src/renderer/bundle.js.map
src/renderer/bundle.js

# Test artifacts
/test-results
Expand Down
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"watch:webpack": "cross-env NODE_ENV=development webpack --mode development --watch",
"predev": "npm run build:ts && node scripts/clean-dev-assets.js",
"dev": "node scripts/index.js dev",
"clear-assets": "rimraf src/renderer/bundle.js src/renderer/bundle.js.map src/renderer/bundle.js.LICENSE.txt src/renderer/output.css",
"clear-assets": "rimraf dist/renderer/bundle.js dist/renderer/bundle.js.map dist/renderer/bundle.js.LICENSE.txt dist/renderer/output.css",
"lint": "npm run format:check && eslint src tests scripts eslint.config.js .eslintrc.js .babelrc.js babel.config.js jest.config.js playwright.config.ts postcss.config.js prettier.config.js tailwind.config.js webpack.config.js --cache --max-warnings 0 && npm run lint:md && npm run test:catalog && npm run changelog:validate",
"lint:md": "npm run lint:md:links && npm run lint:md:style",
"lint:md:links": "node scripts/lint-markdown-links.js",
Expand All @@ -34,18 +34,20 @@
"test:binary": "jest --config jest.config.js --testMatch=\"**/tests/unit/binary-detection.test.{js,ts}\" --verbose",
"test:patterns": "jest --config jest.config.js --testMatch=\"**/tests/**/*pattern*.test.{js,ts}\" --verbose",
"test:lint": "npm run test && npm run lint:tests",
"watch:css": "npx @tailwindcss/cli -i ./src/renderer/styles.css -o ./src/renderer/output.css --watch",
"build:css": "npx @tailwindcss/cli -i ./src/renderer/styles.css -o ./src/renderer/output.css",
"prewatch:css": "node scripts/ensure-build-dirs.js",
"watch:css": "npx @tailwindcss/cli -i ./src/renderer/styles.css -o ./dist/renderer/output.css --watch",
"prebuild:css": "node scripts/ensure-build-dirs.js",
"build:css": "npx @tailwindcss/cli -i ./src/renderer/styles.css -o ./dist/renderer/output.css",
"prepare": "husky install",
"sonar": "node scripts/sonar-scan.js",
"qa": "node scripts/index.js qa",
"preqa:screenshot": "npm run build:ts",
"preqa:screenshot": "npm run build:ts && npm run build:css && npm run build:webpack",
"qa:screenshot": "node scripts/capture-ui-screenshot.js",
"pree2e:playwright": "npm run build:ts && npm run build:css && npm run build:webpack",
"e2e:playwright": "playwright test -c playwright.config.ts",
"e2e:playwright:ci": "playwright test -c playwright.config.ts",
"e2e:playwright:headed": "playwright test -c playwright.config.ts --headed",
"predocs:screenshots": "npm run build:ts && npm run build:webpack",
"predocs:screenshots": "npm run build:ts && npm run build:css && npm run build:webpack",
"docs:screenshots": "node scripts/generate-doc-screenshots.js",
"security": "node scripts/index.js security",
"security:actions-freshness": "node scripts/audit-actions-freshness.js --report actions-freshness-report.md --json actions-freshness-report.json",
Expand Down Expand Up @@ -89,6 +91,7 @@
"files": [
"src/**/*",
"build/ts/**/*",
"dist/renderer/**/*",
"package.json",
"node_modules/**/*"
],
Expand Down
70 changes: 61 additions & 9 deletions scripts/capture-ui-screenshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const path = require('path');
const { chromium } = require('playwright');

const ROOT_DIR = path.join(__dirname, '..');
const RENDERER_DIR = path.join(ROOT_DIR, 'src', 'renderer');
const RENDERER_SOURCE_DIR = path.join(ROOT_DIR, 'src', 'renderer');
const RENDERER_BUILD_DIR = path.join(ROOT_DIR, 'dist', 'renderer');
const DEFAULT_SCREENSHOT_DIR = path.join('dist', 'qa', 'screenshots');
const SCREENSHOT_DIR = resolveOutputDirectory(process.env.UI_SCREENSHOT_DIR);
const PORT = Number(process.env.UI_SCREENSHOT_PORT || 4173);
Expand Down Expand Up @@ -44,6 +45,16 @@ const MIME_TYPES = {
'.svg': 'image/svg+xml',
};

const STATIC_FILE_ROUTES = new Map([
['/', path.join(RENDERER_SOURCE_DIR, 'index.html')],
['/index.html', path.join(RENDERER_SOURCE_DIR, 'index.html')],
['/icon.png', path.join(RENDERER_SOURCE_DIR, 'icon.png')],
['/dist/renderer/output.css', path.join(RENDERER_BUILD_DIR, 'output.css')],
['/dist/renderer/bundle.js', path.join(RENDERER_BUILD_DIR, 'bundle.js')],
['/dist/renderer/bundle.js.map', path.join(RENDERER_BUILD_DIR, 'bundle.js.map')],
['/dist/renderer/bundle.js.LICENSE.txt', path.join(RENDERER_BUILD_DIR, 'bundle.js.LICENSE.txt')],
]);

function ensureError(error) {
if (error instanceof Error) {
return error;
Expand Down Expand Up @@ -106,16 +117,16 @@ async function runStep(stepName, action) {
}

function resolveFilePath(requestUrl) {
const urlPath = decodeURIComponent(requestUrl.split('?')[0]);
const relativePath = urlPath === '/' ? 'index.html' : urlPath.replace(/^\/+/, '');
const absolutePath = path.resolve(RENDERER_DIR, relativePath);
const relativeToRoot = path.relative(RENDERER_DIR, absolutePath);
const rawPath = typeof requestUrl === 'string' ? requestUrl : '/';
let urlPath;

if (relativeToRoot.startsWith('..') || path.isAbsolute(relativeToRoot)) {
try {
urlPath = decodeURIComponent(rawPath.split('?')[0]);
} catch {
return null;
}

return absolutePath;
return STATIC_FILE_ROUTES.get(urlPath) ?? null;
}

function createStaticServer() {
Expand Down Expand Up @@ -516,6 +527,30 @@ async function setLocaleAndWait(page, locale) {
);
}

async function setCheckboxState(page, selector, shouldBeChecked) {
const checkbox = page.locator(selector).first();
await checkbox.waitFor({ state: 'visible', timeout: 10000 });

for (let attempt = 0; attempt < 3; attempt += 1) {
const currentState = await checkbox.isChecked();
if (currentState === shouldBeChecked) {
return;
}

if (shouldBeChecked) {
await checkbox.check();
} else {
await checkbox.uncheck();
}

await page.waitForTimeout(75);
}

throw new Error(
`Unable to set checkbox "${selector}" to ${shouldBeChecked ? 'checked' : 'unchecked'}`
);
}

async function captureLocaleScreenshots(page) {
await runStep('Wait for language selector', async () => {
await page.waitForSelector(UI_SELECTORS.languageSelector, { timeout: 10000 });
Expand Down Expand Up @@ -597,8 +632,25 @@ async function captureAppStateScreenshots(page) {
await runStep('Disable secret filtering in config tab', async () => {
await page.click(UI_SELECTORS.configTab);
await page.waitForSelector(UI_SELECTORS.secretScanningToggle, { timeout: 10000 });
await page.uncheck(UI_SELECTORS.secretScanningToggle);
await page.uncheck(UI_SELECTORS.suspiciousFilesToggle);
await setCheckboxState(page, UI_SELECTORS.secretScanningToggle, false);
await setCheckboxState(page, UI_SELECTORS.suspiciousFilesToggle, false);
await page.waitForFunction(
({ secretSelector, suspiciousSelector }) => {
const secretToggle = document.querySelector(secretSelector);
const suspiciousToggle = document.querySelector(suspiciousSelector);

return (
secretToggle instanceof HTMLInputElement &&
suspiciousToggle instanceof HTMLInputElement &&
!secretToggle.checked &&
!suspiciousToggle.checked
);
},
{
secretSelector: UI_SELECTORS.secretScanningToggle,
suspiciousSelector: UI_SELECTORS.suspiciousFilesToggle,
}
);
await page.getByRole('button', { name: /save config|saved/i }).click();
await page.waitForFunction(() => {
const configContent = localStorage.getItem('configContent') || '';
Expand Down
8 changes: 4 additions & 4 deletions scripts/clean-dev-assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ const { rimraf } = require('rimraf');

// Asset paths relative to project root
const assetPaths = [
'src/renderer/bundle.js',
'src/renderer/bundle.js.map',
'src/renderer/bundle.js.LICENSE.txt',
'src/renderer/output.css',
'dist/renderer/bundle.js',
'dist/renderer/bundle.js.map',
'dist/renderer/bundle.js.LICENSE.txt',
'dist/renderer/output.css',
];

async function cleanDevAssets() {
Expand Down
8 changes: 5 additions & 3 deletions scripts/ensure-build-dirs.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
/**
* Script to ensure build directories exist for webpack
* Script to ensure build directories exist for renderer outputs and TypeScript builds.
*/
const fs = require('fs');
const path = require('path');

// Define build directory paths
const buildDir = path.resolve(__dirname, '../build');
const rendererDir = path.resolve(buildDir, 'renderer');
const distDir = path.resolve(__dirname, '../dist');
const rendererOutputDir = path.resolve(distDir, 'renderer');

// Create directories if they don't exist
function ensureDirectoryExists(dirPath) {
Expand All @@ -18,6 +19,7 @@ function ensureDirectoryExists(dirPath) {

// Ensure all required directories exist
ensureDirectoryExists(buildDir);
ensureDirectoryExists(rendererDir);
ensureDirectoryExists(distDir);
ensureDirectoryExists(rendererOutputDir);

console.log('Build directories ready');
15 changes: 5 additions & 10 deletions scripts/lib/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,20 @@ async function start() {

try {
// Build CSS if it doesn't exist
const cssFile = path.join(utils.ROOT_DIR, 'src', 'renderer', 'output.css');
const cssFile = path.join(utils.ROOT_DIR, 'dist', 'renderer', 'output.css');
if (!fs.existsSync(cssFile)) {
log('CSS not found, building...', colors.yellow);
try {
// Try direct command execution first
const { execSync } = require('child_process');
log('Running tailwindcss directly...', colors.blue);
execSync('npx tailwindcss -i ./src/renderer/styles.css -o ./src/renderer/output.css', {
stdio: 'inherit',
cwd: utils.ROOT_DIR,
});
log('Running build:css script...', colors.blue);
utils.runNpmScript('build:css');
} catch (err) {
log(`Error running tailwindcss: ${err.message}`, colors.red);
log(`Error running build:css: ${err.message}`, colors.red);
throw err;
}
}

// Check if webpack output exists
const webpackOutput = path.join(utils.ROOT_DIR, 'src', 'renderer', 'bundle.js');
const webpackOutput = path.join(utils.ROOT_DIR, 'dist', 'renderer', 'bundle.js');
if (!fs.existsSync(webpackOutput)) {
log('Webpack bundle not found, building...', colors.yellow);
utils.runNpmScript('build:webpack');
Expand Down
8 changes: 1 addition & 7 deletions scripts/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,7 @@ async function setupHooks() {

// Clean functions
async function cleanBuildArtifacts() {
const pathsToRemove = [
path.join(ROOT_DIR, 'dist'),
path.join(ROOT_DIR, 'src', 'renderer', 'bundle.js'),
path.join(ROOT_DIR, 'src', 'renderer', 'bundle.js.map'),
path.join(ROOT_DIR, 'build', 'ts'),
path.join(ROOT_DIR, 'src', 'renderer', 'output.css'),
];
const pathsToRemove = [path.join(ROOT_DIR, 'dist'), path.join(ROOT_DIR, 'build', 'ts')];

console.log('Cleaning build artifacts...');

Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sonar.sources=src
sonar.sourceEncoding=UTF-8

# 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
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/styles.css

# Test directories (kept for coverage mapping, excluded from issue noise)
sonar.tests=tests,src/__tests__
Expand Down
4 changes: 2 additions & 2 deletions src/renderer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AI Code Fusion</title>
<link rel="stylesheet" href="output.css" />
<link rel="stylesheet" href="../../dist/renderer/output.css" />
<script>
// Apply dark mode immediately to prevent flash of light theme
const appWindow = globalThis;
Expand All @@ -25,6 +25,6 @@
class="h-screen overflow-hidden bg-gray-100 dark:bg-gray-900 transition-colors duration-200"
>
<div id="app" class="h-full"></div>
<script src="bundle.js"></script>
<script src="../../dist/renderer/bundle.js"></script>
</body>
</html>
41 changes: 0 additions & 41 deletions src/renderer/index.js.LICENSE.txt

This file was deleted.

10 changes: 5 additions & 5 deletions webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
const path = require('path');

// Source and destination paths
const srcPath = path.resolve(__dirname, 'src/renderer');
const entryFile = path.resolve(srcPath, 'index.tsx');
const rendererSourcePath = path.resolve(__dirname, 'src/renderer');
const rendererBuildPath = path.resolve(__dirname, 'dist/renderer');
const entryFile = path.resolve(rendererSourcePath, 'index.tsx');

module.exports = {
entry: entryFile,
output: {
filename: 'bundle.js', // Output to bundle.js to avoid webpack processing its own output
path: srcPath, // Same directory for simplicity
filename: 'bundle.js',
path: rendererBuildPath,
},
// Increase the node options to allow more stack space
node: {
Expand Down
Loading