Skip to content

Fetch scripts cannot handle a vendor SDK delivered as a .zip (and Android installs one silently) #1

Description

@saimskywalker

The problem

Both generated fetch scripts assume the vendor handed you an already-unpacked
artifact. Vendors very often hand you a .zip instead — one archive containing
the .xcframework, or the .aar plus a README and a sample project.

iOS, local form — refuses outright:

$ tool/fetch_ios_sdk.sh /path/to/AcmeSDK.xcframework.zip
error: not a directory: /path/to/AcmeSDK.xcframework.zip

The download form does unzip (unzip -q "$TMP_DIR/sdk.zip" then
find ... -name '*.xcframework'), so the capability already exists in the
script — it is just not reachable from the local path.

Android, both forms — worse, because it fails silently. The local form only
checks [[ ! -f "$1" ]], so a .zip passes and is copied straight to
android/libs/AcmeSDK.aar. The download form never unzips at all: it curls the
URL to $TMP_DIR/sdk.aar and copies it. Either way you end up with a zip
wearing an .aar extension, sdkPresent in build.gradle.kts reads true,
and the failure surfaces later as a Gradle error about the archive rather than
as "you gave me the wrong file".

Why it matters

This is the first command a new user runs after generating, with whatever the
vendor emailed them. Getting told "not a directory" is survivable; silently
installing a corrupt .aar is the exact failure class this project exists to
remove — a build that looks like it has the SDK and does not.

Suggested approach

In lib/src/templates/script_templates.dart:

  • fetchIosSh — in the local branch, accept a file as well as a directory. If
    it is an archive, unpack it into $TMP_DIR and reuse the existing
    find "$TMP_DIR/unpacked" -maxdepth 3 -type d -name '*.xcframework' | head -1
    logic. Factoring that into an install_from_archive() helper next to
    install_from_dir() keeps both entry points on one code path.
  • fetchAndroidSh — detect an archive in both the local and download branches
    and extract the .aar from it. Error clearly if the archive holds zero or
    more than one .aar rather than picking one.
  • Keep the checksum on the downloaded bytes, not on the extracted file. The
    vendor pins the archive.

One design note worth knowing before you start: an .aar is itself a zip
archive
, so sniffing for the PK magic bytes cannot tell an .aar from a
zip that contains one. Distinguish by listing the entries — a real .aar has
AndroidManifest.xml at the archive root (unzip -l "$f" | grep -q ' AndroidManifest.xml$'
or similar). Say in the PR which test you used and why.

Files involved

  • lib/src/templates/script_templates.dartfetchIosSh, fetchAndroidSh
  • test/generator_test.dart — the lessons the generated code must not lose
    group is where the other script assertions live

How to verify

dart test
dart analyze --fatal-infos

CI also runs bash -n over every generated script, so a syntax slip fails
there. Beyond that, exercise it for real:

dart run bin/binary_sdk_bridge.dart --name acme_ads --org com.example \
  --ios-framework AcmeSDK --android-aar AcmeSDK --out /tmp/gen

mkdir -p /tmp/fake/AcmeSDK.xcframework && (cd /tmp/fake && zip -qr AcmeSDK.xcframework.zip AcmeSDK.xcframework)
/tmp/gen/acme_ads/tool/fetch_ios_sdk.sh /tmp/fake/AcmeSDK.xcframework.zip
ls /tmp/gen/acme_ads/ios/acme_ads/Frameworks/    # AcmeSDK.xcframework should be here

Please paste the generated script diff into the PR — per CONTRIBUTING, the
generated output is the product, and escaping mistakes in a shell template look
fine in the Dart source and wrong in the output.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is needed

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions