Skip to content

Commit c4cb337

Browse files
authored
ci: add changelog lint to catch malformed CHANGELOG.md (#33117)
## **Description** <!-- mms-check: type=text required=true --> The automated main-version-bump PR for the 8.3.0 release cut never got created: `MetaMask/github-tools`'s `create-release-pr` action crashed with `Error: Malformed category header: '### **Before**'` while regenerating `CHANGELOG.md` on the `release-changelog/8.3.0` branch, because a prior PR's raw "Screenshots/Recordings" template text had been committed verbatim into the changelog instead of a clean entry. Nothing in mobile's CI validates `CHANGELOG.md` formatting today, so this kind of corruption is invisible until it silently breaks the release-cut pipeline. This adds a changelog lint, mirroring the pattern `metamask-extension` already uses: - `scripts/lint-changelog.sh`: a branch-aware wrapper around `@metamask/auto-changelog validate` (the same non-mutating parser the release pipeline's `auto-changelog update` uses internally, so it fails on the exact same malformed input). On release-oriented branches (`release/X.Y.Z(-ota)?`, `release-changelog/X.Y.Z*`) it adds `--rc`, which also verifies the current `package.json` version has a changelog section. - `lint:changelog` / `lint:changelog:rc` scripts in `package.json`, wired into the existing `scripts` lint matrix in `.github/workflows/ci.yml` so it runs on every PR — including changelog PRs into `release/*` and release PRs into `stable` — without needing a new job. - A one-time normalization of `CHANGELOG.md` via `auto-changelog validate --fix`, which stripped 718 extraneous blank lines (verified zero content lines added/removed) so the new check starts green instead of failing immediately on `main`. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: null ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Changelog validation in CI Scenario: CI catches a malformed changelog entry before it reaches the release pipeline Given a PR modifies CHANGELOG.md with an invalid category header (e.g. "### **Before**") When the `scripts` CI job runs `yarn lint:changelog` Then the job should fail with "Malformed category header" Scenario: CI validates release-branch changelogs in --rc mode Given a PR's head or base branch matches `release/X.Y.Z` or `release-changelog/X.Y.Z` When `yarn lint:changelog` runs Then it should invoke `auto-changelog validate --rc` And fail if the branch's current package.json version has no changelog section Scenario: main's CHANGELOG.md passes validation Given the CHANGELOG.md normalization included in this PR When `yarn lint:changelog` runs on `main` Then it should exit 0 with no errors ``` Locally verified: `yarn lint:changelog` passes on `main`; re-injecting the exact `### **Before**` corruption that broke the 8.3.0 release cut reproduces the identical `Malformed category header` error; simulating `release/8.3.0` / `release-changelog/8.3.0` branch names via `GITHUB_REF_NAME` / `GITHUB_HEAD_REF` correctly switches the script into `--rc` mode. ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- Generated with the help of the pr-description AI skill --> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Changes are limited to CI and changelog tooling; no runtime app behavior, with the main effect being failed PRs when CHANGELOG.md is invalid. > > **Overview** > Adds **CHANGELOG.md validation** to the existing CI `scripts` matrix so every PR runs `yarn lint:changelog`, catching malformed changelog entries (e.g. invalid category headers) before they break release-cut automation. > > Introduces `scripts/lint-changelog.sh`, which runs `@metamask/auto-changelog validate --prettier` and turns on **`--rc`** on `release/*`, `release/*-ota`, and `release-changelog/*` branches so the current `package.json` version must have a matching changelog section. `package.json` gains `lint:changelog`, `lint:changelog:rc`, and a **`repository`** field so auto-changelog can resolve the repo URL under Yarn Berry. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit e081453. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent d0795b6 commit c4cb337

3 files changed

Lines changed: 51 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ jobs:
270270
scripts:
271271
- lint
272272
- lint:tsc
273+
- lint:changelog
273274
- format:check
274275
- audit:ci
275276
- test:depcheck

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
"name": "metamask",
33
"version": "8.4.0",
44
"private": true,
5+
"repository": {
6+
"type": "git",
7+
"url": "https://github.com/MetaMask/metamask-mobile.git"
8+
},
59
"scripts": {
610
"install:foundryup": "yarn mm-foundryup",
711
"anvil": "node_modules/.bin/anvil",
@@ -19,6 +23,8 @@
1923
"lint:fix": "NODE_OPTIONS='--max-old-space-size=12288' eslint '**/*.{js,ts,tsx}' --fix --cache && yarn messenger-action-types:generate",
2024
"lint:clean": "rm -f .eslintcache",
2125
"lint:tsc": "NODE_OPTIONS='--max-old-space-size=12288' tsc --project ./tsconfig.json",
26+
"lint:changelog": "./scripts/lint-changelog.sh",
27+
"lint:changelog:rc": "auto-changelog validate --rc --prettier",
2228
"format": "prettier '**/*.{js,ts,tsx,json}' --write",
2329
"format:check": "prettier '**/*.{js,ts,tsx,json}' --check",
2430
"format:check:changed": "git diff --name-only --diff-filter=ACM HEAD~1 | { grep -E '\\.(js|ts|tsx|json)$' || true; } | xargs --no-run-if-empty prettier --check",

scripts/lint-changelog.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# Validates CHANGELOG.md with @metamask/auto-changelog, mirroring the pattern used
6+
# by metamask-extension (see .github/workflows/repository-health-checks.yml there).
7+
#
8+
# On release-oriented branches, `--rc` is added so validation also enforces that the
9+
# branch's current package.json version has a corresponding changelog section. This
10+
# is what should have caught the malformed '### **Before**' header that broke the
11+
# 8.3.0 -> 8.4.0 release-cut automation before it ever reached CI.
12+
#
13+
# Branch shapes treated as release-oriented:
14+
# release/X.Y.Z, release/X.Y.Z-ota (release branches, incl. OTA hotfixes)
15+
# release-changelog/X.Y.Z[...] (the changelog-generation working branch)
16+
#
17+
# package.json's "repository" field supplies the repo URL automatically (Yarn
18+
# 3.x/Berry sets PROJECT_CWD, which @metamask/auto-changelog reads), so --repo
19+
# does not need to be passed explicitly here.
20+
#
21+
# --prettier tells the validator to expect the changelog in Prettier-formatted
22+
# Markdown (blank line after headings), which matches this repo's existing
23+
# CHANGELOG.md style. Without it, validation would fail against a stricter,
24+
# denser canonical form (no blank line after headings) hardcoded in
25+
# @metamask/auto-changelog's stringifier, which would otherwise force
26+
# reformatting the entire file's history to pass.
27+
28+
branch="${GITHUB_HEAD_REF:-}"
29+
if [[ -z "$branch" ]]; then
30+
branch="${GITHUB_REF_NAME:-}"
31+
fi
32+
if [[ -z "$branch" ]]; then
33+
branch="$(git branch --show-current 2>/dev/null || true)"
34+
fi
35+
36+
rc_flag=()
37+
if [[ "$branch" =~ ^release/[0-9]+\.[0-9]+\.[0-9]+(-ota)?$ ]] || [[ "$branch" =~ ^release-changelog/[0-9]+\.[0-9]+\.[0-9]+ ]]; then
38+
echo "Branch '${branch}' is release-oriented: validating with --rc"
39+
rc_flag=(--rc)
40+
else
41+
echo "Branch '${branch}' is not release-oriented: validating without --rc"
42+
fi
43+
44+
yarn auto-changelog validate --prettier "${rc_flag[@]+"${rc_flag[@]}"}"

0 commit comments

Comments
 (0)