(records: CommitRecord[])
| 535 | // under squash-merge, where one PR == one commit); a recurrence with a divergent |
| 536 | // `type`/`breaking` keeps the first entry but warns so the conflict is visible. |
| 537 | function parseCommits(records: CommitRecord[]): ParsedCommit[] { |
| 538 | const parsed: ParsedCommit[] = [] |
| 539 | const seen = new Map<number, ParsedCommit>() |
| 540 | for (const { sha, author, message } of records) { |
| 541 | const firstLine = message.split('\n')[0] ?? '' |
| 542 | const prNumber = extractPRNumber(firstLine) |
| 543 | const { type, breaking, description } = parseCommit(message) |
| 544 | const commit: ParsedCommit = { |
| 545 | sha, |
| 546 | author, |
| 547 | prNumber, |
| 548 | type, |
| 549 | breaking, |
| 550 | description |
| 551 | } |
| 552 | if (prNumber === null) { |
| 553 | parsed.push(commit) |
| 554 | continue |
| 555 | } |
| 556 | const existing = seen.get(prNumber) |
| 557 | if (existing === undefined) { |
| 558 | seen.set(prNumber, commit) |
| 559 | parsed.push(commit) |
| 560 | } else if (existing.type !== type || existing.breaking !== breaking) { |
| 561 | // A `(#N)` recurring with a divergent type/breaking (rare under |
| 562 | // squash-merge). Keep the first-seen (authoritative) entry, but warn. |
| 563 | console.warn( |
| 564 | `commit-graph: PR #${prNumber} recurs with a conflicting type/breaking; keeping the first-seen one.` |
| 565 | ) |
| 566 | } |
| 567 | } |
| 568 | return parsed |
| 569 | } |
| 570 | |
| 571 | // Project a fetched PR into a PR-sourced change: `type`/`breaking` from the |
| 572 | // squash commit (via `byNumber`), `description` from the PR title as prose (its |
no test coverage detected