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,64 @@
|
||||
#!/usr/bin/env node
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { createHash, randomUUID } from "node:crypto";
|
||||
import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
||||
import { resolve, relative } from "node:path";
|
||||
|
||||
const root = resolve(import.meta.dirname, "..");
|
||||
const outputFlag = process.argv.indexOf("--output");
|
||||
const output = resolve(root, outputFlag >= 0 ? process.argv[outputFlag + 1] : "release-artifacts");
|
||||
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
|
||||
const command = (program, args) => execFileSync(program, args, { cwd: root, encoding: "utf8", windowsHide: true }).trim();
|
||||
|
||||
const pnpmOutput = process.env.npm_execpath
|
||||
? command(process.execPath, [process.env.npm_execpath, "list", "--prod", "--json", "--depth", "Infinity"])
|
||||
: command("pnpm", ["list", "--prod", "--json", "--depth", "Infinity"]);
|
||||
const listed = JSON.parse(pnpmOutput);
|
||||
const components = new Map();
|
||||
const collect = (dependencies = {}) => {
|
||||
for (const [name, dependency] of Object.entries(dependencies)) {
|
||||
if (dependency.version) components.set(`${name}@${dependency.version}`, { type: "library", name, version: dependency.version, purl: `pkg:npm/${encodeURIComponent(name)}@${dependency.version}` });
|
||||
collect(dependency.dependencies);
|
||||
}
|
||||
};
|
||||
for (const project of listed) collect(project.dependencies);
|
||||
const packageJson = JSON.parse(await readFile(resolve(root, "package.json"), "utf8"));
|
||||
const serialNumber = `urn:uuid:${randomUUID()}`;
|
||||
const sbom = {
|
||||
bomFormat: "CycloneDX",
|
||||
specVersion: "1.6",
|
||||
serialNumber,
|
||||
version: 1,
|
||||
metadata: { component: { type: "application", name: packageJson.name, version: packageJson.version }, tools: { components: [{ type: "application", name: "ProjectBrain release metadata generator", version: "1.0.0" }] } },
|
||||
components: [...components.values()].sort((left, right) => left.purl.localeCompare(right.purl)),
|
||||
};
|
||||
|
||||
const artifactFiles = [];
|
||||
const collectFiles = async (directory) => {
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
const path = resolve(directory, entry.name);
|
||||
if (entry.isDirectory()) await collectFiles(path);
|
||||
else artifactFiles.push({ name: relative(root, path).replaceAll("\\", "/"), digest: { sha256: sha256(await readFile(path)) }, bytes: (await stat(path)).size });
|
||||
}
|
||||
};
|
||||
await collectFiles(resolve(root, "dist"));
|
||||
for (const name of ["Dockerfile.frontend", "Dockerfile.backend", "Dockerfile.unraid", "pnpm-lock.yaml"]) {
|
||||
const path = resolve(root, name);
|
||||
try { artifactFiles.push({ name, digest: { sha256: sha256(await readFile(path)) }, bytes: (await stat(path)).size }); } catch (error) { if (error.code !== "ENOENT") throw error; }
|
||||
}
|
||||
artifactFiles.sort((left, right) => left.name.localeCompare(right.name));
|
||||
const revision = command("git", ["rev-parse", "HEAD"]);
|
||||
const provenance = {
|
||||
predicateType: "https://slsa.dev/provenance/v1",
|
||||
subject: artifactFiles,
|
||||
predicate: {
|
||||
buildDefinition: { buildType: "https://projectbrain.local/build/v1", externalParameters: { node: process.version, packageManager: packageJson.packageManager, revision }, resolvedDependencies: [{ uri: "git+local:projectbrain", digest: { sha1: revision } }] },
|
||||
runDetails: { builder: { id: "https://projectbrain.local/ci" }, metadata: { invocationId: process.env.GITHUB_RUN_ID ?? `local-${revision.slice(0, 12)}`, startedOn: new Date().toISOString(), sourceDirty: command("git", ["status", "--porcelain"]) !== "" } },
|
||||
},
|
||||
sbom: { file: "projectbrain.cdx.json", sha256: sha256(JSON.stringify(sbom)) },
|
||||
};
|
||||
|
||||
await mkdir(output, { recursive: true });
|
||||
await writeFile(resolve(output, "projectbrain.cdx.json"), `${JSON.stringify(sbom, null, 2)}\n`);
|
||||
await writeFile(resolve(output, "projectbrain.provenance.json"), `${JSON.stringify(provenance, null, 2)}\n`);
|
||||
console.log(`Generated ${components.size} component SBOM and provenance for ${artifactFiles.length} artifacts in ${output}.`);
|
||||
Reference in new issue
Block a user