-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbump-version.ts
More file actions
158 lines (134 loc) · 4.96 KB
/
Copy pathbump-version.ts
File metadata and controls
158 lines (134 loc) · 4.96 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
#!/usr/bin/env bun
/// <reference types="bun" />
import { readFile, writeFile } from 'node:fs/promises'
const VERSION_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/
type ManifestVersions = {
packageJson: string
cargoToml: string
cargoLock: string
tauriConfig: string
}
const args = process.argv.slice(2)
const checkOnly = args.includes('--check')
const versionArg = args.find((arg: string) => !arg.startsWith('-'))
function usage(): void {
console.error('Usage:')
console.error(' bun run version:bump 1.2.3')
console.error(' bun run version:check')
process.exit(1)
}
function assertVersion(version: string): void {
if (!VERSION_PATTERN.test(version)) {
console.error(
`Invalid version "${version}". Use SemVer without a leading "v", for example 1.2.3.`
)
process.exit(1)
}
}
function readCargoPackageVersion(content: string): string {
const match = content.match(/^\[package\][\s\S]*?^version\s*=\s*"([^"]+)"/m)
if (!match) throw new Error('Could not find [package] version in src-tauri/Cargo.toml')
return match[1]
}
function updateCargoPackageVersion(content: string, version: string): string {
const lines = content.split('\n')
let inPackage = false
let updated = false
const nextLines = lines.map((line) => {
if (/^\[[^\]]+\]/.test(line)) {
inPackage = line === '[package]'
}
if (inPackage && !updated && /^version\s*=/.test(line)) {
updated = true
return `version = "${version}"`
}
return line
})
if (!updated) throw new Error('Could not update [package] version in src-tauri/Cargo.toml')
return nextLines.join('\n')
}
function readCargoLockPackageVersion(content: string): string {
const match = content.match(
/^\[\[package\]\]\s*\nname\s*=\s*"aether"\s*\nversion\s*=\s*"([^"]+)"/m
)
if (!match) throw new Error('Could not find aether package version in src-tauri/Cargo.lock')
return match[1]
}
function updateCargoLockPackageVersion(content: string, version: string): string {
const next = content.replace(
/^(\[\[package\]\]\s*\nname\s*=\s*"aether"\s*\nversion\s*=\s*)"([^"]+)"/m,
`$1"${version}"`
)
if (next === content) {
throw new Error('Could not update aether package version in src-tauri/Cargo.lock')
}
return next
}
async function readVersions(): Promise<ManifestVersions> {
const [packageRaw, cargoRaw, cargoLockRaw, tauriRaw] = await Promise.all([
readFile('package.json', 'utf8'),
readFile('src-tauri/Cargo.toml', 'utf8'),
readFile('src-tauri/Cargo.lock', 'utf8'),
readFile('src-tauri/tauri.conf.json', 'utf8')
])
const packageJson = JSON.parse(packageRaw) as { version?: string }
const tauriConfig = JSON.parse(tauriRaw) as { version?: string }
if (!packageJson.version) throw new Error('package.json is missing version')
if (!tauriConfig.version) throw new Error('src-tauri/tauri.conf.json is missing version')
return {
packageJson: packageJson.version,
cargoToml: readCargoPackageVersion(cargoRaw),
cargoLock: readCargoLockPackageVersion(cargoLockRaw),
tauriConfig: tauriConfig.version
}
}
function assertSynced(versions: ManifestVersions, expectedVersion: string): void {
const entries = Object.entries(versions)
const mismatches = entries.filter(([, version]) => version !== expectedVersion)
if (mismatches.length > 0) {
console.error(`Version mismatch. Expected ${expectedVersion}:`)
for (const [manifest, version] of entries) {
console.error(` ${manifest}: ${version}`)
}
process.exit(1)
}
}
async function bumpVersion(version: string): Promise<void> {
assertVersion(version)
const [packageRaw, cargoRaw, cargoLockRaw, tauriRaw] = await Promise.all([
readFile('package.json', 'utf8'),
readFile('src-tauri/Cargo.toml', 'utf8'),
readFile('src-tauri/Cargo.lock', 'utf8'),
readFile('src-tauri/tauri.conf.json', 'utf8')
])
const packageJson = JSON.parse(packageRaw) as { version: string }
const tauriConfig = JSON.parse(tauriRaw) as { version: string }
packageJson.version = version
tauriConfig.version = version
await Promise.all([
writeFile('package.json', `${JSON.stringify(packageJson, null, 2)}\n`),
writeFile('src-tauri/Cargo.toml', updateCargoPackageVersion(cargoRaw, version)),
writeFile('src-tauri/Cargo.lock', updateCargoLockPackageVersion(cargoLockRaw, version)),
writeFile('src-tauri/tauri.conf.json', `${JSON.stringify(tauriConfig, null, 2)}\n`)
])
console.log(`Synced app version to ${version}`)
}
async function main(): Promise<void> {
if (checkOnly) {
const versions = await readVersions()
const expectedVersion = versionArg ?? versions.packageJson
assertVersion(expectedVersion)
assertSynced(versions, expectedVersion)
console.log(`App versions are synced at ${expectedVersion}`)
return
}
if (!versionArg) {
usage()
return
}
await bumpVersion(versionArg)
}
main().catch((error: unknown) => {
console.error(error instanceof Error ? error.message : String(error))
process.exit(1)
})