fix(changelog): validate Claude CLI exists before generation (#1305)
* fix(changelog): validate Claude CLI exists before generation
When Claude CLI is not found by the detection logic, the code was
falling back to the string 'claude' and attempting to execute it,
which fails with FileNotFoundError on systems where Claude CLI is
not in PATH.
Now uses getToolInfo('claude') to properly check if Claude CLI
was actually found before attempting changelog generation, and
provides a clear error message with install instructions.
Fixes #1302
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* refactor(changelog): extract prerequisite checks to helper method
Extract duplicated validation logic into ensurePrerequisites() method
to follow DRY principle. Both getGenerator() and getVersionSuggester()
now use this centralized helper for auto-build source and Claude CLI
validation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(tests): update claude-integration-handler tests for PtyManager.writeToPty
The implementation was refactored to use PtyManager.writeToPty() instead
of terminal.pty.write() directly. Update tests to mock the new method.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* 2.7.4 release stable
* fix(test): update mock profile manager and relax audit level
1. subprocess-spawn.test.ts: Fix mock profile manager to match ClaudeProfile interface
- Use correct properties: id, name, isDefault, oauthToken (not profileId/profileName)
- Add missing methods: getActiveProfileToken(), getProfileToken(), getProfile()
- Fixes Windows CI test failure where tasks weren't being tracked
2. pre-commit hook: Change npm audit from high to critical level
- Known tar vulnerability (CVE-2026-23745) in electron-builder cannot be fixed
- electron-builder requires tar@^6.x which is vulnerable
- This is a build dependency, not runtime code
- Will re-enable high level when electron-builder releases tar@7.x support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: package runtime deps and validate pydantic_core (#1336)
* fix: bundle runtime deps for packaged app
* fix: verify pydantic_core binary in bundled python
* fix: bundle minimatch by using esm import
* chore: throw on command failures in packager
* chore: drop redundant PATH filter in packager
* Use shared platform helper for packager
* Use platform helper in resolvePlatforms
* Harden packaging helpers
---------
Co-authored-by: StillKnotKnown <stillknotknown@users.noreply.github.com>
* fix: add shell: true and argument sanitization for Windows packaging (#1340)
On Windows, spawnSync cannot execute .cmd files directly without a shell
context. This adds shell: isWindows() to the spawnSync options in
runCommand() to properly execute electron-vite.cmd and electron-builder.cmd
during packaging.
Additionally, adds argument validation to prevent potential command injection
via shell metacharacters when shell: true is used on Windows. When using
shell: true, cmd.exe interprets certain characters (& | > < ^ % ; $ $`) as
special operators, which could enable command injection if present in user-
controlled arguments.
The validateArgs() function checks for these metacharacters on Windows and
throws an error if any are found, following the same security pattern used
in apps/frontend/src/main/ipc-handlers/mcp-handlers.ts.
This follows the existing pattern used throughout the codebase for Windows
.cmd file execution (env-utils.ts, mcp-handlers.ts).
Fixes ACS-365
Co-authored-by: StillKnotKnown <stillknotknown@users.noreply.github.com>
* fix: Windows CLI detection and version selection UX improvements (#1341)
* fix: Windows CLI detection and version selection UX improvements
- Add fallback to default npm global path (%APPDATA%\npm) when npm.cmd
is not in PATH (happens when packaged app launches from GUI)
- Apply fallback to both sync and async versions of getNpmGlobalPrefix()
- Update version selection warning dialogs with clear terminal messaging
- Change button text to "Open Terminal & Switch/Update" for clarity
- Add i18n translations for terminal note (en/fr)
Fixes Claude Code CLI not being detected in packaged Windows builds.
Improves UX by clearly indicating terminal will open for version changes.
* fix: use APPDATA env var for Windows npm path fallback
Use process.env.APPDATA instead of hardcoded 'AppData\Roaming' path
for better robustness on Windows systems with custom or localized
AppData locations. Provides fallback to hardcoded path for minimal
environments.
Addresses feedback from PR review.
* refactor: use established APPDATA pattern from platform/paths.ts
Update Windows npm fallback to use the concise pattern
`process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming')`
which matches the established pattern in platform/paths.ts (lines 224, 277).
This improves codebase consistency and is more concise than the
previous ternary expression.
Addresses MEDIUM findings from Auto Claude PR Review.
* refactor: use platform module helpers and extract npm path constant
- Use getNpmCommand() from platform module instead of inline ternary
- Extract Windows npm fallback path as WINDOWS_NPM_FALLBACK_PATH constant
This eliminates code duplication and improves consistency with the
codebase's platform abstraction layer.
Addresses LOW findings from Auto Claude PR Review:
- [e3eaee8f94e5] Duplicated Windows fallback path constant
- [7ae39c782e02] Could use getNpmCommand() from platform module
---------
Co-authored-by: StillKnotKnown <stillknotknown@users.noreply.github.com>
* fix: address PR review feedback for changelog CLI validation
- Fix error message redundancy by using claudeInfo.message directly
instead of appending it to a hardcoded message
- Use resolved Claude CLI path from getToolInfo() instead of stale
cached path from constructor, ensuring freshly validated path is
passed to generator and version suggester
- Add !claudeInfo.path check for additional safety
Addresses CodeRabbit and Auto Claude PR review feedback.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Test User <test@example.com>
Co-authored-by: StillKnotKnown <192589389+StillKnotKnown@users.noreply.github.com>
Co-authored-by: StillKnotKnown <stillknotknown@users.noreply.github.com>
Co-authored-by: Andy <119136210+AndyMik90@users.noreply.github.com>
This commit is contained in:
@@ -8,7 +8,7 @@ import { app } from 'electron';
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
import { AUTO_BUILD_PATHS, DEFAULT_CHANGELOG_PATH } from '../../shared/constants';
|
||||
import { getToolPath } from '../cli-tool-manager';
|
||||
import { getToolPath, getToolInfo } from '../cli-tool-manager';
|
||||
import type {
|
||||
ChangelogTask,
|
||||
TaskSpecContent,
|
||||
@@ -175,26 +175,40 @@ export class ChangelogService extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure prerequisites are met for changelog generation
|
||||
* Validates auto-build source path and Claude CLI availability
|
||||
* Returns the resolved Claude CLI path to ensure we use the freshly validated path
|
||||
*/
|
||||
private ensurePrerequisites(): { autoBuildSource: string; claudePath: string } {
|
||||
const autoBuildSource = this.getAutoBuildSourcePath();
|
||||
if (!autoBuildSource) {
|
||||
throw new Error('Auto-build source path not found');
|
||||
}
|
||||
|
||||
const claudeInfo = getToolInfo('claude');
|
||||
if (!claudeInfo.found || !claudeInfo.path) {
|
||||
// Use claudeInfo.message directly to avoid redundant text
|
||||
throw new Error(claudeInfo.message || 'Claude CLI not found. Install from https://claude.ai/download');
|
||||
}
|
||||
|
||||
// Update cached path with freshly resolved value
|
||||
this.claudePath = claudeInfo.path;
|
||||
return { autoBuildSource, claudePath: claudeInfo.path };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create the generator instance
|
||||
*/
|
||||
private getGenerator(): ChangelogGenerator {
|
||||
if (!this.generator) {
|
||||
const autoBuildSource = this.getAutoBuildSourcePath();
|
||||
if (!autoBuildSource) {
|
||||
throw new Error('Auto-build source path not found');
|
||||
}
|
||||
|
||||
// Verify claude CLI is available
|
||||
if (this.claudePath !== 'claude' && !existsSync(this.claudePath)) {
|
||||
throw new Error(`Claude CLI not found. Please ensure Claude Code is installed. Looked for: ${this.claudePath}`);
|
||||
}
|
||||
const { autoBuildSource, claudePath } = this.ensurePrerequisites();
|
||||
|
||||
const autoBuildEnv = this.loadAutoBuildEnv();
|
||||
|
||||
this.generator = new ChangelogGenerator(
|
||||
this.pythonPath,
|
||||
this.claudePath,
|
||||
claudePath,
|
||||
autoBuildSource,
|
||||
autoBuildEnv,
|
||||
this.isDebugEnabled()
|
||||
@@ -226,19 +240,11 @@ export class ChangelogService extends EventEmitter {
|
||||
*/
|
||||
private getVersionSuggester(): VersionSuggester {
|
||||
if (!this.versionSuggester) {
|
||||
const autoBuildSource = this.getAutoBuildSourcePath();
|
||||
if (!autoBuildSource) {
|
||||
throw new Error('Auto-build source path not found');
|
||||
}
|
||||
|
||||
// Verify claude CLI is available
|
||||
if (this.claudePath !== 'claude' && !existsSync(this.claudePath)) {
|
||||
throw new Error(`Claude CLI not found. Please ensure Claude Code is installed. Looked for: ${this.claudePath}`);
|
||||
}
|
||||
const { autoBuildSource, claudePath } = this.ensurePrerequisites();
|
||||
|
||||
this.versionSuggester = new VersionSuggester(
|
||||
this.pythonPath,
|
||||
this.claudePath,
|
||||
claudePath,
|
||||
autoBuildSource,
|
||||
this.isDebugEnabled()
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user