Skip to content

Commit

Permalink
fix(#28) Add support for prepending reference to commit messages
Browse files Browse the repository at this point in the history
  • Loading branch information
negoziator authored Oct 11, 2023
1 parent 233707b commit 0cbb5b4
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 0 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,20 @@ Automatically confirm the generated commit message without prompting the user.
aicommit config set auto-confirm=true
```
#### prepend-reference
Default: `false`
Prepends issue reference from branch name to commit message.
branch name: `feature/abc-123-branch-name`
commit message: `ABC-123: <generated commit message>`
```sh
aicommit config set prepend-reference=true
```
## How it works
This CLI tool runs `git diff` to grab all your latest code changes, sends them to OpenAI's GPT-3, then returns the AI
Expand Down
13 changes: 13 additions & 0 deletions src/commands/aicommit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,19 @@ export default async (
message = selected as string;
}

if (config['prepend-reference']) {
// Get the current branch name
const { stdout} = await execa('git', ['branch', '--show-current']);

// Get reference from branch name
const taskNumber = stdout.match(/([a-zA-Z])+-([0-9]+)/)?.[0];

if (taskNumber?.length) {
// Prepend reference to commit message
message = `${taskNumber?.toUpperCase()}: ${message}`;
}
}

await execa('git', ['commit', '-m', message, ...rawArgv]);

outro(`${green('✔')} Successfully committed!`);
Expand Down
12 changes: 12 additions & 0 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,18 @@ const configParsers = {
parseAssert('auto-confirm', /^(?:true|false)$/.test(autoConfirm), 'Must be a boolean');
return autoConfirm === 'true';
},
'prepend-reference'(prependReference?: string | boolean) {
if (!prependReference) {
return false;
}

if (typeof prependReference === 'boolean') {
return prependReference;
}

parseAssert('prepend-reference', /^(?:true|false)$/.test(prependReference), 'Must be a boolean');
return prependReference === 'true';
},
} as const;

type ConfigKeys = keyof typeof configParsers;
Expand Down
62 changes: 62 additions & 0 deletions tests/specs/cli/commits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,68 @@ export default testSuite(({ describe }) => {
await fixture.rm();
});

test('Generates commit message with prepended reference from branch name', async () => {

const { fixture, aicommit } = await createFixture(files);
const git = await createGit(fixture.path);

await git('checkout', ['-b', 'feature/abc-123-some-feature']);
await git('add', ['data.json']);

const autoConfirm = 'prepend-reference=true'
await aicommit(['config', 'set', autoConfirm])

const committing = aicommit();
committing.stdout!.on('data', (buffer: Buffer) => {
const stdout = buffer.toString();
if (stdout.match('└')) {
committing.stdin!.write('y');
committing.stdin!.end();
}
});

await committing;

const { stdout: commitMessage } = await git('log', ['--pretty=format:%s']);
console.log({
commitMessage,
length: commitMessage.length,
});
expect(commitMessage.startsWith('ABC-123: ')).toBe(true);
await fixture.rm();
});

test('Generates commit message will no prepend if no valid reference', async () => {

const { fixture, aicommit } = await createFixture(files);
const git = await createGit(fixture.path);

await git('checkout', ['-b', 'feature/some-feature']);
await git('add', ['data.json']);

const autoConfirm = 'prepend-reference=true'
await aicommit(['config', 'set', autoConfirm])

const committing = aicommit();
committing.stdout!.on('data', (buffer: Buffer) => {
const stdout = buffer.toString();
if (stdout.match('└')) {
committing.stdin!.write('y');
committing.stdin!.end();
}
});

await committing;

const { stdout: commitMessage } = await git('log', ['--pretty=format:%s']);
console.log({
commitMessage,
length: commitMessage.length,
});
expect(commitMessage.length).toBeLessThanOrEqual(50);
await fixture.rm();
});

test('Generated commit message must be under 50 characters', async () => {
const { fixture, aicommit } = await createFixture({
...files,
Expand Down
24 changes: 24 additions & 0 deletions tests/specs/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,30 @@ export default testSuite(({ describe }) => {
})
})

await describe('prepend-reference', ({ test }) => {
test('must be a boolean', async () => {
const { stderr } = await aicommit(['config', 'set', 'prepend-reference=abc'], {
reject: false
})

expect(stderr).toMatch('Must be a boolean')
})

test('updates config', async () => {
const defaultConfig = await aicommit(['config', 'get', 'prepend-reference'])
expect(defaultConfig.stdout).toBe('prepend-reference=false')

const autoConfirm = 'prepend-reference=true'
await aicommit(['config', 'set', autoConfirm])

const configFile = await fs.readFile(configPath, 'utf8')
expect(configFile).toMatch(autoConfirm)

const get = await aicommit(['config', 'get', 'prepend-reference'])
expect(get.stdout).toBe(autoConfirm)
})
})

await test('set config file', async () => {
await aicommit(['config', 'set', openAiToken])

Expand Down

0 comments on commit 0cbb5b4

Please sign in to comment.