16
16
17
17
import { ChildProcessByStdio , spawn } from 'child_process' ;
18
18
import fs from 'fs' ;
19
- import { Readable , Writable } from 'node:stream' ;
20
19
import os from 'os' ;
21
20
import path from 'path' ;
21
+ import { Readable , Writable } from 'stream' ;
22
22
import * as core from '@actions/core' ;
23
23
24
24
import { Buildx } from './buildx' ;
@@ -92,14 +92,29 @@ export class History {
92
92
} ) ;
93
93
await Exec . exec ( 'mkfifo' , [ buildxOutFifoPath ] ) ;
94
94
95
- const buildxCmd = await this . buildx . getCommand ( [ '--builder' , builderName , 'dial-stdio' ] ) ;
96
- const buildxDialStdioProc = History . spawn ( buildxCmd . command , buildxCmd . args ) ;
95
+ const buildxDialStdioCmd = await this . buildx . getCommand ( [ '--builder' , builderName , 'dial-stdio' ] ) ;
96
+ core . info ( `[command]${ buildxDialStdioCmd . command } ${ buildxDialStdioCmd . args . join ( ' ' ) } ` ) ;
97
+ const buildxDialStdioProc = spawn ( buildxDialStdioCmd . command , buildxDialStdioCmd . args , {
98
+ stdio : [ 'pipe' , 'pipe' , 'inherit' ] ,
99
+ detached : true
100
+ } ) ;
101
+ let buildxDialStdioKilled = false ;
97
102
fs . createReadStream ( buildxInFifoPath ) . pipe ( buildxDialStdioProc . stdin ) ;
98
103
buildxDialStdioProc . stdout . pipe ( fs . createWriteStream ( buildxOutFifoPath ) ) ;
104
+ buildxDialStdioProc . on ( 'exit' , ( code , signal ) => {
105
+ buildxDialStdioKilled = true ;
106
+ if ( signal ) {
107
+ core . info ( `Process "buildx dial-stdio" was killed with signal ${ signal } ` ) ;
108
+ } else {
109
+ core . info ( `Process "buildx dial-stdio" exited with code ${ code } ` ) ;
110
+ }
111
+ } ) ;
99
112
100
113
const tmpDockerbuildFilename = path . join ( outDir , 'rec.dockerbuild' ) ;
101
114
const summaryFilename = path . join ( outDir , 'summary.json' ) ;
102
115
116
+ let dockerRunProc : ChildProcessByStdio < Writable , Readable , null > | undefined ;
117
+ let dockerRunProcKilled = false ;
103
118
await new Promise < void > ( ( resolve , reject ) => {
104
119
const ebargs : Array < string > = [ '--ref-state-dir=/buildx-refs' , `--node=${ builderName } /${ nodeName } ` ] ;
105
120
for ( const ref of refs ) {
@@ -112,13 +127,17 @@ export class History {
112
127
ebargs . push ( `--gid=${ process . getgid ( ) } ` ) ;
113
128
}
114
129
// prettier-ignore
115
- const dockerRunProc = History . spawn ( 'docker' , [
130
+ const dockerRunArgs = [
116
131
'run' , '--rm' , '-i' ,
117
132
'-v' , `${ Buildx . refsDir } :/buildx-refs` ,
118
133
'-v' , `${ outDir } :/out` ,
119
134
opts . image || History . EXPORT_TOOL_IMAGE ,
120
135
...ebargs
121
- ] ) ;
136
+ ]
137
+ core . info ( `[command]docker ${ dockerRunArgs . join ( ' ' ) } ` ) ;
138
+ dockerRunProc = spawn ( 'docker' , dockerRunArgs , {
139
+ stdio : [ 'pipe' , 'pipe' , 'inherit' ]
140
+ } ) ;
122
141
fs . createReadStream ( buildxOutFifoPath ) . pipe ( dockerRunProc . stdin ) ;
123
142
dockerRunProc . stdout . pipe ( fs . createWriteStream ( buildxInFifoPath ) ) ;
124
143
dockerRunProc . on ( 'close' , code => {
@@ -129,16 +148,35 @@ export class History {
129
148
resolve ( ) ;
130
149
}
131
150
} else {
132
- reject ( new Error ( `Process "docker run" exited with code ${ code } ` ) ) ;
151
+ reject ( new Error ( `Process "docker run" closed with code ${ code } ` ) ) ;
133
152
}
134
153
} ) ;
135
154
dockerRunProc . on ( 'error' , err => {
136
- core . error ( `Error executing buildx dial-stdio : ${ err } ` ) ;
155
+ core . error ( `Error executing "docker run" : ${ err } ` ) ;
137
156
reject ( err ) ;
138
157
} ) ;
139
- } ) . catch ( err => {
140
- throw err ;
141
- } ) ;
158
+ dockerRunProc . on ( 'exit' , ( code , signal ) => {
159
+ dockerRunProcKilled = true ;
160
+ if ( signal ) {
161
+ core . info ( `Process "docker run" was killed with signal ${ signal } ` ) ;
162
+ } else {
163
+ core . info ( `Process "docker run" exited with code ${ code } ` ) ;
164
+ }
165
+ } ) ;
166
+ } )
167
+ . catch ( err => {
168
+ throw err ;
169
+ } )
170
+ . finally ( ( ) => {
171
+ if ( buildxDialStdioProc && ! buildxDialStdioKilled ) {
172
+ core . debug ( 'Force terminating "buildx dial-stdio" process' ) ;
173
+ buildxDialStdioProc . kill ( 'SIGKILL' ) ;
174
+ }
175
+ if ( dockerRunProc && ! dockerRunProcKilled ) {
176
+ core . debug ( 'Force terminating "docker run" process' ) ;
177
+ dockerRunProc . kill ( 'SIGKILL' ) ;
178
+ }
179
+ } ) ;
142
180
143
181
let dockerbuildFilename = `${ GitHub . context . repo . owner } ~${ GitHub . context . repo . repo } ~${ refs [ 0 ] . substring ( 0 , 6 ) . toUpperCase ( ) } ` ;
144
182
if ( refs . length > 1 ) {
@@ -162,11 +200,4 @@ export class History {
162
200
refs : refs
163
201
} ;
164
202
}
165
-
166
- private static spawn ( command : string , args ?: ReadonlyArray < string > ) : ChildProcessByStdio < Writable , Readable , null > {
167
- core . info ( `[command]${ command } ${ args ? ` ${ args . join ( ' ' ) } ` : '' } ` ) ;
168
- return spawn ( command , args || [ ] , {
169
- stdio : [ 'pipe' , 'pipe' , 'inherit' ]
170
- } ) ;
171
- }
172
203
}
0 commit comments