/
publish.ts
125 lines (101 loc) · 3.29 KB
/
publish.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import type { Commit, PackageToRelease } from "./types"
import { debug, pkgJson, execSync } from "./utils"
export async function publish(options: {
dryRun: boolean
packages: PackageToRelease[]
RELEASE_COMMIT_MSG: string
}) {
const { dryRun, packages, RELEASE_COMMIT_MSG } = options
execSync("yarn build")
for await (const pkg of packages) {
if (dryRun) {
console.log(
`Dry run, npm publish for package ${pkg.name} will show the wrong version (${pkg.oldVersion}). In normal run, it would be ${pkg.newVersion}`
)
} else {
console.log(
`Writing version ${pkg.newVersion} to package.json for package ${pkg.name}`
)
await pkgJson.update(pkg.path, { version: pkg.newVersion })
console.log("package.json file has been written, publishing...")
}
let npmPublish = `npm publish --access public --registry=https://registry.npmjs.org`
// We use different tokens for `next-auth` and `@next-auth/*` packages
if (pkg.name === "next-auth") {
process.env.NPM_TOKEN = process.env.NPM_TOKEN_PKG
} else {
process.env.NPM_TOKEN = process.env.NPM_TOKEN_ORG
}
if (dryRun) {
console.log(`Dry run, skip npm publish for package ${pkg.name}...`)
npmPublish += " --dry-run"
}
execSync(npmPublish, { cwd: pkg.path })
}
if (dryRun) {
console.log("Dry run, skip release commit...")
} else {
execSync(`git add -A && git commit -m "${RELEASE_COMMIT_MSG}"`)
console.log("Commited.")
}
for (const pkg of packages) {
const { name, oldVersion, newVersion } = pkg
const gitTag = `${name}@v${newVersion}`
console.log(`${name} ${oldVersion} -> ${newVersion}`)
const changelog = createChangelog(pkg)
debug(`Generated changelog for package ${name}`, changelog)
if (dryRun) {
console.log(`Dry run, skip git tag/release notes for package ${name}`)
} else {
console.log(`Creating git tag...`)
execSync(`git tag ${gitTag}`)
execSync("git push --tags")
console.log(`Creating GitHub release notes...`)
execSync(`gh release create ${gitTag} --notes '${changelog}'`)
}
}
if (!dryRun) {
execSync(`git push`)
}
}
function createChangelog(pkg: PackageToRelease) {
const {
commits: { features, breaking, bugfixes, other },
} = pkg
console.log(`Creating changelog for package ${pkg.name}...`)
let changelog = ``
changelog += listGroup("Features", features)
changelog += listGroup("Bugfixes", bugfixes)
changelog += listGroup("Other", other)
if (breaking.length) {
changelog += `
## BREAKING CHANGES
${breaking.map((c) => ` - ${c.body}`).join("\n")}`
}
return changelog
}
function sortByScope(commits: Commit[]) {
return commits.sort((a, b) => {
if (a.parsed.scope && b.parsed.scope) {
return a.parsed.scope.localeCompare(b.parsed.scope)
} else if (a.parsed.scope) return -1
else if (b.parsed.scope) return 1
return a.body.localeCompare(b.body)
})
}
function header(c: Commit) {
let h = c.parsed.subject
if (c.parsed.scope) {
h = `**${c.parsed.scope}**: ${h} (${c.commit.short})`
}
return h
}
function listGroup(heading: string, commits: Commit[]) {
if (!commits.length) return ""
const list = sortByScope(commits)
.map((c) => ` - ${header(c)}`)
.join("\n")
return `## ${heading}
${list}
`
}