UNPKG

scai

Version:

> **AI-powered CLI for local code analysis, commit message suggestions, and natural-language queries.** 100% local, private, GDPR-friendly, made in Denmark/EU with ❤️.

135 lines (134 loc) 4.98 kB
// src/commands/ChangeLogUpdateCmd.ts import { execSync } from 'child_process'; import fs from 'fs/promises'; import path from 'path'; import { runModulePipeline } from '../pipeline/runModulePipeline.js'; import { changelogModule } from '../pipeline/modules/changeLogModule.js'; import { askChangelogApproval } from '../utils/changeLogPrompt.js'; import { openTextEditor } from '../utils/editor.js'; export async function handleStandaloneChangelogUpdate() { let entry = await generateChangelogEntry(); if (!entry) { console.log('⚠️ No significant changes found.'); return; } while (true) { const userChoice = await askChangelogApproval(entry); if (userChoice === 'yes') { const path = await updateChangelogFile(entry); console.log(`✅ CHANGELOG.md updated: ${path}`); break; } else if (userChoice === 'redo') { console.log('🔁 Regenerating changelog...'); entry = await generateChangelogEntry(); if (!entry) { console.log('⚠️ Could not regenerate entry. Exiting.'); break; } } else { console.log('❌ Skipped changelog update.'); break; } } } export async function generateChangelogEntry(currentCommitMsg) { try { const lastTag = getLastGitTag(); if (!lastTag) { console.log("⚠️ No previous git tag found. Using all commits."); } let commits = lastTag ? getCommitsSinceTag(lastTag) : execSync('git log --pretty=format:%s', { encoding: 'utf-8' }).trim(); if (currentCommitMsg) { commits = commits ? `${commits}\n${currentCommitMsg}` : currentCommitMsg; } console.log('Number of commits:', commits.split('\n').length); if (!commits) { console.log("⚠️ No commits found since last release."); return null; } // --- ModuleIO usage --- const result = await runModulePipeline([changelogModule], { query: 'generate changelog entry', content: commits }); const output = result?.data ? typeof result.data === 'string' ? result.data.trim() : JSON.stringify(result.data, null, 2) : null; if (!output || output === 'NO UPDATE') { console.log('⚠️ No significant changes detected for changelog.'); return null; } return output; } catch (err) { console.error("❌ Failed to generate changelog entry:", err.message); return null; } } function getLastGitTag() { try { return execSync('git describe --tags --abbrev=0', { encoding: 'utf-8' }).trim(); } catch { return null; } } function getCommitsSinceTag(tag) { return execSync(`git log ${tag}..HEAD --pretty=format:%s`, { encoding: 'utf-8' }).trim(); } export async function updateChangelogFile(entry) { const root = execSync("git rev-parse --show-toplevel", { encoding: "utf-8" }).trim(); const changelogPath = path.join(root, "CHANGELOG.md"); let existing = ''; try { existing = await fs.readFile(changelogPath, 'utf-8'); } catch { console.log("📄 Creating new CHANGELOG.md"); } const today = new Date().toISOString().split("T")[0]; const newEntry = `\n\n## ${today}\n\n${entry.trim()}`; await fs.writeFile(changelogPath, existing + newEntry, 'utf-8'); return changelogPath; } export async function handleChangelogWithCommitMessage(commitMsg) { let entryFinalized = false; let changelogEntry = await generateChangelogEntry(commitMsg); if (!changelogEntry) { console.log("ℹ️ No changelog entry generated."); return; } while (!entryFinalized) { const userChoice = await askChangelogApproval(changelogEntry); if (userChoice === 'yes') { const changelogPath = await updateChangelogFile(changelogEntry); execSync(`git add "${changelogPath}"`); console.log("✅ CHANGELOG.md staged."); entryFinalized = true; } else if (userChoice === 'redo') { console.log("🔁 Regenerating changelog entry..."); changelogEntry = await generateChangelogEntry(commitMsg); if (!changelogEntry) { console.log('⚠️ Could not regenerate entry. Exiting.'); break; } } else if (userChoice === 'edit') { changelogEntry = await openTextEditor(changelogEntry, 'scai-changelog.txt'); if (!changelogEntry) { console.log('⚠️ No changes made to changelog. Returning to prompt.'); } } else { console.log("❌ Skipped changelog update."); entryFinalized = true; } } }