Skip to content

Commit 6e13b63

Browse files
TheLarkInnCopilot
andcommitted
Add two-stage bootstrap event buffer and handoff
Add the self-contained bootstrap machinery for @rushstack/reporter (#5858). install-run-rush must stay zero-dependency and embed a frozen copy of this encoder rather than import the package at runtime, so the source of truth lives here. - Add a frozen protocol-major constant, buffer and chunk limits, and the private handoff environment variable name - Add BootstrapEventBuffer, a bounded 1 MiB encoder that preserves required and diagnostic events on overflow, splits raw external output into 64 KiB chunks, and appends a bufferTruncated extension event describing any loss - Add handoff helpers that write, read, and delete the temporary NDJSON file - Add parseEarlyReporterControls for the prelude - Cover parsing, encoding, overflow, failure, chunking, and handoff with tests Assistant-model: GitHub Copilot Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 897dcf7e-e6e8-4a84-85ca-34b93fa29be3
1 parent 4eac7b2 commit 6e13b63

9 files changed

Lines changed: 813 additions & 1 deletion

File tree

common/reviews/api/reporter.api.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,31 @@
44
55
```ts
66

7+
// @beta
8+
export const BOOTSTRAP_BUFFER_MAX_BYTES: number;
9+
10+
// @beta
11+
export const BOOTSTRAP_BUFFER_TRUNCATED_EXTENSION_NAME: 'rush.reporter.bufferTruncated';
12+
13+
// @beta
14+
export const BOOTSTRAP_EXTERNAL_CHUNK_MAX_BYTES: number;
15+
16+
// @beta
17+
export const BOOTSTRAP_PROTOCOL_MAJOR: number;
18+
19+
// @beta
20+
export class BootstrapEventBuffer {
21+
constructor(options: IBootstrapEventBufferOptions);
22+
addExternalOutput(stream: 'stdout' | 'stderr', text: string): void;
23+
emit(input: IBootstrapEventInput): string;
24+
get failed(): boolean;
25+
serialize(): string;
26+
get truncation(): IBootstrapTruncation;
27+
}
28+
29+
// @beta
30+
export type BootstrapPrivacyClassification = 'public' | 'local-sensitive' | 'secret';
31+
732
// @beta
833
export function computeEnvelopePrivacyFloor(classifications: Iterable<ReporterPrivacyClassification>): ReporterPrivacyClassification;
934

@@ -16,12 +41,48 @@ export const DEFAULT_FLUSH_TIMEOUT_MS: number;
1641
// @beta
1742
export const DEFAULT_SIGNAL_FLUSH_TIMEOUT_MS: number;
1843

44+
// @beta
45+
export function deleteBootstrapHandoffFileAsync(filePath: string): Promise<void>;
46+
1947
// @beta
2048
export function encodeNdjsonRecord(value: unknown, options?: INdjsonOptions): string;
2149

2250
// @beta
2351
export function getPrivacyClassificationRank(classification: ReporterPrivacyClassification): number;
2452

53+
// @beta
54+
export interface IBootstrapEventBufferOptions {
55+
readonly maxBytes?: number;
56+
readonly now?: () => string;
57+
readonly sessionId: string;
58+
readonly source: IBootstrapEventSource;
59+
}
60+
61+
// @beta
62+
export interface IBootstrapEventInput {
63+
readonly payload?: unknown;
64+
readonly privacy?: BootstrapPrivacyClassification;
65+
readonly required: boolean;
66+
readonly type: string;
67+
}
68+
69+
// @beta
70+
export interface IBootstrapEventSource {
71+
// (undocumented)
72+
readonly packageName: string;
73+
// (undocumented)
74+
readonly packageVersion: string;
75+
}
76+
77+
// @beta
78+
export interface IBootstrapTruncation {
79+
readonly droppedOther: number;
80+
readonly droppedReplaceable: number;
81+
readonly droppedRequired: number;
82+
readonly failed: boolean;
83+
readonly truncated: boolean;
84+
}
85+
2586
// @beta
2687
export interface IClassifiedDiagnosticValue {
2788
readonly privacy: ReporterPrivacyClassification;
@@ -42,6 +103,12 @@ export interface ICreateRushDiagnosticOptions {
42103
readonly source?: IRushDiagnosticSource;
43104
}
44105

106+
// @beta
107+
export interface IEarlyReporterControls {
108+
readonly logLevel?: string;
109+
readonly reporter?: string;
110+
}
111+
45112
// @beta
46113
export interface INdjsonOptions {
47114
readonly maxRecordBytes?: number;
@@ -226,6 +293,12 @@ export function isReporterProtocolCompatible(consumer: IReporterProtocolVersion,
226293
// @beta
227294
export function isValidRushDiagnosticCode(code: string): boolean;
228295

296+
// @beta
297+
export interface IWriteBootstrapHandoffOptions {
298+
readonly directory?: string;
299+
readonly pid?: number;
300+
}
301+
229302
// @beta
230303
export class NdjsonDecoder {
231304
constructor(options?: INdjsonOptions);
@@ -242,6 +315,12 @@ export class NdjsonRecordTooLargeError extends Error {
242315
// @beta
243316
export function negotiateReporterHello(hello: IReporterHello, options: IReporterHandshakeOptions): IReporterHandshakeResult;
244317

318+
// @beta
319+
export function parseEarlyReporterControls(argv: readonly string[], env: Record<string, string | undefined>): IEarlyReporterControls;
320+
321+
// @beta
322+
export function readBootstrapHandoffFileAsync(filePath: string): Promise<unknown[]>;
323+
245324
// @beta
246325
export const REPORTER_EVENT_TYPES: readonly ReporterEventType[];
247326

@@ -314,6 +393,9 @@ export const RUSH_DIAGNOSTIC_TEMPLATES: {
314393
// @beta
315394
export const RUSH_INTERNAL_ERROR_CODE: 'RUSH_INTERNAL_UNEXPECTED';
316395

396+
// @beta
397+
export const RUSH_REPORTER_BOOTSTRAP_HANDOFF_ENV_VAR: '_RUSH_REPORTER_BOOTSTRAP_HANDOFF';
398+
317399
// @beta
318400
export type RushDiagnosticCategory = 'configuration' | 'input' | 'dependency-tool' | 'environment' | 'network-auth' | 'operation' | 'internal';
319401

@@ -330,4 +412,7 @@ export class RushError extends Error {
330412
// @beta
331413
export type RushRemediationSafety = 'safe' | 'requires-confirmation' | 'unsafe';
332414

415+
// @beta
416+
export function writeBootstrapHandoffFileAsync(buffer: BootstrapEventBuffer, options?: IWriteBootstrapHandoffOptions): Promise<string>;
417+
333418
```

0 commit comments

Comments
 (0)