Repository: mui/material-ui
File: scripts/releaseChangelog.mjs (JavaScript)

Code before:
    .map((author) => `@${author}`)
    .join(', ');

  // We don't know when a particular commit was made from the API.
  // Only that the commits are ordered by date ASC
  const commitsItemsByDateDesc = commitsItems.slice().reverse();
  // Sort by tags ASC, date desc
  // Will only consider exact matches of tags so `[Slider]` will not be grouped with `[Slider][Modal]`
  commitsItems.sort((a, b) => {
    const aTags = parseTags(a.commit.message);
    const bTags = parseTags(b.commit.message);
    if (aTags === bTags) {
      return commitsItemsByDateDesc.indexOf(a) - commitsItemsByDateDesc.indexOf(b);
    }
    return aTags.localeCompare(bTags);
  });
  const changes = commitsItems.map((commitsItem) => {
    // Helps changelog author keeping track of order when grouping commits under headings.
    // &#8203; is a zero-width-space that ensures that the content of the listitem is formatted properly
    const dateSortMarker = `&#8203;<!-- ${(commitsItems.length - commitsItems.indexOf(commitsItem))
      .toString()
      // Padding them with a zero means we can just feed a list into online sorting tools like https://www.online-utility.org/text/sort.jsp
      // i.e. we can sort the lines alphanumerically
      .padStart(Math.floor(Math.log10(commitsItemsByDateDesc.length)) + 1, '0')} -->`;
    const shortMessage = commitsItem.commit.message.split('\n')[0];
    return `- ${dateSortMarker}${shortMessage} @${commitsItem.author?.login}`;
  });
  const nowFormatted = new Date().toLocaleDateString('en-US', {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  });

  const changelog = `
## TODO RELEASE NAME
<!-- generated comparing ${lastRelease}..${release} -->
_${nowFormatted}_

A big thanks to the ${
    authors.length
  } contributors who made this release possible. Here are some highlights ✨:

TODO INSERT HIGHLIGHTS

${changes.join('\n')}

All contributors of this release in alphabetical order: ${contributorHandles}
`;

  // eslint-disable-next-line no-console -- output of this script
  console.log(changelog);

Review comment (security):
You could call the `getAuthor` here as well, so all the places to update manually are clearly marked

Code after:
      }),
    ),
  );
  const contributorHandles = authors
    .sort((a, b) => a.localeCompare(b))
    .map((author) => `@${author}`)
    .join(', ');

  // We don't know when a particular commit was made from the API.
  // Only that the commits are ordered by date ASC
  const commitsItemsByDateDesc = commitsItems.slice().reverse();
  // Sort by tags ASC, date desc
  // Will only consider exact matches of tags so `[Slider]` will not be grouped with `[Slider][Modal]`
  commitsItems.sort((a, b) => {
    const aTags = parseTags(a.commit.message);
    const bTags = parseTags(b.commit.message);
    if (aTags === bTags) {
      return commitsItemsByDateDesc.indexOf(a) - commitsItemsByDateDesc.indexOf(b);
    }
    return aTags.localeCompare(bTags);
  });
  const changes = commitsItems.map((commitsItem) => {
    // Helps changelog author keeping track of order when grouping commits under headings.
    // &#8203; is a zero-width-space that ensures that the content of the listitem is formatted properly
    const dateSortMarker = `&#8203;<!-- ${(commitsItems.length - commitsItems.indexOf(commitsItem))
      .toString()
      // Padding them with a zero means we can just feed a list into online sorting tools like https://www.online-utility.org/text/sort.jsp
      // i.e. we can sort the lines alphanumerically
      .padStart(Math.floor(Math.log10(commitsItemsByDateDesc.length)) + 1, '0')} -->`;
    const shortMessage = commitsItem.commit.message.split('\n')[0];
    return `- ${dateSortMarker}${shortMessage} @${getAuthor(commitsItem)}`;
  });
  const nowFormatted = new Date().toLocaleDateString('en-US', {
    month: 'short',
    day: 'numeric',
    year: 'numeric',
  });

  const changelog = `
## TODO RELEASE NAME
<!-- generated comparing ${lastRelease}..${release} -->
_${nowFormatted}_

A big thanks to the ${
    authors.length
  } contributors who made this release possible. Here are some highlights ✨:

TODO INSERT HIGHLIGHTS

${changes.join('\n')}