Skip to content

Commit

Permalink
feat: smartly generate changelog from previous stable release
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Sep 5, 2023
1 parent e01400d commit d9cf46b
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 10 deletions.
10 changes: 3 additions & 7 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getCurrentGitBranch, getFirstGitCommit, getGitHubRepo, getLastGitTag, isPrerelease } from './git'
import { getCurrentGitBranch, getFirstGitCommit, getGitHubRepo, getLastMatchingTag, isPrerelease } from './git'
import type { ChangelogOptions, ResolvedChangelogOptions } from './types'

export function defineConfig(config: ChangelogOptions) {
Expand Down Expand Up @@ -28,18 +28,14 @@ export async function resolveConfig(options: ChangelogOptions) {
overrides: options,
}).then(r => r.config || defaultConfig)

config.from = config.from || await getLastGitTag()
config.to = config.to || await getCurrentGitBranch()
config.from = config.from || await getLastMatchingTag(config.to) || await getFirstGitCommit()
// @ts-expect-error backward compatibility
config.repo = config.repo || config.github || await getGitHubRepo()
config.prerelease = config.prerelease ?? isPrerelease(config.to)

if (typeof config.repo !== 'string')
throw new Error(`Invalid GitHub repository, expected a string but got ${JSON.stringify(config.repo)}`)

config.prerelease = config.prerelease ?? isPrerelease(config.to)

if (config.to === config.from)
config.from = await getLastGitTag(-1) || await getFirstGitCommit()

return config as ResolvedChangelogOptions
}
22 changes: 19 additions & 3 deletions src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,25 @@ export async function isRepoShallow() {
return (await execCommand('git', ['rev-parse', '--is-shallow-repository'])).trim() === 'true'
}

export async function getLastGitTag(delta = 0) {
const tags = await execCommand('git', ['--no-pager', 'tag', '-l', '--sort=creatordate']).then(r => r.split('\n'))
return tags[tags.length + delta - 1]
export async function getGitTags() {
return (await execCommand('git', ['--no-pager', 'tag', '-l', '--sort=creatordate']).then(r => r.split('\n')))
.reverse()
}

export async function getLastMatchingTag(inputTag: string) {
const isVersion = inputTag[0] === 'v'
const isPrerelease = inputTag[0] === 'v' && inputTag.includes('-')
const tags = await getGitTags()

let tag: string | undefined
// Doing a stable release, find the last stable release to compare with
if (!isPrerelease && isVersion)
tag = tags.find(tag => tag !== inputTag && tag[0] === 'v' && !tag.includes('-'))

// Fallback to the last tag, that are not the input tag
tag ||= tags.find(tag => tag !== inputTag)

return tag
}

export async function isRefGitTag(to: string) {
Expand Down

0 comments on commit d9cf46b

Please sign in to comment.