Skip to content

Commit

Permalink
added scripts to auto generate changelogs
Browse files Browse the repository at this point in the history
  • Loading branch information
sethkfman committed Jun 28, 2024
1 parent fe986fe commit 68b85ee
Show file tree
Hide file tree
Showing 4 changed files with 355 additions and 3 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"test:merge-coverage": "nyc report --temp-dir ./tests/coverage --report-dir ./tests/merged-coverage/ --reporter json --reporter text --reporter lcovonly",
"test:validate-coverage": "nyc check-coverage --nycrc-path ./coverage-thresholds.json -t ./tests/merged-coverage/",
"update-changelog": "./scripts/auto-changelog.sh",
"changeset-changelog": "wrap () { node ./scripts/generate-rc-commits.js \"$@\" && ./scripts/changelog-csv.sh }; wrap ",
"prestorybook": "rnstl",
"deduplicate": "yarn yarn-deduplicate && yarn install",
"create-release": "./scripts/set-versions.sh && yarn update-changelog",
Expand Down Expand Up @@ -189,6 +190,7 @@
"@metamask/utils": "^8.1.0",
"@ngraveio/bc-ur": "^1.1.6",
"@notifee/react-native": "^7.8.2",
"@octokit/rest": "^21.0.0",
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-clipboard/clipboard": "1.8.4",
"@react-native-community/blur": "4.3.2",
Expand Down Expand Up @@ -338,6 +340,7 @@
"redux-thunk": "^2.4.2",
"reselect": "^4.0.0",
"rxjs": "^7.8.1",
"simple-git": "^3.22.0",
"socket.io-client": "^4.5.3",
"stream-browserify": "3.0.0",
"through2": "3.0.1",
Expand Down Expand Up @@ -572,4 +575,4 @@
}
},
"packageManager": "[email protected]"
}
}
75 changes: 75 additions & 0 deletions scripts/changelog-csv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/bin/bash

set -e
set -u
set -o pipefail

readonly CSV_FILE='commits.csv'
# Temporary file for new entries
NEW_ENTRIES=$(mktemp)
# Backup file for existing CHANGELOG
CHANGELOG_BACKUP="CHANGELOG.md.bak"

# Backup existing CHANGELOG.md
cp CHANGELOG.md "$CHANGELOG_BACKUP"

# Function to append entry to the correct category in the temp file
append_entry() {
local change_type="$1"
local entry="$2"
# Ensure the "Other" category is explicitly handled
case "$change_type" in
Added|Changed|Fixed) ;;
*) change_type="Other" ;; # Categorize as "Other" if not matching predefined categories
esac
echo "$entry" >> "$NEW_ENTRIES-$change_type"
}

# Read the CSV file and append entries to temp files based on change type
while IFS=, read -r commit_message author pr_link team change_type
do
pr_id=$(echo "$pr_link" | grep -o '[^/]*$')
entry="- [#$pr_id]($pr_link): $commit_message"
append_entry "$change_type" "$entry"
done < <(tail -n +2 "$CSV_FILE") # Skip the header line

# Function to insert new entries into CHANGELOG.md after a specific line
insert_new_entries() {
local marker="## Current Main Branch"
local changelog="CHANGELOG.md"
local temp_changelog=$(mktemp)

# Find the line number of the marker
local line_num=$(grep -n "$marker" "$CHANGELOG_BACKUP" | cut -d ':' -f 1)

# Split the existing CHANGELOG at the marker line
head -n "$line_num" "$CHANGELOG_BACKUP" > "$temp_changelog"

# Append the release header
echo "" >> "$temp_changelog"
echo "## <Enter Release Number> - <Date>" >> "$temp_changelog"
echo "" >> "$temp_changelog"

# Append new entries for each change type if they exist
for change_type in Added Changed Fixed Other; do
if [[ -s "$NEW_ENTRIES-$change_type" ]]; then
echo "### $change_type" >> "$temp_changelog"
cat "$NEW_ENTRIES-$change_type" >> "$temp_changelog"
echo "" >> "$temp_changelog" # Add a newline for spacing
fi
done

# Append the rest of the original CHANGELOG content
tail -n +$((line_num + 1)) "$CHANGELOG_BACKUP" >> "$temp_changelog"

# Replace the original CHANGELOG with the updated one
mv "$temp_changelog" "$changelog"
}

# Insert new entries into CHANGELOG.md
insert_new_entries

# Cleanup
rm "$NEW_ENTRIES-"* "$CHANGELOG_BACKUP"

