Initial curated projectbrain source from 8a7b1e0651dbdab97d744cbd2e653ab3970ac6c5
This commit is contained in:
commit
5aa3e8d685
700 files changed
+132801
No files matched your search
@@ -0,0 +1,152 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const proofDir = process.env.PROJECTBRAIN_PROOF_ARCHIVE_DIR ?? "checkpoints/release-proof";
|
||||
const signoffDir = process.env.PROJECTBRAIN_SIGNOFF_ARCHIVE_DIR ?? "checkpoints/release-signoff";
|
||||
const deploymentProofDir = process.env.PROJECTBRAIN_DEPLOY_PROOF_ARCHIVE_DIR ?? "checkpoints/deployment-proof";
|
||||
const dossierOut = process.env.PROJECTBRAIN_RELEASE_DOSSIER_OUT;
|
||||
|
||||
const run = (command, args) => spawnSync(command, args, {
|
||||
encoding: "utf8",
|
||||
shell: process.platform === "win32",
|
||||
});
|
||||
|
||||
const getGitCommit = () => {
|
||||
const result = run("git", ["rev-parse", "--short", "HEAD"]);
|
||||
return result.status === 0 ? result.stdout.trim() : "unknown";
|
||||
};
|
||||
|
||||
const parseField = (text, label) => {
|
||||
const match = text.match(new RegExp(`^${label}:\\s*(.+)$`, "m"));
|
||||
return match?.[1]?.trim() ?? "unknown";
|
||||
};
|
||||
|
||||
const displayPath = (filePath) => filePath.split(path.sep).join("/");
|
||||
|
||||
const listMarkdownFiles = (archiveDir) => {
|
||||
if (!fs.existsSync(archiveDir)) return [];
|
||||
|
||||
return fs.readdirSync(archiveDir)
|
||||
.filter((fileName) => fileName.endsWith(".md"))
|
||||
.map((fileName) => path.join(archiveDir, fileName))
|
||||
.filter((filePath) => fs.statSync(filePath).isFile());
|
||||
};
|
||||
|
||||
const sortNewestFirst = (items) => items.sort((a, b) => {
|
||||
const generatedDelta = Date.parse(b.generated) - Date.parse(a.generated);
|
||||
if (Number.isFinite(generatedDelta) && generatedDelta !== 0) return generatedDelta;
|
||||
return b.fileName.localeCompare(a.fileName);
|
||||
});
|
||||
|
||||
const parseArtifact = (filePath, type) => {
|
||||
const text = fs.readFileSync(filePath, "utf8");
|
||||
const generated = parseField(text, "Generated");
|
||||
const commit = type === "deployment"
|
||||
? parseField(text, "Local commit")
|
||||
: parseField(text, "Commit");
|
||||
|
||||
return {
|
||||
type,
|
||||
text,
|
||||
filePath,
|
||||
displayPath: displayPath(filePath),
|
||||
fileName: path.basename(filePath),
|
||||
generated,
|
||||
commit,
|
||||
verdict: parseField(text, "Verdict"),
|
||||
freshness: type === "deployment"
|
||||
? parseField(text, "Commit freshness")
|
||||
: parseField(text, "Freshness"),
|
||||
};
|
||||
};
|
||||
|
||||
const findLatestCurrentArtifact = (archiveDir, type, currentCommit) => {
|
||||
const artifacts = sortNewestFirst(listMarkdownFiles(archiveDir).map((filePath) => parseArtifact(filePath, type)));
|
||||
|
||||
return artifacts.find((artifact) => {
|
||||
if (artifact.commit !== currentCommit) return false;
|
||||
if (type === "proof") return artifact.verdict === "PASS";
|
||||
if (type === "signoff") return artifact.freshness === "current";
|
||||
if (type === "deployment") return artifact.verdict === "PASS" && artifact.freshness === "current";
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
const indentArtifact = (artifact) => artifact.text
|
||||
.split("\n")
|
||||
.map((line) => line ? `> ${line}` : ">")
|
||||
.join("\n");
|
||||
|
||||
const createDefaultDossierPath = (commit) => {
|
||||
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
||||
return `checkpoints/release-dossier/projectbrain-release-dossier-${commit}-${stamp}.md`;
|
||||
};
|
||||
|
||||
const currentCommit = getGitCommit();
|
||||
const proof = findLatestCurrentArtifact(proofDir, "proof", currentCommit);
|
||||
const signoff = findLatestCurrentArtifact(signoffDir, "signoff", currentCommit);
|
||||
const deployment = findLatestCurrentArtifact(deploymentProofDir, "deployment", currentCommit);
|
||||
const missing = [
|
||||
proof ? null : "current passing release proof",
|
||||
signoff ? null : "current release signoff",
|
||||
deployment ? null : "current passing deployment proof",
|
||||
].filter(Boolean);
|
||||
|
||||
if (missing.length) {
|
||||
console.error("Cannot create release evidence dossier: missing required current artifacts.");
|
||||
for (const item of missing) console.error(`- ${item}`);
|
||||
console.error("Run: PROJECTBRAIN_RELEASE_DEPLOYMENT_PROOF=1 pnpm run release:bundle");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const dossierPath = dossierOut || createDefaultDossierPath(currentCommit);
|
||||
const dossier = [
|
||||
"# ProjectBrain Release Evidence Dossier",
|
||||
"",
|
||||
`Generated: ${new Date().toISOString()}`,
|
||||
`Commit: ${currentCommit}`,
|
||||
`Verdict: PASS`,
|
||||
"",
|
||||
"## Included Artifacts",
|
||||
"",
|
||||
"| Artifact | Generated | Source |",
|
||||
"| --- | --- | --- |",
|
||||
`| Release proof | ${proof.generated} | ${proof.displayPath} |`,
|
||||
`| Operator signoff | ${signoff.generated} | ${signoff.displayPath} |`,
|
||||
`| Deployment proof | ${deployment.generated} | ${deployment.displayPath} |`,
|
||||
"",
|
||||
"## Operator Summary",
|
||||
"",
|
||||
"- Release operator smoke suite passed for the current commit.",
|
||||
"- Release proof freshness is current.",
|
||||
"- Operator signoff file exists for the current commit.",
|
||||
"- Remote deployment proof passed for the current commit.",
|
||||
"- Tower health and ProjectBrain containers were proven by the deployment proof.",
|
||||
"",
|
||||
"## Release Proof",
|
||||
"",
|
||||
indentArtifact(proof),
|
||||
"",
|
||||
"## Operator Signoff",
|
||||
"",
|
||||
indentArtifact(signoff),
|
||||
"",
|
||||
"## Remote Deployment Proof",
|
||||
"",
|
||||
indentArtifact(deployment),
|
||||
"",
|
||||
"## Tower Commands",
|
||||
"",
|
||||
"```bash",
|
||||
"cd /mnt/pool/appdata/brain",
|
||||
"docker compose build --no-cache frontend",
|
||||
"docker compose up -d",
|
||||
"```",
|
||||
].join("\n");
|
||||
|
||||
fs.mkdirSync(path.dirname(dossierPath), { recursive: true });
|
||||
fs.writeFileSync(dossierPath, `${dossier}\n`, "utf8");
|
||||
|
||||
console.log(dossier);
|
||||
console.log(`\nRelease evidence dossier written to ${dossierPath}`);
|
||||
Reference in new issue
Block a user