Files
orca/config/scripts/release/versioning/hourly-build-version.mjs
T
Neil 9bd6272fdf refactor(tooling): organize build, CI, and test owners (#38130)
* refactor(tooling): organize test runtime and maintenance owners

* test(tooling): preserve relocated runtime fixture dependency edges

* refactor(tooling): preserve xterm routing owner checks

* ci(tooling): include routing owner in sparse checkout

* test(tooling): preserve copied workflow dependency closures

* fix(tooling): normalize hashed JSON assets in release parity

* fix(tooling): distinguish asset aliases from literal references

* fix(tooling): frame normalized asset reference payloads

* fix(tooling): normalize decoded JSON asset references

* refactor(tooling): organize build, CI and release owners

* fix(tooling): align moved generator and workflow path contracts

* fix(tooling): update generated plugin bundle owner banners

* test(tooling): create relocated mobile verifier fixture directories

* test(tooling): copy headless detector dependency closure

* test(tooling): align native batch policy fixtures with owner path

* fix(tooling): link moved reliability command to historical evidence

* fix(tooling): preserve nested sandbox owners and canonical guide source

* fix(tooling): target release version owners in checkout fixture
2026-11-04 21:08:19 -08:00

90 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { execFileSync } from 'node:child_process'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { formatReleaseTitleTimestamp } from './release-title-timestamp.mjs'
import {
readPublishedVersionsFromEnv,
resolveDevChannelBaseVersion
} from './dev-channel-base-version.mjs'
// UTC minute tags sort chronologically by semver.
export function createHourlyBuildVersion(baseVersion, date) {
const match = /^(\d+\.\d+\.\d+)(?:-[0-9A-Za-z.-]+)?$/.exec(baseVersion)
if (!match) {
throw new Error(`Package version is not valid semver: ${baseVersion}`)
}
if (!(date instanceof Date) || Number.isNaN(date.getTime())) {
throw new Error('Hourly build timestamp is invalid.')
}
const pad = (value, width = 2) => String(value).padStart(width, '0')
const stamp = [
pad(date.getUTCFullYear(), 4),
pad(date.getUTCMonth() + 1),
pad(date.getUTCDate()),
pad(date.getUTCHours()),
pad(date.getUTCMinutes())
].join('')
// Strip RC tail: rc.N-hourly outranks RC and would offer untested builds automatically; base-hourly stays below RC/stable for explicit selection.
return `${match[1]}-hourly.${stamp}`
}
// Restart numbering per base; take max release-title number, not count, so retention pruning cannot reissue numbers. Legacy unmatched titles yield 01.
export function nextHourlyBuildNumber(baseVersion, releaseNames = []) {
const prefix = `${baseVersion} • `
const highest = releaseNames.reduce((max, entry) => {
const name = String(entry ?? '')
if (!name.startsWith(prefix)) {
return max
}
const match = /^(\d+) • /.exec(name.slice(prefix.length))
return match ? Math.max(max, Number(match[1])) : max
}, 0)
return highest + 1
}
// Release title shown verbatim in GitHub/build picker: 1.4.163 • 01 • Jul 31, 1:54PM • e698241.
export function formatHourlyReleaseName(version, buildNumber, commit, date) {
if (!Number.isInteger(buildNumber) || buildNumber < 1) {
throw new Error(`Hourly build number must be a positive integer: ${buildNumber}`)
}
return [
version.split('-')[0],
String(buildNumber).padStart(2, '0'),
formatReleaseTitleTimestamp(date),
commit.slice(0, 7)
].join(' • ')
}
// Resolve published tags before counting so numbering uses actual base version, not caller’s guess.
export function getHourlyBuildIdentity(
now = new Date(),
{ packageVersion, publishedVersions, releaseNames } = {}
) {
const versionFromPackage =
packageVersion ?? JSON.parse(readFileSync(resolve('package.json'), 'utf8')).version
const commit = execFileSync('git', ['rev-parse', '--short=12', 'HEAD'], {
encoding: 'utf8'
}).trim()
const base = resolveDevChannelBaseVersion(versionFromPackage, publishedVersions ?? [])
const version = createHourlyBuildVersion(base, now)
const buildNumber = nextHourlyBuildNumber(base, releaseNames ?? [])
return {
commit,
version,
buildNumber,
name: formatHourlyReleaseName(version, buildNumber, commit, now)
}
}
if (process.argv[1] && resolve(process.argv[1]) === resolve(import.meta.filename)) {
const identity = getHourlyBuildIdentity(new Date(), {
publishedVersions: readPublishedVersionsFromEnv(),
// Titles are newline separated and contain spaces, so this cannot reuse the
// whitespace split the version list gets.
releaseNames: (process.env.ORCA_HOURLY_RELEASE_NAMES ?? '').split('\n').filter(Boolean)
})
process.stdout.write(
`version=${identity.version}\ncommit=${identity.commit}\nbuild_number=${identity.buildNumber}\nname=${identity.name}\n`
)
}