Skip to content

Commit 8f1f1fe

Browse files
committed
Handle empty lines in Docker event streams
1 parent b782c3f commit 8f1f1fe

File tree

3 files changed

+24
-21
lines changed

3 files changed

+24
-21
lines changed

custom-typings/event-stream.d.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
declare module 'event-stream' {
2-
// Type definitions for event-stream v3.3.2
2+
// Type definitions for event-stream v4.0
33
// Project: https://github.com/dominictarr/event-stream
44
// Definitions by: David Gardiner <https://github.com/flcdrg>
55
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
@@ -8,7 +8,7 @@ declare module 'event-stream' {
88

99
import * as stream from 'stream';
1010

11-
interface MapStream extends stream.Stream {
11+
export interface MapStream extends stream.Stream {
1212
writable: boolean;
1313
readable: boolean;
1414

@@ -22,7 +22,7 @@ declare module 'event-stream' {
2222
/**
2323
* Create a stream from a series of MapStreams
2424
*/
25-
export function pipeline(...streams: MapStream[]): NodeJS.ReadWriteStream;
25+
export function pipeline(...streams: MapStream[]): MapStream;
2626

2727
/**
2828
* Create a through stream from an asynchronous function
@@ -37,6 +37,11 @@ declare module 'event-stream' {
3737
*/
3838
export function mapSync(syncFunction: Function): MapStream;
3939

40+
/**
41+
* Filter elements of the stream.
42+
*/
43+
export function filterSync(syncFunction: (value: any) => boolean): MapStream;
44+
4045
/**
4146
* Break up a stream and reassemble it so that each line is a chunk. matcher may be a String, or a RegExp
4247
*

src/interceptors/docker/docker-build-injection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ const END_OF_STEP_REGEX = /^ ---\u003e [a-z0-9]+\n$/;
218218
* HTTP Toolkit interception noise down to a single clear line, and normalize the step count text
219219
* to match.
220220
*/
221-
export function getBuildOutputPipeline(extraDockerCommandCount: number): NodeJS.ReadWriteStream {
221+
export function getBuildOutputPipeline(extraDockerCommandCount: number): EventStream.MapStream {
222222
let outputToHide: 'none' | 'all' | 'until-next' = 'none';
223223

224224
let totalStepCount = -1;

src/interceptors/docker/docker-networking.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ interface DockerEvent {
2020
};
2121
}
2222

23-
let dockerEventStream: NodeJS.ReadableStream | undefined;
23+
let dockerEventStream: EventStream.MapStream | undefined;
2424

2525
/**
2626
* Get a stream of events from Docker. Although Dockerode will only give us the raw event buffers,
@@ -33,31 +33,29 @@ function getDockerEventStream(docker: Docker) {
3333
if (!dockerEventStream) {
3434
const dockerEventParsingStream = EventStream.pipeline(
3535
EventStream.split(),
36-
EventStream.mapSync((rawLine: Buffer) =>
37-
JSON.parse(rawLine.toString('utf8'))
38-
)
36+
EventStream.mapSync((buffer: Buffer) => buffer.toString('utf8')),
37+
EventStream.filterSync((line: string) => line.length > 0),
38+
EventStream.mapSync((rawLine: string) => JSON.parse(rawLine))
3939
);
4040

4141
// We expose the stream immediately, even though no data is coming yet
4242
dockerEventStream = dockerEventParsingStream;
4343

4444
// This gives us a stream of raw Buffer data. Inside, it contains
4545
// JSON strings, newline separated, which we parse above.
46-
(docker.getEvents() as Promise<stream.Readable>) // Wrong types, it's a raw http.IncomingMessage
47-
.then((rawEventStream) => {
48-
rawEventStream.pipe(dockerEventParsingStream);
49-
rawEventStream.on('error', (e) => {
50-
dockerEventParsingStream?.emit('error', e);
51-
});
52-
rawEventStream.on('close', () => {
53-
dockerEventParsingStream?.end();
54-
dockerEventStream = undefined;
55-
});
56-
})
57-
.catch((e) => {
46+
docker.getEvents().then((rawEventStream) => {
47+
rawEventStream.pipe(dockerEventParsingStream);
48+
rawEventStream.on('error', (e) => {
5849
dockerEventParsingStream?.emit('error', e);
50+
});
51+
rawEventStream.on('close', () => {
52+
dockerEventParsingStream?.end();
5953
dockerEventStream = undefined;
6054
});
55+
}).catch((e) => {
56+
dockerEventParsingStream?.emit('error', e);
57+
dockerEventStream = undefined;
58+
});
6159
}
6260

6361
return dockerEventStream;
@@ -166,7 +164,7 @@ class DockerNetworkMonitor {
166164
constructor(
167165
private docker: Docker,
168166
private proxyPort: number,
169-
private dockerEventStream: NodeJS.ReadableStream
167+
private dockerEventStream: stream.Stream
170168
) {
171169
// We use mobx here to automatically propagate updates whilst avoiding
172170
// unnecessary updates when nothing changes.

0 commit comments

Comments
 (0)