Download the image if it does not exist locally. Returns whether it was found.
(self, max_retries: int)
| 1133 | time.sleep(sleep_time) |
| 1134 | |
| 1135 | def try_pull(self, max_retries: int) -> bool: |
| 1136 | """Download the image if it does not exist locally. Returns whether it was found.""" |
| 1137 | command = ["docker", "pull"] |
| 1138 | # --quiet skips printing the progress bar, which does not display well in CI. |
| 1139 | if ui.env_is_truthy("CI"): |
| 1140 | command.append("--quiet") |
| 1141 | command.append(self.spec()) |
| 1142 | if not self.acquired: |
| 1143 | ui.header(f"Acquiring {self.spec()}") |
| 1144 | sleep_time = 1 |
| 1145 | for retry in range(1, max_retries + 1): |
| 1146 | try: |
| 1147 | spawn.runv( |
| 1148 | command, |
| 1149 | stdin=subprocess.DEVNULL, |
| 1150 | stdout=sys.stderr.buffer, |
| 1151 | ) |
| 1152 | self.acquired = True |
| 1153 | break |
| 1154 | except subprocess.CalledProcessError: |
| 1155 | if retry < max_retries: |
| 1156 | # There seems to be no good way to tell what error |
| 1157 | # happened based on error code |
| 1158 | # (https://github.com/docker/cli/issues/538) and we |
| 1159 | # want to print output directly to terminal. |
| 1160 | if build := os.getenv("CI_WAITING_FOR_BUILD"): |
| 1161 | for retry in range(max_retries): |
| 1162 | try: |
| 1163 | build_status = buildkite.get_build_status(build) |
| 1164 | except subprocess.CalledProcessError: |
| 1165 | time.sleep(sleep_time) |
| 1166 | sleep_time = min(sleep_time * 2, 10) |
| 1167 | break |
| 1168 | print(f"Build {build} status: {build_status}") |
| 1169 | if build_status == "failed": |
| 1170 | print( |
| 1171 | f"Build {build} has been marked as failed, exiting hard" |
| 1172 | ) |
| 1173 | sys.exit(1) |
| 1174 | elif build_status == "success": |
| 1175 | break |
| 1176 | assert ( |
| 1177 | build_status == "pending" |
| 1178 | ), f"Unknown build status {build_status}" |
| 1179 | time.sleep(1) |
| 1180 | else: |
| 1181 | print(f"Retrying in {sleep_time}s ...") |
| 1182 | time.sleep(sleep_time) |
| 1183 | sleep_time = min(sleep_time * 2, 10) |
| 1184 | continue |
| 1185 | else: |
| 1186 | break |
| 1187 | return self.acquired |
| 1188 | |
| 1189 | def is_published_if_necessary(self) -> bool: |
| 1190 | """Report whether the image exists on DockerHub & GHCR if it is publishable.""" |