Skip to content

Commit 4a5f681

Browse files
committed
initial commit
0 parents  commit 4a5f681

85 files changed

Lines changed: 13950 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cursor/BUGBOT.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Guidance for Bugbot
2+
3+
Please read the [agents file](./AGENTS.md) in the root of the project for instructions.

.depcheckrc.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
---
2+
ignores:
3+
# Ignore dependencies used by Yarn binaries in `.yarn`
4+
- '@yarnpkg/*'
5+
- 'clipanion'
6+
- 'typanion'
7+
# Ignore dependencies imported implicitly by TypeScript
8+
- '@types/*'
9+
# Ignore tools (packages which we use as executables and not libraries)
10+
- '@lavamoat/allow-scripts'
11+
- '@metamask/auto-changelog'
12+
- '@metamask/create-release-branch'
13+
- 'depcheck'
14+
- 'eslint-interactive'
15+
- 'rimraf'
16+
- 'simple-git-hooks'
17+
- 'ts-node'
18+
- 'typedoc'
19+
# Ignore plugins for tools
20+
- '@typescript-eslint/*'
21+
- 'eslint-config-*'
22+
- 'eslint-plugin-*'
23+
- 'jest-silent-reporter'
24+
- 'prettier-plugin-packagejson'
25+
- 'typescript-eslint'
26+
# Jest environment referenced in `jest.config.scripts.js`
27+
- 'jest-environment-node'
28+
- 'jest-environment-jsdom'
29+
# Ignore dependencies imported implicitly by tools
30+
- 'eslint-import-resolver-typescript'
31+
# Ignore dependencies which plug into the NPM lifecycle
32+
- '@lavamoat/preinstall-always-fail'

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
charset = utf-8
6+
end_of_line = lf
7+
indent_size = 2
8+
indent_style = space
9+
insert_final_newline = true
10+
trim_trailing_whitespace = true
11+
12+
[*.md]
13+
trim_trailing_whitespace = false