echo 'CHANGELOG updated'
162 changes: 162 additions & 0 deletions scripts/generate-rc-commits.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// eslint-disable-next-line import/no-nodejs-modules
import fs from 'fs';
// eslint-disable-next-line import/no-extraneous-dependencies
import simpleGit from 'simple-git';
// eslint-disable-next-line import/no-extraneous-dependencies
import { Octokit } from '@octokit/rest';

// "GITHUB_TOKEN" is an automatically generated, repository-specific access token provided by GitHub Actions.
const githubToken = process.env.GITHUB_TOKEN;
if (!githubToken) {
console.log('GITHUB_TOKEN not found');
process.exit(1);
}

// Initialize Octokit with your GitHub token
const octokit = new Octokit({ auth: githubToken});

async function getPRLabels(prNumber) {
try {
const { data } = await octokit.pulls.get({
owner: 'MetaMask',
repo: 'metamask-mobile',
pull_number: prNumber[1],
});

const labels = data.labels.map(label => label.name);

// Check if any label name contains "team"
const hasTeamLabel = labels.filter(label => label.toLowerCase().includes('team'));

return hasTeamLabel || 'Unknown';

} catch (error) {
console.error(`Error fetching labels for PR #${prNumber}:`, error);
return [];
}
}

// Function to filter commits based on unique commit messages and group by teams
async function filterCommitsByTeam(branchA, branchB) {
try {
const git = simpleGit();

const logOptions = {
from: branchB,
to: branchA,
format: {
hash: '%H',
author: '%an',
message: '%s',
},
};

const log = await git.log(logOptions);
const seenMessages = new Set();
const seenMessagesArray = [];
const commitsByTeam = {};

const MAX_COMMITS = 500; // Limit the number of commits to process

for (const commit of log.all) {
const { author, message, hash } = commit;
if (commitsByTeam.length >= MAX_COMMITS) {
break;
}

// Extract PR number from the commit message using regex
const prMatch = message.match(/\(#(\d{5})\)$/u);
const prLink = prMatch ? `https://github.com/MetaMask/metamask-mobile/pull/${prMatch[1]}` : '';

const team = await getPRLabels(prMatch);
console.log(team);

// Check if the commit message is unique
if (!seenMessages.has(message)) {
seenMessagesArray.push(message);
seenMessages.add(message);

// Initialize the team's commits array if it doesn't exist
if (!commitsByTeam[team]) {
commitsByTeam[team] = [];
}

commitsByTeam[team].push({
message,
author,
hash: hash.substring(0, 10),
prLink,
});
}
}

return commitsByTeam;
} catch (error) {
console.error(error);
return {};
}
}

function formatAsCSV(commitsByTeam) {
const csvContent = [];
for (const [team, commits] of Object.entries(commitsByTeam)) {
commits.forEach((commit) => {
const row = [
escapeCSV(commit.message),
escapeCSV(commit.author),
commit.prLink,
escapeCSV(team),
assignChangeType(commit.message)
];
csvContent.push(row.join(','));
});
}
csvContent.unshift('Commit Message,Author,PR Link,Team,Change Type');

return csvContent;
}

// Helper function to escape CSV fields
function escapeCSV(field) {
if (field.includes(',') || field.includes('"') || field.includes('\n')) {
return `"${field.replace(/"/g, '""')}"`; // Encapsulate in double quotes and escape existing quotes
}
return field;
}
// Helper function to create change type
function assignChangeType(field) {
if (field.includes('feat'))
return 'Added';
else if (field.includes('cherry') || field.includes('bump'))
return 'Ops';
else if (field.includes('chore') || field.includes('test') || field.includes('ci') || field.includes('docs') || field.includes('refactor'))
return 'Changed';
else if (field.includes('fix'))
return 'Fixed';

return 'Unknown';
}

async function main() {
const args = process.argv.slice(2);

if (args.length !== 2) {
console.error('Usage: node script.js branchA branchB');
process.exit(1);
}

const branchA = args[0];
const branchB = args[1];

const commitsByTeam = await filterCommitsByTeam(branchA, branchB);

if (Object.keys(commitsByTeam).length === 0) {
console.log('No unique commits found.');
} else {
const csvContent = formatAsCSV(commitsByTeam);
fs.writeFileSync('commits.csv', csvContent.join('\n'));
console.log('CSV file "commits.csv" created successfully.');
}
}

main();
Loading

0 comments on commit 68b85ee

Please sign in to comment.