-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerate-release-info.ts
132 lines (119 loc) · 3.71 KB
/
generate-release-info.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
126
127
128
129
130
131
132
// @ts-expect-error No default export
import release, { Config } from 'release-it'
import { createReleaseItConfig, ExtraConfig } from 'data/release-it'
import { execSync } from 'child_process'
import { readFile, writeFile } from 'fs/promises'
import { join } from 'path'
import { objectToJson } from './utils/object-to-json'
import { isMain } from './utils/is-main'
import { getRepositoryRootDir } from './utils/get-repository-root-dir'
import { getAndCreateGeneratedDataDir } from './utils/get-and-create-generated-data-dir'
interface ReleaseData {
commitSha: string
current: {
version: string
changelog: string
}
next?: {
changelog: string
}
}
// TODO: PR for this
const releaseIt = release as (config: Config) => Promise<{
name: string
changelog: string
latestVersion: string
version: string | undefined
}>
const generateReleaseInfo = async (): Promise<ReleaseData> => {
const dryRunReleaseResult = await dryRunReleaseIt()
const commitSha = execSync('git rev-parse HEAD').toString().trim()
if (dryRunReleaseResult.version) {
return {
commitSha,
current: {
version: dryRunReleaseResult.version,
changelog: dryRunReleaseResult.changelog,
},
}
}
const currentReleaseData = {
commitSha,
current: {
version: dryRunReleaseResult.latestVersion,
changelog: await getLastChangelog(dryRunReleaseResult.latestVersion),
},
}
const isReleasedAlready =
execSync('git tag --points-at HEAD').toString().trim().length > 0
if (isReleasedAlready) {
return currentReleaseData
}
return {
...currentReleaseData,
next: {
changelog: await fixUnreleasedChangelog(dryRunReleaseResult.changelog),
},
}
}
const dryRunReleaseIt = (extraConfig?: ExtraConfig) => {
const config = createReleaseItConfig(extraConfig)
const dryRunConfig: Config = {
git: {
...config.git,
requireCleanWorkingDir: false,
requireUpstream: false,
requireBranch: false,
push: false,
tag: false,
},
github: {
...config.github,
release: false,
},
// @ts-expect-error TODO: Invalid definition, issue a PR
dryRun: true,
}
return releaseIt({
...config,
...dryRunConfig,
})
}
const getLastChangelog = async (lastVersion: string): Promise<string> => {
const previousVersion = getPreviousVersion()
const lastChangelog = (
await dryRunReleaseIt({
gitRawCommitsOpts: { from: previousVersion, to: `v${lastVersion}` },
})
).changelog
return lastChangelog
.slice(lastChangelog.indexOf(`## [${lastVersion}]`))
.replace(`v${lastVersion}...vnull`, `${previousVersion}...v${lastVersion}`)
}
const getPreviousVersion = (): string =>
execSync('git describe --abbrev=0 --tags `git describe --abbrev=0 --tags`^')
.toString()
.trim()
const fixUnreleasedChangelog = async (changelog: string): Promise<string> =>
changelog
.replace(await getVersionPlaceHolder(), 'Unreleased')
.replace('vnull', 'main')
const getVersionPlaceHolder = async (): Promise<string> => {
const packageJson = JSON.parse(
await readFile(join(getRepositoryRootDir(), 'package.json'), 'utf-8'),
) as { version: string }
return packageJson.version
}
if (isMain(import.meta.url)) {
//👇 Otherwise version field for unreleased changes CHANGELOG is empty
process.chdir(getRepositoryRootDir())
await writeFile(
join(await getAndCreateGeneratedDataDir(), 'release.json'),
objectToJson(await generateReleaseInfo()),
)
// 👇 37 handles open at this point😅 So Node.js doesn't exit
// Mainly due to `conventional-changelog`'s monorepo libs
// Maybe that's why `semantic-release` also hangs
// Use `why-is-node-running` for more info. In the meantime, ...
process.exit(0)
}