| 1268 | } |
| 1269 | |
| 1270 | private async pullImage (writeStreams: WriteStreams, imageToPull: string, imagePlatform: string | null = null) { |
| 1271 | const pullPolicy = this.argv.pullPolicy; |
| 1272 | const platformArgs = imagePlatform ? ["--platform", imagePlatform] : []; |
| 1273 | const platformSuffix = imagePlatform ? ` (${imagePlatform})` : ""; |
| 1274 | const actualPull = async () => { |
| 1275 | await this.validateCiDependencyProxyServerAuthentication(imageToPull); |
| 1276 | const time = process.hrtime(); |
| 1277 | await Utils.spawn([this.argv.containerExecutable, "pull", imageToPull, ...platformArgs]); |
| 1278 | const endTime = process.hrtime(time); |
| 1279 | writeStreams.stdout(chalk`${this.formattedJobName} {magentaBright pulled} ${imageToPull}${platformSuffix} in {magenta ${prettyHrtime(endTime)}}\n`); |
| 1280 | this.refreshLongRunningSilentTimeout(writeStreams); |
| 1281 | }; |
| 1282 | |
| 1283 | if (pullPolicy === "always") { |
| 1284 | await actualPull(); |
| 1285 | return; |
| 1286 | } |
| 1287 | // The `image inspect` cache check is platform-agnostic — a different-arch |
| 1288 | // variant of the same image name will satisfy it, causing the requested |
| 1289 | // platform to silently differ from what's actually on disk. Force a pull |
| 1290 | // when a specific platform was requested so the matching manifest is |
| 1291 | // guaranteed locally. Pulls are idempotent: if the variant is already |
| 1292 | // cached, `docker pull` short-circuits with "Image is up to date". |
| 1293 | if (imagePlatform) { |
| 1294 | await actualPull(); |
| 1295 | return; |
| 1296 | } |
| 1297 | try { |
| 1298 | await Utils.spawn([this.argv.containerExecutable, "image", "inspect", imageToPull]); |
| 1299 | } catch { |
| 1300 | await actualPull(); |
| 1301 | } |
| 1302 | } |
| 1303 | |
| 1304 | private async initProducerReportsDotenvVariables (writeStreams: WriteStreams, expanded: {[key: string]: string}) { |
| 1305 | const cwd = this.argv.cwd; |