diff --git a/scripts/_utils.ts b/scripts/_utils.ts index fb5804c514..fa28f92e25 100644 --- a/scripts/_utils.ts +++ b/scripts/_utils.ts @@ -1,7 +1,7 @@ -import { execSync } from 'node:child_process' import { promises as fsp } from 'node:fs' import { $fetch } from 'ofetch' import { resolve } from 'pathe' +import { compare } from 'semver' import { glob } from 'tinyglobby' import { exec } from 'tinyexec' import { determineSemverChange, getGitDiff, loadChangelogConfig, parseCommits } from 'changelogen' @@ -106,17 +106,35 @@ export async function determineBumpType () { return determineSemverChange(commits, config) } +export async function getLatestTag () { + const { stdout: latestTag } = await exec('git', ['describe', '--tags', '--abbrev=0']) + return latestTag.trim() +} + +export async function getLatestReleasedTag () { + const latestReleasedTag = await exec('git', ['tag', '-l']).then(r => r.stdout.trim().split('\n').filter(t => /v3\.\d+\.\d+/.test(t)).sort(compare)).then(r => r.pop()!.trim()) + return latestReleasedTag +} + +export async function getPreviousReleasedCommits () { + const config = await loadChangelogConfig(process.cwd()) + const latestTag = await getLatestTag() + const latestReleasedTag = await getLatestReleasedTag() + const commits = parseCommits(await getGitDiff(latestTag, latestReleasedTag), config) + return commits +} + export async function getLatestCommits () { const config = await loadChangelogConfig(process.cwd()) - const { stdout: latestTag } = await exec('git', ['describe', '--tags', '--abbrev=0']) + const latestTag = await getLatestTag() - return parseCommits(await getGitDiff(latestTag.trim()), config) + return parseCommits(await getGitDiff(latestTag), config) } export async function getContributors () { const contributors = [] as Array<{ name: string, username: string }> const emails = new Set() - const latestTag = execSync('git describe --tags --abbrev=0').toString().trim() + const latestTag = await getLatestTag() const rawCommits = await getGitDiff(latestTag) for (const commit of rawCommits) { if (emails.has(commit.author.email) || commit.author.name === 'renovate[bot]') { continue } diff --git a/scripts/update-changelog.ts b/scripts/update-changelog.ts index 7da75bb731..eb16f6c47c 100644 --- a/scripts/update-changelog.ts +++ b/scripts/update-changelog.ts @@ -3,15 +3,19 @@ import { $fetch } from 'ofetch' import { inc } from 'semver' import { generateMarkDown, getCurrentGitBranch, loadChangelogConfig } from 'changelogen' import { consola } from 'consola' -import { determineBumpType, getContributors, getLatestCommits, loadWorkspace } from './_utils' +import { determineBumpType, getContributors, getLatestCommits, getLatestReleasedTag, getLatestTag, getPreviousReleasedCommits, loadWorkspace } from './_utils' + +const handleSeparateBranch = true async function main () { const releaseBranch = await getCurrentGitBranch() const workspace = await loadWorkspace(process.cwd()) const config = await loadChangelogConfig(process.cwd(), {}) + const prevMessages = new Set(handleSeparateBranch ? await getPreviousReleasedCommits().then(r => r.map(c => c.message)) : []) + const commits = await getLatestCommits().then(commits => commits.filter( - c => config.types[c.type] && !(c.type === 'chore' && c.scope === 'deps'), + c => config.types[c.type] && !(c.type === 'chore' && c.scope === 'deps') && !prevMessages.has(c.message), )) const bumpType = await determineBumpType() || 'patch' @@ -38,6 +42,9 @@ async function main () { const [currentPR] = await $fetch(`https://api.github.com/repos/nuxt/nuxt/pulls?head=nuxt:v${newVersion}`) const contributors = await getContributors() + const latestTag = await getLatestTag() + const previousReleasedTag = handleSeparateBranch ? await getLatestReleasedTag() : latestTag + const releaseNotes = [ currentPR?.body.replace(/## 👉 Changelog[\s\S]*$/, '') || `> ${newVersion} is the next ${bumpType} release.\n>\n> **Timetable**: to be announced.`, '## 👉 Changelog', @@ -45,7 +52,8 @@ async function main () { .replace(/^## v.*\n/, '') .replace(`...${releaseBranch}`, `...v${newVersion}`) .replace(/### ❤️ Contributors[\s\S]*$/, '') - .replace(/[\n\r]+/g, '\n'), + .replace(/[\n\r]+/g, '\n') + .replace(latestTag, previousReleasedTag), '### ❤️ Contributors', contributors.map(c => `- ${c.name} (@${c.username})`).join('\n'), ].join('\n')