Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions scripts/migration-pr-readiness.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ const POLICY_PATH = 'scripts/migration-readiness-policy.json'
const SQL_PATH = /^supabase\/migrations\/(\d{14})_([A-Za-z0-9_.-]+)\.sql$/
const sha = /^[a-f0-9]{40}$/
const hashBytes = bytes => createHash('sha256').update(bytes).digest('hex')
const requireFact = (condition, message) => { if (!condition) throw new Error(message) }
// `safe` marks our own fixed-text refusals so the job log can name the failed rule; provider/Git errors never carry it.
const requireFact = (condition, message) => { if (!condition) throw Object.assign(new Error(message), { safe: true }) }

// One native Git process reads the corpus; never spawn a process per historical migration.
export function readGitBlobs(git, revision, paths) {
Expand Down Expand Up @@ -228,7 +229,8 @@ async function main() {
if (result.status === 'strict_parity') { console.log('Migration PR historical SQL unchanged; current main/production strict parity VERIFIED.'); return }
console.log(`Migration PR staging VERIFIED; ${result.pending.length} exact registered migration(s) PENDING APPLY. Production was NOT changed. Main remains strict.`)
}
if (invokedDirectly(import.meta.url)) main().catch(() => {
if (invokedDirectly(import.meta.url)) main().catch(error => {
if (error?.safe === true) console.error(`Migration readiness rule refused: ${error.message}`)
// No API body, token, SQL, state or Git command arguments are copied into CI diagnostics.
console.error('Migration PR readiness failed closed; registration, current base/ledger or exact-head staging proof was not satisfied.')
process.exitCode = 1
Expand Down
6 changes: 4 additions & 2 deletions scripts/publish-migration-readiness.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createHash } from 'node:crypto'
const repo = 'hellofrequencylab/frequency-web'
const sha = /^[a-f0-9]{40}$/, digest = /^[a-f0-9]{64}$/
const hash = value => createHash('sha256').update(value).digest('hex')
const requireFact = (condition, message) => { if (!condition) throw Error(message) }
const requireFact = (condition, message) => { if (!condition) throw Object.assign(Error(message), { safe: true }) }
const files = ['scripts/migration-pr-readiness.mjs', 'scripts/publish-migration-readiness.mjs', '.github/workflows/migration-readiness.yml', 'scripts/migration-readiness-policy.json']
export async function publishReadiness({ env, event, api, git, publisherSha256, evaluate }) {
requireFact(env.GITHUB_ACTIONS === 'true' && env.GITHUB_EVENT_NAME === 'pull_request_target' && env.GITHUB_REPOSITORY === repo && env.GITHUB_WORKFLOW_REF === `${repo}/.github/workflows/migration-readiness.yml@refs/heads/main`, 'trusted workflow required')
Expand Down Expand Up @@ -43,7 +43,9 @@ export async function publishReadiness({ env, event, api, git, publisherSha256,
// A branch movement during the API write invalidates even the old-head result.
await current(result.status !== 'not_applicable')
return result
} catch {
} catch (error) {
// Only our own fixed-text rule names are printed; provider, Git and API errors are never serialized.
if (error?.safe === true) console.error(`Migration readiness rule refused: ${error.message}`)
await finish('failure', { title: 'Trusted migration readiness failed closed', summary: 'Evaluation, identity or proof was refused, unavailable or moved. No production SQL was applied. Rerun against the current PR head and main.' })
throw Error('trusted candidate-head readiness failed')
}
Expand Down
Loading