36 lines
2.7 KiB
JavaScript
36 lines
2.7 KiB
JavaScript
import fs from 'node:fs'
|
|
|
|
const config=JSON.parse(fs.readFileSync('contracts/configuration/kbx.configuration.json','utf8'))
|
|
const artifact=JSON.parse(fs.readFileSync('deploy/kbx/release-artifact.contract.json','utf8'))
|
|
const errors=[]
|
|
|
|
if(!artifact.immutableArtifact)errors.push('release artifact must be immutable across promoted environments')
|
|
if(!artifact.environmentSpecificConfigurationExternal)errors.push('environment configuration must stay outside the promoted artifact')
|
|
if(JSON.stringify(artifact.promotionOrder)!==JSON.stringify(['Staging','Production']))errors.push('promotion order must remain Staging -> Production')
|
|
for(const evidence of ['generated/release-impact.json','generated/configuration-manifest.json','generated/test-scenario-manifest.json','generated/api-manifest.json'])if(!artifact.requiredEvidence.includes(evidence))errors.push(`release artifact evidence missing ${evidence}`)
|
|
const prod=config.environments.find(x=>x.id==='Production')
|
|
for(const gate of ['configuration-validation','migration-dry-run','release-governance'])if(!prod?.requiredGates.includes(gate))errors.push(`Production profile missing gate ${gate}`)
|
|
|
|
for(const env of config.environments){
|
|
const p=`deploy/kbx/environments/${env.id.toLowerCase()}.env.example`
|
|
if(!fs.existsSync(p)){errors.push(`missing environment example ${p}`);continue}
|
|
const text=fs.readFileSync(p,'utf8')
|
|
const envKey=`KBX__Runtime__Environment=${env.id}`
|
|
if(!text.includes(envKey))errors.push(`${p} must pin ${envKey}`)
|
|
if(['Staging','Production'].includes(env.id)&&!text.includes('KBX__Database__MigrationsMode=predeploy'))errors.push(`${p} must use predeploy migrations`)
|
|
if(env.id==='Production'&&!text.includes('KBX__Security__RequireHttps=true'))errors.push('production env example must require HTTPS')
|
|
}
|
|
|
|
const workflow=fs.readFileSync('.gitea/workflows/kbx-quality-gate.yaml','utf8')
|
|
if(!workflow.includes('generated/') && !workflow.includes('generated/configuration-manifest.json'))errors.push('quality gate drift list must include generated configuration manifest')
|
|
if(!workflow.includes('deploy/kbx/'))errors.push('quality gate drift list must include deployment contract outputs')
|
|
const readiness='.gitea/workflows/kbx-release-readiness.yaml'
|
|
if(!fs.existsSync(readiness))errors.push('missing release readiness workflow')
|
|
else {
|
|
const text=fs.readFileSync(readiness,'utf8')
|
|
for(const token of ['validate-kbx.mjs','migration','configuration'])if(!text.toLowerCase().includes(token.toLowerCase()))errors.push(`release readiness workflow missing ${token}`)
|
|
}
|
|
|
|
if(errors.length){console.error('deployment governance FAIL');for(const e of errors)console.error(`- ${e}`);process.exit(1)}
|
|
console.log(`deployment governance PASS: immutable artifact promotion, environments=${config.environments.length}`)
|