mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 06:35:21 +00:00
135 lines
4.1 KiB
JavaScript
135 lines
4.1 KiB
JavaScript
/**
|
|
* `pnpm reels:ingest <diretório-do-pacote> [--apply]` — C195 ingest of a reel
|
|
* package into the private library of `/campanha`.
|
|
*
|
|
* Runs on the homeserver maintenance image, where the production credentials
|
|
* already live and the package arrives by rsync: the command writes through the
|
|
* Payload Local API (never raw SQL, never a campaign credential on the
|
|
* workstation). Dry-run is the default and validates everything — target,
|
|
* package, S3 — without writing; `--apply` additionally requires the explicit
|
|
* intent flag REELS_INGEST_CONFIRM=1 and refuses a database that does not match
|
|
* the declared TEQO_ENV (fail-closed pair).
|
|
*
|
|
* Runbook (staging first, then production): docs/ops/teqo-1313-deploy.md.
|
|
*/
|
|
import { getPayload } from 'payload'
|
|
|
|
import { dieWithLabel, loadCliEnv } from './lib/cli.mjs'
|
|
import {
|
|
REELS_INGEST_CONFIRM_FLAG,
|
|
assertReelIngestApplyConfirm,
|
|
assertReelIngestTarget,
|
|
parseReelIngestArgs,
|
|
readReelPackage,
|
|
} from './lib/reel-ingest.mjs'
|
|
|
|
import { REEL_PACKAGE_TRANSCRIPT_FILENAME } from '../src/lib/reel.ts'
|
|
import { resolveS3StorageEnv } from '../src/utilities/mediaStorage.ts'
|
|
import {
|
|
findReelBySourceHash,
|
|
ingestReelPackage,
|
|
} from '../src/utilities/reels/reelPackageIngest.ts'
|
|
|
|
loadCliEnv()
|
|
|
|
const die = dieWithLabel('reels:ingest')
|
|
|
|
let args
|
|
try {
|
|
args = parseReelIngestArgs()
|
|
} catch (error) {
|
|
die(error.message)
|
|
}
|
|
|
|
try {
|
|
assertReelIngestApplyConfirm({ apply: args.apply })
|
|
} catch (error) {
|
|
die(error.message)
|
|
}
|
|
|
|
let target
|
|
try {
|
|
target = assertReelIngestTarget()
|
|
} catch (error) {
|
|
die(error.message)
|
|
}
|
|
|
|
let storage
|
|
try {
|
|
storage = resolveS3StorageEnv(process.env)
|
|
} catch (error) {
|
|
die(error.message)
|
|
}
|
|
if (target.environment !== 'test' && !storage.enabled) {
|
|
die(
|
|
`sem S3_* completo no alvo ${target.environment} — a ingestão é uma operação do bucket privado de produção.\n` +
|
|
' O container de manutenção gravaria num disco efêmero; configure as 4 S3_* no env file do ambiente.',
|
|
)
|
|
}
|
|
|
|
let reelPackage
|
|
try {
|
|
reelPackage = await readReelPackage(args.directory)
|
|
} catch (error) {
|
|
die(error.message)
|
|
}
|
|
|
|
const mode = args.apply ? 'apply' : 'dry-run'
|
|
console.log(
|
|
[
|
|
'\n[reels:ingest] Alvo da execução:',
|
|
` TEQO_ENV : ${target.environment}`,
|
|
` DB : ${target.databaseName}`,
|
|
` Bucket : ${storage.enabled ? storage.bucket : '(storage local de teste)'}`,
|
|
` Modo : ${mode}`,
|
|
].join('\n'),
|
|
)
|
|
|
|
const payload = await getPayload({ config: (await import('../src/payload.config.ts')).default })
|
|
const existing = await findReelBySourceHash(payload, reelPackage.metadata.shotListHash)
|
|
|
|
console.log(
|
|
[
|
|
`[reels:ingest] Pacote : ${reelPackage.directory}`,
|
|
` Título : ${reelPackage.metadata.title}`,
|
|
` Feature : ${reelPackage.metadata.feature}`,
|
|
` Hash : ${reelPackage.metadata.shotListHash}`,
|
|
` Operação : ${
|
|
existing === null
|
|
? 'cria uma nova entrada (publicada)'
|
|
: `atualiza o reel #${existing.id} (status atual: ${existing.status})`
|
|
}`,
|
|
].join('\n'),
|
|
)
|
|
|
|
for (const artifact of reelPackage.artifacts) {
|
|
// A missing required artifact never reaches the echo: readReelPackage refuses
|
|
// the package first.
|
|
const action = artifact.present ? `→ ${artifact.kind}` : 'ausente (opcional)'
|
|
console.log(`[reels:ingest] ${artifact.filename.padEnd(16)} ${action}`)
|
|
}
|
|
console.log(
|
|
`[reels:ingest] ${REEL_PACKAGE_TRANSCRIPT_FILENAME.padEnd(16)} ${
|
|
reelPackage.transcriptPath === null ? 'ausente (opcional)' : '→ transcript'
|
|
}`,
|
|
)
|
|
|
|
if (!args.apply) {
|
|
console.log(
|
|
`\n[reels:ingest] dry-run OK — nenhuma escrita. Para aplicar: ${REELS_INGEST_CONFIRM_FLAG}=1 pnpm reels:ingest ${args.directory} --apply`,
|
|
)
|
|
process.exit(0)
|
|
}
|
|
|
|
let result
|
|
try {
|
|
result = await ingestReelPackage(payload, reelPackage)
|
|
} catch (error) {
|
|
die(
|
|
`a escrita falhou (nada parcial ficou visível — a transação foi revertida): ${error?.message ?? String(error)}`,
|
|
)
|
|
}
|
|
console.log(
|
|
`\n[reels:ingest] ${result.operation === 'created' ? 'criado' : 'atualizado'} o reel #${result.reelId} — a biblioteca já reflete o pacote.`,
|
|
)
|
|
process.exit(0)
|