Skip to content

Conversation

@jluque0101
Copy link

@jluque0101 jluque0101 commented Nov 4, 2025

Problem Statement

The auto-changelog tool in MetaMask Mobile CI was creating duplicate changelog entries when running multiple times on the same release branch. Direct commits without PR numbers (e.g., "Update Attributions", "Bump version to X.Y.Z") were being included and re-added on each workflow run.

Why this matters:

  • They cause noise and duplication in user-facing changelogs
  • The idempotency mechanism relies on PR numbers to track logged changes

Solution

Implements a strict filter that completely excludes commits without PR numbers from changelog generation.

Key Changes

1. Filtered Commit Processing (src/get-new-changes.ts):

  • Changed filter from !prNumber || !loggedPrNumbers.includes(prNumber)
  • To: prNumber && !loggedPrNumbers.includes(prNumber)
  • Now only commits with PR numbers are processed
  • Direct commits are silently excluded, preventing duplication

2. Code Cleanup:

  • Removed redundant if (prNumber) check in map function (guaranteed by filter)
  • Added type assertion (as string) for TypeScript template literal requirements
  • Respects @typescript-eslint/no-non-null-assertion rule

3. TypeScript Compatibility:

  • Replaced assert.ok() with explicit if (!subject) throw Error() pattern
  • Removed unnecessary assert import
  • Fixes TS2775 errors about assertion signatures

Correctness Guarantees

  • 490+ lines of test coverage verifying:
    • Direct commits are excluded
    • PR-based commits are included
    • Idempotency maintained across multiple runs
  • Backward compatible with existing changelogs
  • Production-validated in MetaMask Mobile

Test Validation ✅

Test Repository: consensys-test/metamask-extension-test

Test Branch: release/99.0.0

