@@ -198,8 +198,34 @@ def _go_sdk_impl(ctx):
198198 host_detected_goos , host_detected_goarch = detect_host_platform (ctx )
199199 toolchains = []
200200
201- sdks_by_version = getattr (ctx , "facts" , None ) or {}
202- used_versions = {}
201+ all_sdks_by_version = {}
202+ used_sdks_by_version = {}
203+ facts = getattr (ctx , "facts" , {})
204+
205+ def get_sdks_by_version_cached (version ):
206+ # Avoid a download without a known digest in the SDK repo rule by fetching the SDKs filename
207+ # and digest here. When using a version of Bazel that supports module extension facts, this
208+ # info will be persisted in the lockfile, allowing for truly airgapped builds with an
209+ # up-to-date lockfile and download (formerly repository) cache.
210+ sdks = facts .get (version )
211+ if sdks == None :
212+ # Lazily fetch the information about all SDKs so that we avoid the download if the facts
213+ # already contain all the versions we care about. We take care to only do this once and
214+ # also accept failures to support airgapped builds: the user may have set sdk hashes on
215+ # all SDK repos they actually intend to use, but others (e.g., the default SDK added by
216+ # rules_go) trigger this path even if they would never be selected by toolchain
217+ # resolution. We must not break those builds.
218+ if not all_sdks_by_version :
219+ all_sdks_by_version .clear ()
220+ all_sdks_by_version .update (fetch_sdks_by_version (ctx , allow_fail = True ))
221+ sdks = all_sdks_by_version .get (version )
222+ if sdks == None :
223+ # This is either caused by an invalid version or because we are in an airgapped build
224+ # and the version wasn't present in facts. Since we don't want to fail in the latter
225+ # case, we leave it to the repository rule to report a useful error message.
226+ return None
227+ used_sdks_by_version [version ] = sdks
228+ return sdks
203229
204230 for module in ctx .modules :
205231 # Apply wrapped toolchains first to override specific platforms from the
@@ -266,9 +292,7 @@ def _go_sdk_impl(ctx):
266292 )
267293
268294 _download_sdk (
269- module_ctx = ctx ,
270- sdks_by_version = sdks_by_version ,
271- used_versions = used_versions ,
295+ get_sdks_by_version = get_sdks_by_version_cached ,
272296 name = name ,
273297 goos = download_tag .goos ,
274298 goarch = download_tag .goarch ,
@@ -307,9 +331,7 @@ def _go_sdk_impl(ctx):
307331 )
308332
309333 _download_sdk (
310- module_ctx = ctx ,
311- sdks_by_version = sdks_by_version ,
312- used_versions = used_versions ,
334+ get_sdks_by_version = get_sdks_by_version_cached ,
313335 name = default_name ,
314336 goos = goos ,
315337 goarch = goarch ,
@@ -381,11 +403,7 @@ def _go_sdk_impl(ctx):
381403
382404 # See _download_sdk below for details on these facts.
383405 if hasattr (ctx , "facts" ):
384- kwargs ["facts" ] = {
385- version : sdk_info
386- for version , sdk_info in sdks_by_version .items ()
387- if version in used_versions
388- }
406+ kwargs ["facts" ] = used_sdks_by_version
389407 return ctx .extension_metadata (** kwargs )
390408 else :
391409 return None
@@ -416,23 +434,11 @@ def _left_pad_zero(index, length):
416434 fail ("index must be non-negative" )
417435 return ("0" * length + str (index ))[- length :]
418436
419- def _download_sdk (* , module_ctx , sdks_by_version , used_versions , name , goos , goarch , download_tag ):
437+ def _download_sdk (* , get_sdks_by_version , name , goos , goarch , download_tag ):
420438 version = download_tag .version
421439 sdks = download_tag .sdks
422440 if version and not sdks :
423- # Avoid a download without a known digest in the SDK repo rule by fetching the SDKs filename
424- # and digest here. When using a version of Bazel that supports module extension facts, this
425- # info will be persisted in the lockfile, allowing for truly airgapped builds with an
426- # up-to-date lockfile and download (formerly repository) cache.
427- if version not in sdks_by_version :
428- # Lazily fetch the information about all SDKs so that we avoid the download if the facts
429- # already contain all the versions we care about.
430- sdks_by_version .clear ()
431- sdks_by_version .update (fetch_sdks_by_version (module_ctx ))
432- if version not in sdks_by_version :
433- fail ("go_sdk: no SDKs found for version {} requested by" .format (version ), download_tag )
434- used_versions [version ] = True
435- sdks = sdks_by_version [version ]
441+ sdks = get_sdks_by_version (version )
436442
437443 go_download_sdk_rule (
438444 name = name ,
0 commit comments