This repository was archived by the owner on Dec 28, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathrelease.js
More file actions
218 lines (180 loc) · 6.42 KB
/
Copy pathrelease.js
File metadata and controls
218 lines (180 loc) · 6.42 KB
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/// Package release utilities. Especially, utilities to load `CHANGELOG.md`, extract the newest
/// entry, and use it to generate package version and description.
const fss = require('fs')
const path = require('path')
const paths = require('./paths')
const semver = require('semver')
const config = require('../config')
// =================
// === Constants ===
// =================
const CHANGELOG_FILE_NAME = 'CHANGELOG.md'
const CHANGELOG_FILE = path.join(paths.root,CHANGELOG_FILE_NAME)
const ENGINE_VERSION = config.engineVersion
// ===============
// === Version ===
// ===============
class NextReleaseVersion {
/// Version used for config files when building the package with "next version" in changelog.
toString() {
return "0.0.0"
}
isPrerelease() {
return true
}
}
class Version {
constructor(major,minor,patch,tag,tagVersion,rcTag,rcTagVersion) {
this.major = major
this.minor = minor
this.patch = patch
this.tag = tag
this.tagVersion = tagVersion
this.rcTag = rcTag
this.rcTagVersion = rcTagVersion
}
lt(that) {
if (this.major < that.major) { return true }
if (this.minor < that.minor) { return true }
if (this.patch < that.patch) { return true }
if (this.tag === 'nightly' && that.tag !== 'nightly') { return false }
if (this.tag === 'alpha' && that.tag === 'beta') { return true }
if (this.tag === 'alpha' && that.tag === 'rc') { return true }
if (this.tag === 'beta' && that.tag === 'rc') { return true }
if (ltStrings(this.tagVersion, that.tagVersion)) { return true }
if (ltStrings(this.rcTagVersion, that.rcTagVersion)) { return true }
return false
}
isPrerelease() {
if (this.tag) { return true } else { return false }
}
toString() {
let suffix = ''
if (this.tag) {
suffix = `-${this.tag}.${this.tagVersion}`
if (this.rcTag) {
suffix += `.${this.rcTag}.${this.rcTagVersion}`
}
}
return `${this.major}.${this.minor}.${this.patch}${suffix}`
}
}
/// Compare two versions lexicographically.
function ltStrings(version1, version2) {
let maxLength = Math.max(version1.length, version2.length)
let v1 = version1.padStart(maxLength, ' ')
let v2 = version2.padStart(maxLength, ' ')
return v1 < v2
}
// ======================
// === ChangelogEntry ===
// ======================
class ChangelogEntry {
constructor(version,body) {
this.version = version
this.body = body
}
assert_is_newest_version_defined() {
if (this.version instanceof NextReleaseVersion) {
throw `The newest entry in CHANGELOG.md does not have version assigned.`
}
}
assert_is_unstable() {
this.assert_is_newest_version_defined()
if (!this.isPrerelease()) {
throw "Assertion failed. The version is stable."
}
}
assert_is_stable() {
this.assert_is_newest_version_defined()
if (this.isPrerelease()) {
throw "Assertion failed. The version is unstable."
}
}
isPrerelease() {
return this.version.isPrerelease()
}
}
// =================
// === Changelog ===
// =================
class Changelog {
constructor() {
this.entries = changelogEntries()
}
newestEntry() {
return this.entries[0]
}
currentVersion() {
return this.newestEntry().version
}
}
function changelogSections() {
let text = '\n' + fss.readFileSync(CHANGELOG_FILE,"utf8")
let chunks = text.split(/\r?\n#(?!#)/)
return chunks.filter((s) => s != '')
}
function changelogEntries() {
let sections = changelogSections()
let entries = []
let firstSection = true
for (let section of sections) {
let splitPoint = section.indexOf('\n')
let header = section.substring(0,splitPoint)
let body = section.substring(splitPoint).trim()
if (firstSection && header.startsWith(' Next Release')) {
let version = new NextReleaseVersion
entries.push(new ChangelogEntry(version,body))
} else {
let headerReg = /^ Enso (?<major>[0-9]+)\.(?<minor>[0-9]+)\.(?<patch>[0-9]+)(-(?<tag>alpha|beta|nightly|rc)\.(?<tagVersion>[0-9-]+))?(.(?<rcTag>rc)\.(?<rcTagVersion>[0-9]+))? \((?<year>[0-9][0-9][0-9][0-9])-(?<month>[0-9][0-9])-(?<day>[0-9][0-9])\)/
let match = header.match(headerReg)
if (!match) {
throw `Improper changelog entry header: '${header}'. See the 'CHANGELOG_TEMPLATE.md' for details.`
}
let grps = match.groups
let version = new Version(grps.major,grps.minor,grps.patch,grps.tag,grps.tagVersion,grps.rcTag,grps.rcTagVersion)
entries.push(new ChangelogEntry(version,body))
}
firstSection = false
}
let firstEntry = true
let lastVersion = null
for (let entry of entries) {
if (!(firstEntry && entry.version instanceof NextReleaseVersion)) {
if (lastVersion !== null) {
if (!entry.version.lt(lastVersion)) {
let v1 = entry.version.toString()
let v2 = lastVersion.toString()
throw `Versions are not properly ordered in the changelog (${v1} >= ${v2}).`
}
}
lastVersion = entry.version
}
firstEntry = false
}
return entries
}
function changelog() {
return new Changelog
}
function currentVersion() {
return changelog().currentVersion()
}
/// Create the nightly version based on the last version in changelog.
function nightlyVersion() {
let changelog = new Changelog
let version = changelog.entries[0].version
if (version instanceof NextReleaseVersion) {
version = changelog.entries[1].version
}
return `${version.major}.${version.minor}.${version.patch}-nightly.${isoDate()}`
}
/// Get the current ISO date in format `YYYY-MM-DD`.
function isoDate() {
let date = new Date()
return date.toISOString().split('T')[0]
}
// ===============
// === Exports ===
// ===============
module.exports = {ENGINE_VERSION,Version,NextReleaseVersion,changelog,currentVersion,nightlyVersion,isoDate}