ci: fixed versioning (#5214)

* chore(deps): add lerna-lite

* feat: update-1

* feat(db-mongodb): update 2

* chore: lerna init

* chore: add version option to lerna config

* chore(ci): add gh usernames to changelog and user root package.json for version

* chore(ci): whitelist poc branches

* chore(ci): add contributors section

* chore(ci): use turbo for prepublishOnly scripts, enable caching

* chore(deps): update turborepo, add execa

* feat(plugin-stripe): adjust type import

* chore: remove lerna-lite

* chore(ci): new and improved release script for fixed versioning

* chore: remove unused lerna-lite packages

* chore: sync root package.json version

* chore: remove remnants of bundler packages

* chore(plugin-seo): update packagea.json from main, disable build

* chore: disable turbo caching

* chore(ci): update release script

* chore: sync pnpm-lock.yaml

* chore: ci cleanup
This commit is contained in:
Elliot DeNolf
2024-02-29 16:01:51 -05:00
committed by GitHub
parent 7188cfe85a
commit 6ff42d1627
11 changed files with 316 additions and 239 deletions

View File

@@ -1,39 +1,82 @@
import addStream from 'add-stream'
import { ExecSyncOptions } from 'child_process'
import conventionalChangelog from 'conventional-changelog'
import { default as getConventionalPreset } from 'conventional-changelog-conventionalcommits'
import { GitRawCommitsOptions, ParserOptions, WriterOptions } from 'conventional-changelog-core'
import fse, { createReadStream, createWriteStream } from 'fs-extra'
import minimist from 'minimist'
import semver, { ReleaseType } from 'semver'
import tempfile from 'tempfile'
import { PackageDetails } from '../lib/getPackageDetails'
import { Octokit } from '@octokit/core'
import simpleGit from 'simple-git'
import { once } from 'events'
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN })
const git = simpleGit()
type Args = {
pkg: PackageDetails
bump: ReleaseType
newVersion: string
dryRun?: boolean
}
export const updateChangelog = ({ pkg, bump }: Args) => {
// Prefix to find prev tag
const tagPrefix = pkg.shortName === 'payload' ? 'v' : pkg.prevGitTag.split('/')[0] + '/'
export const updateChangelog = async ({ newVersion, dryRun }: Args) => {
const monorepoVersion = fse.readJSONSync('package.json')?.version
if (!monorepoVersion) {
throw new Error('Could not find version in package.json')
}
const lastTag = (await git.tags()).all.reverse().filter((t) => t.startsWith('v'))?.[0]
if (monorepoVersion !== lastTag.replace('v', '')) {
throw new Error(
`Version in package.json (${monorepoVersion}) does not match last tag (${lastTag})`,
)
}
// Load conventional commits preset and modify it
const conventionalPreset = (await getConventionalPreset()) as {
gitRawCommitsOpts: GitRawCommitsOptions
parserOpts: ParserOptions
writerOpts: WriterOptions
recommmendBumpOpts: unknown
conventionalChangelog: unknown
}
// Unbold scope
conventionalPreset.writerOpts.commitPartial =
conventionalPreset.writerOpts?.commitPartial?.replace('**{{scope}}:**', '{{scope}}:')
// Add footer to end of main template
conventionalPreset.writerOpts.mainTemplate = conventionalPreset.writerOpts?.mainTemplate?.replace(
/\n*$/,
'{{footer}}\n',
)
// Fetch commits from last tag to HEAD
const credits = await createContributorSection(lastTag)
// Add Credits to footer
conventionalPreset.writerOpts.finalizeContext = (context) => {
context.footer = credits
return context
}
const nextReleaseVersion = semver.inc(pkg.version, bump) as string
const changelogStream = conventionalChangelog(
// Options
{
preset: 'conventionalcommits',
tagPrefix,
pkg: {
path: `${pkg.packagePath}/package.json`,
},
},
// Context
{
version: nextReleaseVersion, // next release
version: newVersion, // next release
},
// GitRawCommitsOptions
{
path: 'packages',
// path: pkg.packagePath,
// from: pkg.prevGitTag,
// to: 'HEAD'
},
undefined,
conventionalPreset.writerOpts,
).on('error', (err) => {
console.error(err.stack)
console.error(err.toString())
@@ -42,13 +85,60 @@ export const updateChangelog = ({ pkg, bump }: Args) => {
const changelogFile = 'CHANGELOG.md'
const readStream = fse.createReadStream(changelogFile)
const tmp = tempfile()
changelogStream
.pipe(addStream(readStream))
.pipe(createWriteStream(tmp))
.on('finish', () => {
createReadStream(tmp).pipe(createWriteStream(changelogFile))
})
// Output to stdout if debug is true
const emitter = dryRun
? changelogStream.pipe(createWriteStream(tmp)).on('finish', () => {
createReadStream(tmp).pipe(process.stdout)
})
: changelogStream
.pipe(addStream(readStream))
.pipe(createWriteStream(tmp))
.on('finish', () => {
createReadStream(tmp).pipe(createWriteStream(changelogFile))
})
// Wait for the stream to finish
await once(emitter, 'finish')
}
// If file is executed directly, run the function
if (require.main === module) {
const { newVersion } = minimist(process.argv.slice(2))
updateChangelog({ newVersion, dryRun: true })
}
async function createContributorSection(lastTag: string): Promise<string> {
const commits = await git.log({ from: lastTag, to: 'HEAD' })
console.log(`Fetching contributors from ${commits.total} commits`)
const usernames = await Promise.all(
commits.all.map((c) =>
octokit
.request('GET /repos/{owner}/{repo}/commits/{ref}', {
owner: 'payloadcms',
repo: 'payload',
ref: c.hash,
})
.then(({ data }) => data.author?.login as string),
),
)
if (!usernames.length) return ''
// List of unique contributors
const contributors = Array.from(new Set(usernames)).map((c) => `@${c}`)
const formats = {
1: (contributors: string[]) => contributors[0],
2: (contributors: string[]) => contributors.join(' and '),
// Oxford comma ;)
default: (contributors: string[]) => contributors.join(', ').replace(/,([^,]*)$/, ', and$1'),
}
const formattedContributors =
formats[contributors.length]?.(contributors) || formats['default'](contributors)
const credits = `### Credits\n\nThanks to ${formattedContributors} for their contributions!\n`
return credits
}