.gitattributes

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
* text=auto
2+
3+
yarn.lock linguist-generated=false
4+
5+
# `tsconfig.json` is already recognized as JSONC. This ensures our other `tsconfig` files are as
6+
# well. They all use this naming convention.
7+
tsconfig.**.json linguist-language=jsonc
8+
9+
# yarn v3
10+
# See: https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored
11+
/.yarn/releases/** binary
12+
/.yarn/plugins/** binary

.github/CODEOWNERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Lines starting with '#' are comments.
2+
# Each line is a file pattern followed by one or more owners.
3+
4+
# Note: Please keep this synchronized with the `teams.json` file in the repository root.
5+
# That file is used for some automated workflows, and maps controller to owning team(s).
6+
7+
* @MetaMask/core-platform @MetaMask/network

.github/actionlint.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Please see the documentation for all configuration options:
2+
# https://github.com/rhysd/actionlint/blob/main/docs/config.md#configuration-file
3+
4+
paths:
5+
.github/workflows/publish-release.yml:
6+
ignore:
7+
# Queue option is not supported by actionlint yet.
8+
- 'unexpected key "queue" for "concurrency" section. expected one of "cancel-in-progress", "group"'
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: Check merge queue changelogs
2+
description: Check if the changelog was incorrectly merged in a merge queue
3+
pull request.
4+
5+
inputs:
6+
github-token:
7+
description: The GitHub token to use for authentication.
8+
required: false
9+
default: ${{ github.token }}
10+
11+
runs:
12+
using: composite
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v6
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Get pull request number
20+
id: pr-number
21+
uses: actions/github-script@v8
22+
env:
23+
HEAD_REF: ${{ github.event.pull_request.head.ref || github.event.merge_group.head_ref }}
24+
with:
25+
github-token: ${{ inputs.github-token }}
26+
script: |
27+
const { HEAD_REF } = process.env;
28+
29+
if (context.eventName === 'pull_request') {
30+
const prNumber = context.payload.pull_request.number;
31+
return core.setOutput('pr-number', prNumber);
32+
}
33+
34+
const match = HEAD_REF.match(/\/pr-([0-9]+)-/u);
35+
if (!match) {
36+
return core.setFailed(`Could not extract pull request number from head ref: "${HEAD_REF}".`);
37+
}
38+
39+
const number = parseInt(match[1], 10);
40+
core.setOutput('pr-number', number);
41+
42+
- name: Get pull request branch
43+
id: pr-branch
44+
shell: bash
45+
env:
46+
REPOSITORY: ${{ github.repository }}
47+
PR_NUMBER: ${{ steps.pr-number.outputs.pr-number }}
48+
GH_TOKEN: ${{ inputs.github-token }}
49+
run: |
50+
BRANCH=$(gh api "/repos/${REPOSITORY}/pulls/${PR_NUMBER}" --jq=.head.ref)
51+
echo "pr-branch=$BRANCH" >> "$GITHUB_OUTPUT"
52+
53+
- name: Check changelog changes
54+
id: changelog-check
55+
shell: bash
56+
env:
57+
BASE_REF: ${{ github.event.pull_request.base.ref || github.event.merge_group.base_ref }}
58+
PR_BRANCH: ${{ steps.pr-branch.outputs.pr-branch }}
59+
ACTION_PATH: ${{ github.action_path }}
60+
run: |
61+
set -euo pipefail
62+
63+
# Strip invalid prefix from `BASE_REF`
64+
# It comes prefixed with `refs/heads/`, but the branch is not checked out in this context
65+
# We need to express it as a remote branch
66+
PREFIXED_REF_REGEX='refs/heads/(.+)'
67+
if [[ "$BASE_REF" =~ $PREFIXED_REF_REGEX ]]; then
68+
BASE_REF="${BASH_REMATCH[1]}"
69+
fi
70+
71+
TARGET_REF=$(git merge-base "origin/$BASE_REF" "origin/$PR_BRANCH")
72+
git fetch origin "$TARGET_REF"
73+
74+
UPDATED_CHANGELOGS=$(git diff --name-only "$TARGET_REF" "origin/$PR_BRANCH" | grep -E 'CHANGELOG\.md$' || true)
75+
if [ -n "$UPDATED_CHANGELOGS" ]; then
76+
for FILE in $UPDATED_CHANGELOGS; do
77+
if [ ! -f "$FILE" ]; then
78+
echo "Changelog file \"$FILE\" was deleted in this PR. Skipping."
79+
continue
80+
fi
81+
82+
if ! git cat-file -e "$TARGET_REF":"$FILE" 2>/dev/null; then
83+
echo "Changelog file \"$FILE\" is new in this PR. Skipping."
84+
continue
85+
fi
86+
87+
echo "Checking changelog file: $FILE"
88+
git show "$TARGET_REF":"$FILE" > /tmp/base-changelog.md
89+
git show origin/"$PR_BRANCH":"$FILE" > /tmp/pr-changelog.md
90+
91+
node "${ACTION_PATH}/check-changelog-diff.cjs" \
92+
/tmp/base-changelog.md \
93+
/tmp/pr-changelog.md \
94+
"$FILE"
95+
done
96+
else
97+
echo "No CHANGELOG.md files were modified in this PR."
98+
fi
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// This script checks that any new changelog entries added in a PR
2+
// remain in the [Unreleased] section after the PR is merged.
3+
4+
const fs = require('fs');
5+
6+
if (process.argv.length < 5) {
7+
console.error(
8+
'Usage: node check-changelog-diff.cjs <base-file> <pr-file> <merged-file>',
9+
);
10+
11+
// eslint-disable-next-line n/no-process-exit
12+
process.exit(1);
13+
}
14+
15+
/* eslint-disable n/no-sync */
16+
// The type of these is inferred as `Buffer` when using "utf-8" directly instead
17+
// of an options object. Even though it's a plain JavaScript file, it's nice to
18+
// keep the types correct.
19+
const baseContent = fs.readFileSync(process.argv[2], {
20+
encoding: 'utf-8',
21+
});
22+
23+
const prContent = fs.readFileSync(process.argv[3], {
24+
encoding: 'utf-8',
25+
});
26+
27+
const mergedContent = fs.readFileSync(process.argv[4], {
28+
encoding: 'utf-8',
29+
});
30+
/* eslint-enable n/no-sync */
31+
32+
/**
33+
* Extract the "[Unreleased]" section from the changelog content.
34+
*
35+
* This doesn't actually parse the Markdown, it just looks for the section
36+
* header and collects lines until the next section header.
37+
*
38+
* @param {string} content - The changelog content.
39+
* @returns {Set<string>} The lines in the "[Unreleased]" section as a
40+
* {@link Set}.
41+
*/
42+
function getUnreleasedSection(content) {
43+
const lines = content.split('\n');
44+
45+
let inUnreleased = false;
46+
const sectionLines = new Set();
47+
48+
for (const line of lines) {
49+
// Find unreleased header.
50+
if (line.trim().match(/^##\s+\[Unreleased\]/u)) {
51+
inUnreleased = true;
52+
continue;
53+
}
54+
55+
// Stop if we hit the next version header (## [x.x.x]).
56+
if (inUnreleased && line.trim().match(/^##\s+\[/u)) {
57+
break;
58+
}
59+
60+
// If inside the unreleased header, add lines to the set.
61+
if (inUnreleased) {
62+
sectionLines.add(line.trim());
63+
}
64+
}
65+
66+
return sectionLines;
67+
}
68+
69+
/**
70+
* Get the lines that were added in the PR content compared to the base content.
71+
*
72+
* @param {Set<string>} oldLines - The base changelog content.
73+
* @param {Set<string>} newLines - The PR changelog content.
74+
* @returns {string[]} The added lines as an array of strings.
75+
*/
76+
function getAddedLines(oldLines, newLines) {
77+
return Array.from(newLines).filter(
78+
(line) => line.length > 0 && !oldLines.has(line) && !line.startsWith('#'),
79+
);
80+
}
81+
82+
const mergedUnreleased = getUnreleasedSection(mergedContent);
83+
const addedLines = getAddedLines(
84+
getUnreleasedSection(baseContent),
85+
getUnreleasedSection(prContent),
86+
);
87+
88+
const missingLines = [];
89+
for (const line of addedLines) {
90+
if (!mergedUnreleased.has(line)) {
91+
missingLines.push(line);
92+
}
93+
}
94+
95+
if (missingLines.length > 0) {
96+
console.error(
97+
`The following lines added in the PR are missing from the "Unreleased" section after merge:\n\n ${missingLines.join('\n ')}\n\nPlease update your pull request and ensure that new changelog entries remain in the "Unreleased" section.`,
98+
);
99+
100+
process.exitCode = 1;
101+
}

0 commit comments

Comments
 (0)