googleapis / googleapis/release-please
[BUG] fails to parse commits with nested parentheses
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 588
- Avg merge
- 12h 16m
- Merged PRs (30d)
- 7
Description
### Description
Conventional commit parsing in `release-please` can misbehave or fail when a commit or it's body contains nested parentheses, such as code references or function calls (e.g., `Foo.Bar(baz(abc))`). This issue is particularly notable in GitHub squash merge commits where nested parentheses are nested inside squashed comments or split commits in the message body.
### Test Cases
Here are the test cases that demonstrate the desired behavior:
```typescript
it('handles commits with nested parentheses in body', async () => {
const commits = [
buildMockCommit(
'feat: something\n\nFoo.Bar(baz(abc)). Some trailing text.'
),
];
const conventionalCommits = parseConventionalCommits(commits);
expect(conventionalCommits).lengthOf(1);
expect(conventionalCommits[0].type).to.equal('feat');
});
it('handles a GitHub squash merge commit with nested parentheses inside squashed comments in the body', async () => {
const squashCommitMessage =
'feat(scope): some message (#123)\n\n' +
'* refactor(subscope): first squashed change\n\n' +
'Some details here.\n\n' +
'* refactor(subscope): second squashed change\n\n' +
'Foo.Bar(baz(abc)). More details.';
const commits = [buildMockCommit(squashCommitMessage)];
const conventionalCommits = parseConventionalCommits(commits);
expect(conventionalCommits).lengthOf(1);
expect(conventionalCommits[0].type).to.equal('feat');
expect(conventionalCommits[0].scope).to.equal('scope');
});
it('handles a squash merge with split commits that contain a nested parenthesis commit', async () => {
const squashSplitMessage =
'feat(scope): some message (#123)\n\n' +
'refactor(subscope): first squashed change\n\n' +
'Some details here.\n\n' +
'refactor(subscope): second squashed change\n\n' +
'Foo.Bar(baz(abc)). More details.';
const commits = [buildMockCommit(squashSplitMessage)];
const conventionalCommits = parseConventionalCommits(commits);
expect(conventionalCommits).lengthOf(3);
expect(conventionalCommits[0].type).to.equal('feat');
expect(conventionalCommits[1].type).to.equal('refactor');
expect(conventionalCommits[2].type).to.equal('refactor');
});
```
Contributor guide
Research direction
Start at the parseConventionalCommits entry point and inspect the existing tests that use buildMockCommit. Add the three supplied cases for nested parentheses in regular and squash-merge commit bodies, then run the parser test suite and confirm the expected commit counts, types, and scope are preserved.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- release, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100