Files
orca/config/scripts/ci-unit-input-ownership.mjs
T

81 lines
2.3 KiB
JavaScript

import { createHash } from 'node:crypto'
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
export function unitInputSourceDigest(sources) {
return createHash('sha256')
.update(JSON.stringify([...sources].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))))
.digest('hex')
}
function repositoryInput(path) {
return (
typeof path === 'string' &&
/^(?:src|config|tests)\//.test(path) &&
!/[\\*?[\]{}]/.test(path) &&
path
.split('/')
.every((part, index, parts) =>
part === '' ? index === parts.length - 1 : part !== '.' && part !== '..'
)
)
}
export function readUnitInputOwnership(root) {
try {
const manifest = JSON.parse(
readFileSync(join(root, 'config/scripts/ci-unit-input-ownership.json'), 'utf8')
)
return manifest?.version === 1 && Array.isArray(manifest.records) ? manifest.records : []
} catch {
return []
}
}
export function checkUnitInputOwnership(
records,
sourceClosure,
env = process.env,
contextSha256 = unitInputSourceDigest(new Map())
) {
const checked = new Map()
if (!Array.isArray(records)) {
return checked
}
const counts = new Map()
for (const record of records) {
if (typeof record?.file === 'string') {
counts.set(record.file, (counts.get(record.file) ?? 0) + 1)
}
}
for (const record of records) {
if (!record || typeof record !== 'object') {
continue
}
const { file, inputs, emptyEnv, sourceClosureSha256, reason } = record
if (
counts.get(file) !== 1 ||
!repositoryInput(file) ||
file.endsWith('/') ||
!Array.isArray(inputs) ||
!inputs.every(repositoryInput) ||
!Array.isArray(emptyEnv) ||
!emptyEnv.every((name) => typeof name === 'string' && /^[A-Z][A-Z0-9_]*$/.test(name)) ||
emptyEnv.some((name) => Boolean(env[name])) ||
typeof reason !== 'string' ||
!reason.trim() ||
typeof sourceClosureSha256 !== 'string' ||
!/^[a-f0-9]{64}$/.test(sourceClosureSha256) ||
record.contextSha256 !== contextSha256
) {
continue
}
const sources = sourceClosure(file)
if (!sources || !sources.has(file) || unitInputSourceDigest(sources) !== sourceClosureSha256) {
continue
}
checked.set(file, { inputs })
}
return checked
}