feat: git hook (#95)

This commit is contained in:
hiroki osame
2023-02-21 08:08:44 -05:00
committed by GitHub
parent 0d3f35c135
commit 0b80a0031e
7 changed files with 191 additions and 32 deletions

View File

@@ -0,0 +1,65 @@
import fs from 'fs/promises';
import {
intro, outro, spinner,
} from '@clack/prompts';
import {
black, green, red, bgCyan,
} from 'kolorist';
import { getStagedDiff } from './utils/git.js';
import { getConfig } from './utils/config.js';
import { generateCommitMessage } from './utils/openai.js';
const [messageFilePath, commitSource] = process.argv.slice(2);
(async () => {
if (!messageFilePath) {
throw new Error('Commit message file path is missing. This file should be called from the "prepare-commit-msg" git hook');
}
// If a commit message is passed in, ignore
if (commitSource) {
return;
}
// All staged files can be ignored by our filter
const staged = await getStagedDiff();
if (!staged) {
return;
}
intro(bgCyan(black(' aicommits ')));
const { OPENAI_KEY, generate } = await getConfig();
if (!OPENAI_KEY) {
throw new Error('Please set your OpenAI API key in ~/.aicommits');
}
const s = spinner();
s.start('The AI is analyzing your changes');
const messages = await generateCommitMessage(
OPENAI_KEY,
staged!.diff,
generate || 1,
);
s.stop('Changes analyzed');
const hasMultipleMessages = messages.length > 1;
let instructions = `# 🤖 AI generated commit${hasMultipleMessages ? 's' : ''}\n`;
if (hasMultipleMessages) {
instructions += '# Select one of the following messages by uncommeting:\n';
instructions += `\n${messages.map(message => `# ${message}`).join('\n')}`;
} else {
instructions += '# Edit the message below and commit:\n';
instructions += `\n${messages[0]}\n`;
}
await fs.appendFile(
messageFilePath,
instructions,
);
outro(`${green('✔')} Saved commit message!`);
})().catch((error) => {
outro(`${red('✖')} ${error.message}`);
process.exit(1); // eslint-disable-line unicorn/no-process-exit
});