Test Commits:

  1. feat: Add notification system (#4) - PR merge (has PR number)
  2. chore: Update Attributions - Direct commit (no PR number)
  3. fix: Emergency hotfix for critical bug - Direct commit (no PR number)

Generated Changelog Result:

## [99.0.0]

### Added

- feat: Add notification system (#4)

Verification:

  • ✅ Includes commits from merged PRs (with PR numbers)
  • ✅ Filters out direct commits (without PR numbers)
  • ✅ Solves idempotency - no re-adding on subsequent runs

Workflow: Using github-tools@chore/test-auto-changelog with this branch fix/INFRA-3081-filter-commits

Related Issues

Fixes INFRA-3081

…otency

- Modified filter to require PR numbers for changelog inclusion
- Added comprehensive test coverage
- Prevents duplicate changelog entries on repeated workflow runs
@Qbandev Qbandev requested a review from Copilot November 4, 2025 16:11
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR modifies the filtering logic for commits to exclude commits without PR numbers from the changelog generation. The key change converts the filter condition from including commits with missing or unlogged PR numbers (!prNumber || !loggedPrNumbers.includes(prNumber)) to only including commits that have a PR number and are not already logged (prNumber && !loggedPrNumbers.includes(prNumber)).

  • Changed filter logic to exclude commits without PR numbers from changelog entries
  • Added comprehensive test suite covering the new filtering behavior and edge cases

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/get-new-changes.ts Changed filter condition to require PR numbers and exclude direct commits
src/get-new-changes.test.ts Added comprehensive test suite covering filtering, idempotency, and real-world scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The filter at line 212 guarantees that prNumber is truthy,
making the subsequent if (prNumber) check redundant.
This simplifies the code while maintaining the same behavior.
@Qbandev Qbandev requested a review from Copilot November 5, 2025 12:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Qbandev Qbandev requested a review from Copilot November 5, 2025 14:28
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Qbandev and others added 3 commits November 5, 2025 15:30
Add explicit type annotation to fix TS2775 error in CI:
'Assertions require every name in the call target to be
declared with an explicit type annotation.'

This ensures TypeScript can properly validate the assert.ok
call in strict mode.
Replace assert.ok with a simple if-throw pattern to avoid
TypeScript TS2775 error about assertion signatures requiring
explicit type annotations. This is more straightforward and
eliminates the need for the assert import.

The behavior is identical - throws an error if subject is empty.
@Qbandev Qbandev requested a review from Copilot November 5, 2025 14:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Add type assertion for prNumber to fix template literal type errors
- Replace short variable name 'r' with 'item' in test file
- Auto-fix formatting issues (import order, line breaks, trailing spaces)

All linting errors are now resolved.
@Qbandev Qbandev requested a review from Copilot November 5, 2025 15:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

TypeScript can infer the string type from runCommand's return type,
making the explicit annotation unnecessary. This addresses Copilot's
code review feedback for cleaner code.

Note: Cannot use non-null assertion (prNumber!) as suggested by
Copilot because @typescript-eslint/no-non-null-assertion rule
forbids it. The type assertion approach (as string) is the
correct solution for this codebase's linting rules.
@Qbandev Qbandev requested a review from Copilot November 5, 2025 15:38
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <[email protected]>
@Qbandev Qbandev marked this pull request as ready for review November 5, 2025 17:54
@Qbandev Qbandev requested a review from a team as a code owner November 5, 2025 17:54
@Qbandev Qbandev changed the title Fix/infra 3081 filter commits fix(INFRA-3081): duplicate changelog entries Nov 6, 2025
@Qbandev Qbandev changed the title fix(INFRA-3081): duplicate changelog entries fix(INFRA-3081): duplicate auto-changelog entries Nov 6, 2025
Copy link
Contributor

@mcmire mcmire left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seem to be multiple kinds of changes in this PR. If the goal is to remove duplicate changelog entries then that's fine, but removing commits without PR numbers doesn't seem like the best solution to that problem.

Have you considered checking for the existence of the entire entry in the existing changelog instead? So if we're about to copy an entry into the changelog and it has a PR number, we don't add the entry if one already exists with the same PR number. But if the entry we're copying doesn't have a PR number, we don't add the entry if one already exists with the whole message.

Second, I don't think we should exclude commit messages without PR numbers by default. This would essentially break how we typically use auto-changelog in library repos. Just because a commit message doesn't have a PR number doesn't mean it's ineligible for inclusion in the changelog. Basically the release author needs to review this entry in the same way as every other entry. If for some reason we still really want this then can we add an option?

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-allow-scripts.cjs
spec: "https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js"
spec: 'https://raw.githubusercontent.com/LavaMoat/LavaMoat/main/packages/yarn-plugin-allow-scripts/bundles/@yarnpkg/plugin-allow-scripts.js'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Copilot here, I do not see why this is necessary. Can you revert?

@Qbandev
Copy link
Contributor

Qbandev commented Nov 7, 2025

There seem to be multiple kinds of changes in this PR. If the goal is to remove duplicate changelog entries then that's fine, but removing commits without PR numbers doesn't seem like the best solution to that problem.

Have you considered checking for the existence of the entire entry in the existing changelog instead? So if we're about to copy an entry into the changelog and it has a PR number, we don't add the entry if one already exists with the same PR number. But if the entry we're copying doesn't have a PR number, we don't add the entry if one already exists with the whole message.

Second, I don't think we should exclude commit messages without PR numbers by default. This would essentially break how we typically use auto-changelog in library repos. Just because a commit message doesn't have a PR number doesn't mean it's ineligible for inclusion in the changelog. Basically the release author needs to review this entry in the same way as every other entry. If for some reason we still really want this then can we add an option?

@mcmire Thanks for the review you’re right.

I was targeting INFRA-3081, where direct commits like “Update Attributions” caused duplicate entries because idempotency relied on PR numbers. In doing so, I conflated the duplication issue with the filtering strategy and introduced a breaking change by excluding all non‑PR commits.

Here’s a another path:

  1. Core fix: de‑dupe by checking the existing changelog by PR number when present, and by full message when there’s no PR number. This solves the idempotency problem without breaking other repos.
  2. PR‑only (opt‑in): either reuse the existing --pr-links flag for the update command, or add a dedicated flag like --require-pr-numbers to filter out entries without PR numbers during generation. Default behavior remains unchanged; MetaMask can opt in to PR‑only.

@gauthierpetetin can you confirm this aligns with INFRA‑3081’s expectations? Is step 2 required for your use case? I’ll rework the PR accordingly or open a new one.

@Qbandev Qbandev marked this pull request as draft November 7, 2025 10:03
@gauthierpetetin
Copy link
Contributor

Hi @Qbandev @mcmire ,
Great point, I didn't think the use of auto-changelog could be different in library repos. Thanks for flagging this breaking change we were about to introduce.

In our use case of release changelog generation, the problem, rather than duplicate changelog entries, is the presence of commits without PRs, as they're always irrelevant (e.g. “Update Attributions”) for end users.

Implementing suggestion 2., i.e. introducing a dedicated flag like --require-pr-numbers, sounds good to me!

@Qbandev
Copy link
Contributor

Qbandev commented Nov 7, 2025

The current PR mixes concerns and already diverged; refactoring it further will bloat the diff and complicate review/rollback.
Plan:

  • PR 1 (focused): implement duplicate detection (PR-number match or full-message match). No behaviour flip; minor release.
  • PR 2 (opt-in): add --require-pr-numbers for generation-time filtering. Consumers like MetaMask can opt in.

@Qbandev Qbandev closed this Nov 7, 2025
Qbandev added a commit that referenced this pull request Dec 3, 2025
…iltering (#253)

## What is the current state of things and why does it need to change?

Currently, `auto-changelog` includes all commits in the changelog, even
direct commits without PR numbers. For projects following strict
PR-based workflows (like MetaMask Extension), these direct commits
should be excluded to ensure all changelog entries represent reviewed
changes.

## What is the solution your changes offer and how does it work?

### 1. New `--requirePrNumbers` Flag
Adds an opt-in CLI flag that filters out commits without PR numbers at
generation time. Defaults to `false` for backward compatibility.

**Files changed:** `cli.ts`, `update-changelog.ts`, `get-new-changes.ts`

### 2. Graceful 404 Handling for Forked Repos
When running on forked repositories, the tool fetches PR details from
the fork. PRs originating from the upstream repo return 404 errors.
Added `try-catch` to return empty labels instead of crashing.

### 3. HTML Comment Stripping
PR templates often contain HTML comments (`<!-- ... -->`) that were
breaking markdown rendering in changelogs. Added `stripHtmlComments()`
function to clean descriptions.

### 4. `CHANGELOG entry: null` Fix
PRs marked with `CHANGELOG entry: null` were appearing as "Null (#PR)"
due to:
- Trailing whitespace not being trimmed
- Case-sensitive comparison (only matched lowercase `null`)

Fixed by adding `.trim()` and case-insensitive comparison at both check
points.

> **Note:** Fixes 2-4 were discovered during integration testing and are
prerequisites for the `--requirePrNumbers` flag to work correctly in
production environments with forked repos.

## Usage

```bash
yarn auto-changelog update --requirePrNumbers --autoCategorize --useChangelogEntry --useShortPrLink --rc
```

## Testing

Tested with
[consensys-test/metamask-extension-test](https://github.com/consensys-test/metamask-extension-test)
on `release/1100.0.0`:

| Test | Result |
|------|--------|
| PR Commit `feat: test commit with PR for 1100.0.0 (#40)` | ✅
**INCLUDED** |
| Direct Commit `chore: direct commit without PR for 1100.0.0` | ✅
**EXCLUDED** |
| `Null (#PR)` entries | ✅ **NONE** (case-insensitive fix working) |
| [Generated
Changelog](https://github.com/consensys-test/metamask-extension-test/blob/release/1100.0.0-Changelog/CHANGELOG.md)
| ✅ Correct |

### Changelog Excerpt

```markdown
## [1100.0.0]

### Added
- feat: test commit with PR for 1100.0.0 (#40)
- Design upgrades for Confirmations (#38399)
- Fix amount component to be only accept numeric inputs (#38235)
...
```

**Note:** `N/A` and `None` entries still appear (e.g., `N/A (#37810)`)
because these are different strings from `null` - they're valid
descriptions that PRs chose to use.

## References

- Complements duplicate detection work: #251
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants