-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathruntime-artifact-helpers.ts
More file actions
117 lines (112 loc) · 4.96 KB
/
Copy pathruntime-artifact-helpers.ts
File metadata and controls
117 lines (112 loc) · 4.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { join } from "node:path"
import { artifactManifestFile } from "@automattic/wp-codebox-core"
import { normalizeJsonValue } from "@automattic/wp-codebox-core/internals"
import type {
ArtifactBundle,
ArtifactManifestFile,
ArtifactPreview,
ArtifactSpec,
ExecutionResult,
LifecycleEvent,
MountSpec,
ObservationResult,
RuntimeCreateSpec,
RuntimeEpisodeTraceRef,
RuntimeInfo,
Snapshot,
} from "@automattic/wp-codebox-core"
import { ArtifactBundleBuilder } from "./artifact-bundle-builder.js"
import { redactArtifactFiles } from "./artifact-bundle-writer.js"
import type { ArtifactRedactor } from "./artifacts.js"
import { browserManifestFiles as browserArtifactManifestFiles, browserRedactionPaths, browserReviewSummary as browserArtifactReviewSummary, type BrowserArtifact } from "./browser-artifacts.js"
import { pluginCheckManifestFiles, redactPluginCheckArtifacts, redactThemeCheckArtifacts, themeCheckManifestFiles, type PluginCheckArtifact, type ThemeCheckArtifact } from "./check-artifacts.js"
import { captureMountDiffs, captureMountedFiles } from "./mounted-artifact-capture.js"
export async function collectPlaygroundArtifacts({
artifactRoot,
browserProbes,
commands,
createdAt,
events,
info,
mounts,
observations,
pluginChecks,
previewInfo,
recordArtifactsCollected,
runtimeId,
snapshots,
spec,
themeChecks,
}: {
artifactRoot: string
browserProbes: BrowserArtifact[]
commands: ExecutionResult[]
createdAt: string
events: LifecycleEvent[]
info: () => Promise<RuntimeInfo>
mounts: MountSpec[]
observations: ObservationResult[]
pluginChecks: PluginCheckArtifact[]
previewInfo: (createdAt: string, holdSeconds: number, commands: ExecutionResult[]) => Promise<ArtifactPreview | undefined>
recordArtifactsCollected: (bundleId: string, createdAt: string, artifactSpec: ArtifactSpec) => void
runtimeId: string
snapshots: Snapshot[]
spec: RuntimeCreateSpec
themeChecks: ThemeCheckArtifact[]
}, artifactSpec: ArtifactSpec = {}): Promise<ArtifactBundle> {
return new ArtifactBundleBuilder({
artifactRoot,
runtimeId,
runtimeCreatedAt: createdAt,
spec,
mounts,
commands,
observations,
snapshots,
events,
info,
previewInfo,
browserReviewSummary: () => browserArtifactReviewSummary(browserProbes),
browserArtifacts: () => browserProbes,
captureMountedFiles: (filesDirectory, redactor) => captureMountedFiles(filesDirectory, mounts, redactor),
captureMountDiffs: (filesDirectory, redactor) => captureMountDiffs(artifactRoot, filesDirectory, mounts, redactor),
redactBrowserArtifacts: (redactor) => redactBrowserArtifacts(artifactRoot, browserProbes, redactor),
redactPluginCheckArtifacts: (redactor) => redactPluginCheckArtifacts(artifactRoot, pluginChecks, redactor),
redactThemeCheckArtifacts: (redactor) => redactThemeCheckArtifacts(artifactRoot, themeChecks, redactor),
browserManifestFiles: () => browserArtifactManifestFiles(artifactRoot, browserProbes),
pluginCheckArtifactPaths: () => pluginChecks.map((check) => check.files.normalized),
themeCheckArtifactPaths: () => themeChecks.map((check) => check.files.normalized),
observationManifestFiles: () => observationManifestFiles(artifactRoot, observations),
pluginCheckManifestFiles: () => pluginCheckManifestFiles(artifactRoot, pluginChecks),
themeCheckManifestFiles: () => themeCheckManifestFiles(artifactRoot, themeChecks),
formatRuntimeLog: () => formatRuntimeLog(events),
formatCommandsLog: (artifactCommands) => formatCommandsLog(artifactCommands),
recordArtifactsCollected,
}).build(artifactSpec)
}
export function formatRuntimeLog(events: LifecycleEvent[]): string {
return events.map((event) => `[${event.timestamp}] ${event.type} ${JSON.stringify(normalizeJsonValue(event.data ?? {}))}`).join("\n") + "\n"
}
export function formatCommandsLog(commands: ExecutionResult[]): string {
return (
commands
.map((command) => {
const header = `[${command.startedAt}] ${command.command} ${command.args.join(" ")}`.trim()
const output = [command.stdout, command.stderr].filter(Boolean).join("\n")
return `${header}\nexitCode=${command.exitCode}\n${output}`
})
.join("\n---\n") + "\n"
)
}
function observationManifestFiles(artifactRoot: string, observations: ObservationResult[]): ArtifactManifestFile[] {
return observations.flatMap((observation) => observation.artifactManifestFiles ??
(observation.artifactRefs ?? [])
.filter((ref): ref is RuntimeEpisodeTraceRef & { path: string } => typeof ref.path === "string" && ref.path.length > 0)
.map((ref) => artifactManifestFile(join(artifactRoot, ref.path), ref.kind, ref.path.endsWith(".json") ? "application/json" : "text/plain")),
)
}
async function redactBrowserArtifacts(artifactRoot: string, browserProbes: BrowserArtifact[], redactor: ArtifactRedactor): Promise<void> {
for (const probe of browserProbes) {
await redactArtifactFiles(artifactRoot, browserRedactionPaths(probe), redactor)
}
}