90 lines
2.3 KiB
JavaScript
90 lines
2.3 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import { execFileSync } from 'node:child_process'
|
|
import { pathToFileURL } from 'node:url'
|
|
|
|
function gitLines(args, cwd) {
|
|
try {
|
|
return execFileSync('git', args, {
|
|
cwd,
|
|
encoding: 'utf8',
|
|
stdio: ['ignore', 'pipe', 'ignore']
|
|
})
|
|
.split(/\r?\n/)
|
|
.map((line) => line.trim())
|
|
.filter(Boolean)
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
export function rcNumberFromTag(base, tag) {
|
|
const prefix = `v${base}-rc.`
|
|
if (!tag.startsWith(prefix)) {
|
|
return null
|
|
}
|
|
|
|
const suffix = tag.slice(prefix.length)
|
|
// Why the optional .identifier: suffixed side-branch RCs (v1.2.3-rc.4.perf)
|
|
// must advance the shared rc counter, or the next suffixed cut recomputes
|
|
// an existing tag and the workflow refuses to re-cut over it.
|
|
const match = /^(\d+)(?:\.[0-9A-Za-z]+)?$/.exec(suffix)
|
|
return match ? Number(match[1]) : null
|
|
}
|
|
|
|
export function rcNumberFromReleaseSubject(base, subject) {
|
|
const prefix = `release: v${base}-rc.`
|
|
if (!subject.startsWith(prefix)) {
|
|
return null
|
|
}
|
|
|
|
const match = /^(\d+)(?:\s|$)/.exec(subject.slice(prefix.length))
|
|
return match ? Number(match[1]) : null
|
|
}
|
|
|
|
export function highestRcForBase(base, { cwd = process.cwd() } = {}) {
|
|
const numbers = []
|
|
|
|
for (const tag of gitLines(['tag', '--list', `v${base}-rc.*`], cwd)) {
|
|
const rcNumber = rcNumberFromTag(base, tag)
|
|
if (rcNumber !== null) {
|
|
numbers.push(rcNumber)
|
|
}
|
|
}
|
|
|
|
const logRefs = ['HEAD', 'origin/main'].filter(
|
|
(ref) => gitLines(['rev-parse', '--verify', '--quiet', ref], cwd).length > 0
|
|
)
|
|
if (logRefs.length > 0) {
|
|
for (const subject of gitLines(['log', '--format=%s', ...logRefs], cwd)) {
|
|
const rcNumber = rcNumberFromReleaseSubject(base, subject)
|
|
if (rcNumber !== null) {
|
|
numbers.push(rcNumber)
|
|
}
|
|
}
|
|
}
|
|
|
|
return numbers.length === 0 ? null : Math.max(...numbers)
|
|
}
|
|
|
|
function main() {
|
|
const base = process.argv[2]
|
|
if (!base) {
|
|
throw new Error('Usage: node config/scripts/release-rc-history.mjs <base-version>')
|
|
}
|
|
|
|
const highest = highestRcForBase(base)
|
|
if (highest !== null) {
|
|
process.stdout.write(String(highest))
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
try {
|
|
main()
|
|
} catch (error) {
|
|
console.error(error instanceof Error ? error.message : String(error))
|
|
process.exit(1)
|
|
}
|
|
}
|