Skip to content

release v0.10.1

release v0.10.1 #180

Triggered via push August 11, 2025 09:25
Status Failure
Total duration 22s
Artifacts

test.yml

on: push
Fit to window
Zoom out
Zoom in

Annotations

4 errors
test
Process completed with exit code 1.
tests/gpt5-models.test.js > GPT-5 Model Integration > Semantic Commit Messages > should have increased max_tokens for longer semantic messages: tests/gpt5-models.test.js#L114
AssertionError: expected '#!/usr/bin/env node\nimport { exec as…' to contain 'max_tokens: 100' - Expected + Received - max_tokens: 100 + #!/usr/bin/env node + import { exec as originalExec, execSync } from 'child_process' + import fs from 'fs' + import os from 'os' + import path from 'path' + import process from 'process' + import { promisify } from 'util' + + import { program } from 'commander' + import OpenAI from 'openai' + import prompts from 'prompts' + + import { sanitizeCommitMessage } from './utils/sanitizeCommitMessage.js' + + let openai + let model = 'gpt-5-mini' // Default model + let language = 'English' // Default language + let apiKey = null // Store API key from config + // Define prefixState using closure for safer state management + const prefixState = (() => { + let enabled = true // Default is enabled + return { + isEnabled: () => enabled, + setEnabled: (value) => { + enabled = value + return value + }, + } + })() + + const CONFIG_FILE = path.join(os.homedir(), '.git-gpt-commit-config.json') + + // Function to save config to file + function saveConfig(config) { + try { + // Load existing config first + let existingConfig = {} + if (fs.existsSync(CONFIG_FILE)) { + existingConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) + } + // Merge with new config + const updatedConfig = { ...existingConfig, ...config } + fs.writeFileSync(CONFIG_FILE, JSON.stringify(updatedConfig, null, 2)) + } catch (error) { + console.error('Error saving configuration:', error) + } + } + + // Function to load config from file + function loadConfig() { + try { + if (fs.existsSync(CONFIG_FILE)) { + const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) + if (config.model) { + model = config.model + } + if (config.language) { + language = config.language + } + if (config.prefixEnabled !== undefined) { + prefixState.setEnabled(config.prefixEnabled) + } + if (config.apiKey) { + apiKey = config.apiKey + } + } + } catch (error) { + console.error('Error loading configuration:', error) + // Continue with default model if there's an error + } + } + + // Mask API key for display + function maskApiKey(key) { + if (!key) return 'none' + // Show only first 4 and last 4 characters + return `${key.substring(0, 4)}...${key.substring(key.length - 4)}` + } + + export async function getGitSummary() { + try { + // If no API key in config, try to load from .env + if (!apiKey) { + const dotenv = await import('dotenv') + const envPath = path.join(process.cwd(), '.env') + dotenv.config({ path: envPath }) + } + + // Use API key from config if available, otherwise use from .env + const openaiApiKey = apiKey || process.env.OPENAI_API_KEY + + if (!openaiApiKey) { + console.error( + 'No OpenAI API key found. Please set it using "git gpt open-api-key add".', + ) + process.exit(1) + } + + openai = new OpenAI({ apiKey: openaiApiKey }) + + const exec = promisify(originalExec) + const { stdout } = await exec( + "git diff --cached -- . ':(exclude)*lock.json' ':(exclude)*lock.yaml'", + ) + const summary = stdout.trim() + if (summary.length === 0) { + return null + } + + return summary + } catch (error) { + console.error('Error while summarizing Git changes:', error) + process.exit(1) + } + } + + const gptCommit = async () => { + const gitSummary = await getGitSummary() + if (!gitSummary) { + console.log('No changes to commit. Commit canceled.') + process.exit(0) + } + + const messages = [ + { + role: 'system', + content: + 'You are an expert Git commit message writer. Generate semantic, meaningful commit messages that explain the PURPOSE and IMPACT of changes, not just what changed. ' + + 'Focus on WHY the change was made and its benefits. Write in ' + + language + + '. Kee
tests/gpt5-models.test.js > GPT-5 Model Integration > Model Configuration > should include all GPT-5 series models in the selection list: tests/gpt5-models.test.js#L62
AssertionError: expected '#!/usr/bin/env node\nimport { exec as…' to contain 'gpt-4o-mini (Previous Gen)' - Expected + Received - gpt-4o-mini (Previous Gen) + #!/usr/bin/env node + import { exec as originalExec, execSync } from 'child_process' + import fs from 'fs' + import os from 'os' + import path from 'path' + import process from 'process' + import { promisify } from 'util' + + import { program } from 'commander' + import OpenAI from 'openai' + import prompts from 'prompts' + + import { sanitizeCommitMessage } from './utils/sanitizeCommitMessage.js' + + let openai + let model = 'gpt-5-mini' // Default model + let language = 'English' // Default language + let apiKey = null // Store API key from config + // Define prefixState using closure for safer state management + const prefixState = (() => { + let enabled = true // Default is enabled + return { + isEnabled: () => enabled, + setEnabled: (value) => { + enabled = value + return value + }, + } + })() + + const CONFIG_FILE = path.join(os.homedir(), '.git-gpt-commit-config.json') + + // Function to save config to file + function saveConfig(config) { + try { + // Load existing config first + let existingConfig = {} + if (fs.existsSync(CONFIG_FILE)) { + existingConfig = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) + } + // Merge with new config + const updatedConfig = { ...existingConfig, ...config } + fs.writeFileSync(CONFIG_FILE, JSON.stringify(updatedConfig, null, 2)) + } catch (error) { + console.error('Error saving configuration:', error) + } + } + + // Function to load config from file + function loadConfig() { + try { + if (fs.existsSync(CONFIG_FILE)) { + const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')) + if (config.model) { + model = config.model + } + if (config.language) { + language = config.language + } + if (config.prefixEnabled !== undefined) { + prefixState.setEnabled(config.prefixEnabled) + } + if (config.apiKey) { + apiKey = config.apiKey + } + } + } catch (error) { + console.error('Error loading configuration:', error) + // Continue with default model if there's an error + } + } + + // Mask API key for display + function maskApiKey(key) { + if (!key) return 'none' + // Show only first 4 and last 4 characters + return `${key.substring(0, 4)}...${key.substring(key.length - 4)}` + } + + export async function getGitSummary() { + try { + // If no API key in config, try to load from .env + if (!apiKey) { + const dotenv = await import('dotenv') + const envPath = path.join(process.cwd(), '.env') + dotenv.config({ path: envPath }) + } + + // Use API key from config if available, otherwise use from .env + const openaiApiKey = apiKey || process.env.OPENAI_API_KEY + + if (!openaiApiKey) { + console.error( + 'No OpenAI API key found. Please set it using "git gpt open-api-key add".', + ) + process.exit(1) + } + + openai = new OpenAI({ apiKey: openaiApiKey }) + + const exec = promisify(originalExec) + const { stdout } = await exec( + "git diff --cached -- . ':(exclude)*lock.json' ':(exclude)*lock.yaml'", + ) + const summary = stdout.trim() + if (summary.length === 0) { + return null + } + + return summary + } catch (error) { + console.error('Error while summarizing Git changes:', error) + process.exit(1) + } + } + + const gptCommit = async () => { + const gitSummary = await getGitSummary() + if (!gitSummary) { + console.log('No changes to commit. Commit canceled.') + process.exit(0) + } + + const messages = [ + { + role: 'system', + content: + 'You are an expert Git commit message writer. Generate semantic, meaningful commit messages that explain the PURPOSE and IMPACT of changes, not just what changed. ' + + 'Focus on WHY the change was made and its benefits. Write in ' + + langu