Skip to content

Conversation

@gmegidish
Copy link
Member

@gmegidish gmegidish commented Nov 29, 2025

Summary by CodeRabbit

  • New Features

    • Support for configuring a local WebDriverAgent package via environment variable.
  • Refactor

    • Automatic architecture-aware retrieval of WebDriverAgent with GitHub fallback.
    • Streamlined installation flow that prefers local packages, falls back to download, and conditionally cleans temporary files.
    • Improved installation robustness and error handling.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 29, 2025

Walkthrough

Reworked the simulator's WebDriverAgent installation to choose architecture-specific filenames/URLs at runtime, prefer a local WDA when MOBILECLI_WDA_PATH is set, and otherwise download the appropriate ZIP from GitHub; removed the exported DownloadWebDriverAgent method and added internal helpers and conditional cleanup.

Changes

Cohort / File(s) Summary
WebDriverAgent install & download logic
devices/simulator.go
Added runtime GOARCH-based helpers (getWebdriverAgentFilename, getWebdriverAgentDownloadUrl), extracted GitHub download into downloadWebDriverAgentFromGitHub(), changed InstallWebDriverAgent to prefer MOBILECLI_WDA_PATH local file and fall back to GitHub download, added conditional cleanup for downloaded files, improved error wrapping, and removed exported DownloadWebDriverAgent() in favor of non-exported helpers.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Caller as InstallWebDriverAgent
    participant FS as Local Filesystem
    participant Env as MOBILECLI_WDA_PATH
    participant Downloader as GitHub
    participant Unzipper as Unzip Logic

    Caller->>Env: check MOBILECLI_WDA_PATH
    alt local path set
        Caller->>FS: stat path / verify filename
        alt file matches expected filename
            FS-->>Caller: local file path
            Caller->>Unzipper: unzip local file
            Unzipper-->>Caller: success / error
        else file missing or wrong name
            Caller->>Downloader: build arch-specific URL
            Downloader-->>Caller: download ZIP
            Caller->>Unzipper: unzip downloaded ZIP
            Unzipper-->>Caller: success / error
            Caller->>FS: conditional cleanup downloaded ZIP
        end
    else no local path
        Caller->>Downloader: build arch-specific URL
        Downloader-->>Caller: download ZIP
        Caller->>Unzipper: unzip downloaded ZIP
        Unzipper-->>Caller: success / error
        Caller->>FS: cleanup downloaded ZIP
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Inspect architecture mapping (amd64 → x86_64, arm64 → arm64) and URL construction
  • Verify MOBILECLI_WDA_PATH validation, filename checks, and copy semantics
  • Review error wrapping changes (%w usage) and unzip error handling
  • Confirm removal of exported DownloadWebDriverAgent() is safe for callers

Possibly related PRs

Poem

🐰 I nibbled code with nimble paws,

Arch-aware hops without a pause,
Local path first, then GitHub's stream,
ZIPs unwrapped and logs agleam — hooray, build dreams! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature addition: supporting installation of WebDriverAgent (WDA) from a local directory, which is the primary behavioral change in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-install-wda-from-local-directory

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
devices/simulator.go (2)

301-304: Extract hardcoded version to a named constant.

The version v9.15.1 is embedded in the URL string. Extracting it to a constant improves maintainability and makes version updates more visible.

+const webDriverAgentVersion = "v9.15.1"
+
 func getWebdriverAgentDownloadUrl(arch string) string {
 	filename := getWebdriverAgentFilename(arch)
-	return "https://github.com/appium/WebDriverAgent/releases/download/v9.15.1/" + filename
+	return "https://github.com/appium/WebDriverAgent/releases/download/" + webDriverAgentVersion + "/" + filename
 }

346-356: Use streaming copy instead of loading entire file into memory.

os.ReadFile loads the entire WDA zip (~20-50MB) into memory before writing. Using io.Copy with file streams is more memory-efficient.

-			input, err := os.ReadFile(localPath)
+			srcFile, err := os.Open(localPath)
 			if err != nil {
 				_ = os.Remove(tmpFile.Name())
 				return "", fmt.Errorf("failed to read local WebDriverAgent: %w", err)
 			}
+			defer srcFile.Close()
 
-			err = os.WriteFile(tmpFile.Name(), input, 0644)
+			dstFile, err := os.Create(tmpFile.Name())
+			if err != nil {
+				return "", fmt.Errorf("failed to create temp file: %w", err)
+			}
+			defer dstFile.Close()
+
+			_, err = io.Copy(dstFile, srcFile)
 			if err != nil {
 				_ = os.Remove(tmpFile.Name())
 				return "", fmt.Errorf("failed to copy local WebDriverAgent: %w", err)
 			}

This requires adding "io" to the imports.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3bec98 and 1c29608.

📒 Files selected for processing (1)
  • devices/simulator.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
devices/simulator.go (1)
utils/logger.go (1)
  • Verbose (19-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint
🔇 Additional comments (3)
devices/simulator.go (3)

294-299: LGTM!

The architecture mapping correctly translates Go's amd64 to x86_64 for the WDA binary naming convention, with arm64 as the default for Apple Silicon.


306-329: LGTM!

The GitHub download flow correctly handles temp file creation, cleanup on failure, and logs download progress. The silent fallback when file stat fails for logging purposes is acceptable.


367-375: LGTM!

The integration with the new downloadWebDriverAgent method is correct and maintains the existing error handling and cleanup logic.

Comment on lines 339 to 365

tmpFile, err := os.CreateTemp("", "wda-*.zip")
if err != nil {
return "", fmt.Errorf("failed to create temp file: %v", err)
}
_ = tmpFile.Close()

input, err := os.ReadFile(localPath)
if err != nil {
_ = os.Remove(tmpFile.Name())
return "", fmt.Errorf("failed to read local WebDriverAgent: %w", err)
}

err = os.WriteFile(tmpFile.Name(), input, 0644)
if err != nil {
_ = os.Remove(tmpFile.Name())
return "", fmt.Errorf("failed to copy local WebDriverAgent: %w", err)
}

return tmpFile.Name(), nil
}

utils.Verbose("Local WebDriverAgent not found at: %s", localPath)
}

return s.downloadWebDriverAgentFromGitHub()
}

func (s SimulatorDevice) InstallWebDriverAgent(onProgress func(string)) error {
if onProgress != nil {
onProgress("Downloading WebDriverAgent")
}

file, err := s.DownloadWebDriverAgent()
file, err := s.downloadWebDriverAgent()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for any references to the public DownloadWebDriverAgent method
rg -n --type=go '\bDownloadWebDriverAgent\b' -g '!devices/simulator.go'

Repository: mobile-next/mobilecli

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Search in all files including tests
rg -n '\bDownloadWebDriverAgent\b'

Repository: mobile-next/mobilecli

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Read the simulator.go file around the specified lines to see context
wc -l devices/simulator.go

Repository: mobile-next/mobilecli

Length of output: 89


🏁 Script executed:

#!/bin/bash
# Search for all function/method definitions in simulator.go
rg -n '^\s*func.*DownloadWebDriver|^\s*func.*download' devices/simulator.go

Repository: mobile-next/mobilecli

Length of output: 218


🏁 Script executed:

#!/bin/bash
# Search for all exported (capitalized) methods in simulator.go
rg -n '^\s*func.*\(s.*Simulator.*\)\s+[A-Z]' devices/simulator.go

Repository: mobile-next/mobilecli

Length of output: 2289


🏁 Script executed:

#!/bin/bash
# Check git log for changes to DownloadWebDriverAgent
git log --oneline --all -S 'DownloadWebDriverAgent' -- devices/simulator.go | head -20

Repository: mobile-next/mobilecli

Length of output: 87


🏁 Script executed:

#!/bin/bash
# Check the initial commit to see if DownloadWebDriverAgent existed then
git show 88cf9fe:devices/simulator.go | rg -n 'DownloadWebDriverAgent'

Repository: mobile-next/mobilecli

Length of output: 181


🏁 Script executed:

#!/bin/bash
# Check current branch and see what changed
git diff 88cf9fe HEAD -- devices/simulator.go | head -100

Repository: mobile-next/mobilecli

Length of output: 3027


🏁 Script executed:

#!/bin/bash
# Get the specific diff around where DownloadWebDriverAgent was removed
git diff 88cf9fe HEAD -- devices/simulator.go | grep -A 20 -B 5 'DownloadWebDriverAgent' || echo "Method not in diff"

Repository: mobile-next/mobilecli

Length of output: 1844


🏁 Script executed:

#!/bin/bash
# Check if there's a CHANGELOG or deprecation notice
find . -name "CHANGELOG*" -o -name "MIGRATION*" -o -name "BREAKING*" | head -10

Repository: mobile-next/mobilecli

Length of output: 79


🏁 Script executed:

#!/bin/bash
# Check CHANGELOG for mentions of DownloadWebDriverAgent or WebDriverAgent changes
rg -n 'DownloadWebDriverAgent|Breaking|WebDriverAgent' CHANGELOG.md | head -20

Repository: mobile-next/mobilecli

Length of output: 47


Based on my verification, I can now provide the rewritten review comment:

Public API method DownloadWebDriverAgent was removed without deprecation notice or changelog entry.

The exported method DownloadWebDriverAgent that existed in the initial commit has been removed and replaced with a private downloadWebDriverAgent helper. This is a breaking change for external consumers of this package. External code that calls SimulatorDevice.DownloadWebDriverAgent() will fail after this change. Consider either: maintaining backward compatibility by keeping a deprecated public method, or documenting this as a breaking change in the CHANGELOG and migration guide.

🤖 Prompt for AI Agents
In devices/simulator.go around lines 331 to 365, the refactor removed the
exported SimulatorDevice.DownloadWebDriverAgent() public API and replaced it
with a private downloadWebDriverAgent(), which is a breaking change for external
consumers; restore backward compatibility by reintroducing a public
DownloadWebDriverAgent method on SimulatorDevice that simply calls the new
private downloadWebDriverAgent and returns its results, mark the public method
as deprecated in its Go doc (pointing to the new behavior) so callers see the
migration path, and add an entry to the CHANGELOG under "Unreleased" mentioning
the deprecation (or, alternatively, if you intend to break the API, add a clear
breaking-change note to the CHANGELOG and migration guide instead of restoring
the public method).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
devices/simulator.go (2)

301-304: Consider making the WDA version configurable.

The WebDriverAgent version is hardcoded to v9.15.1. Consider making this configurable via an environment variable (e.g., MOBILECLI_WDA_VERSION) or a package-level constant to allow users to specify different versions and make updates easier.

Example implementation:

+const defaultWdaVersion = "v9.15.1"
+
+func getWdaVersion() string {
+	if version := os.Getenv("MOBILECLI_WDA_VERSION"); version != "" {
+		return version
+	}
+	return defaultWdaVersion
+}
+
 func getWebdriverAgentDownloadUrl(arch string) string {
 	filename := getWebdriverAgentFilename(arch)
-	return "https://github.com/appium/WebDriverAgent/releases/download/v9.15.1/" + filename
+	return "https://github.com/appium/WebDriverAgent/releases/download/" + getWdaVersion() + "/" + filename
 }

336-348: Document the MOBILECLI_WDA_PATH environment variable.

The new MOBILECLI_WDA_PATH environment variable enables local WDA installation but isn't documented in the code. Consider adding a comment above the InstallWebDriverAgent method or in a package-level doc comment explaining:

  • The purpose of MOBILECLI_WDA_PATH
  • Expected directory structure (should contain architecture-specific ZIP files)
  • Fallback behavior when not set or file not found

Example:

// InstallWebDriverAgent installs the WebDriverAgent app on the simulator.
// If MOBILECLI_WDA_PATH is set, it will look for the architecture-specific
// WDA bundle in that directory (e.g., WebDriverAgentRunner-Build-Sim-arm64.zip).
// If not found locally, it downloads the appropriate bundle from GitHub releases.
// The onProgress callback is called to report installation progress.
func (s SimulatorDevice) InstallWebDriverAgent(onProgress func(string)) error {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c29608 and d17dc05.

📒 Files selected for processing (1)
  • devices/simulator.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
devices/simulator.go (2)
utils/logger.go (1)
  • Verbose (19-23)
utils/zipfile.go (1)
  • Unzip (12-25)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: lint
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
devices/simulator.go (4)

11-11: LGTM!

The runtime import is correctly added to support architecture detection via runtime.GOARCH.


306-329: LGTM!

The download logic is well-structured with proper error handling and cleanup. The verbose logging provides good visibility into the download process.

Note: This method's success depends on getWebdriverAgentDownloadUrl returning a valid URL, which relies on proper architecture validation (see comment on lines 294-299).


331-366: Local-first installation pattern is well-implemented.

The refactored logic correctly prioritizes a local WDA path and falls back to GitHub download, with appropriate conditional cleanup. The verbose logging provides good visibility into the installation flow.

However, the logic relies on getWebdriverAgentFilename returning valid filenames. If an unsupported architecture is detected, this could construct invalid paths. Ensure architecture validation is added as suggested in the comment on lines 294-299.


370-370: Good improvement to error wrapping.

Changing from %v to %w enables proper error chain unwrapping, which is a Go best practice.

Comment on lines +294 to +299
filename := getWebdriverAgentFilename(arch)
return "https://github.com/appium/WebDriverAgent/releases/download/v9.15.1/" + filename
}

func (s SimulatorDevice) downloadWebDriverAgentFromGitHub() (string, error) {
url := getWebdriverAgentDownloadUrl(runtime.GOARCH)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add validation for unsupported architectures.

The function defaults to arm64 for any architecture that isn't "amd64", which may cause issues if the code runs on unsupported architectures (e.g., "386", "arm", "mips", etc.). Consider adding explicit validation and returning an error for unsupported architectures.

Apply this diff to add validation:

 func getWebdriverAgentFilename(arch string) string {
-	if arch == "amd64" {
+	switch arch {
+	case "amd64":
 		return "WebDriverAgentRunner-Build-Sim-x86_64.zip"
+	case "arm64":
+		return "WebDriverAgentRunner-Build-Sim-arm64.zip"
+	default:
+		// Unsupported architecture
+		return ""
 	}
-	return "WebDriverAgentRunner-Build-Sim-arm64.zip"
 }

Then update the callers to check for empty strings and return appropriate errors.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func getWebdriverAgentFilename(arch string) string {
if arch == "amd64" {
return "WebDriverAgentRunner-Build-Sim-x86_64.zip"
}
return "WebDriverAgentRunner-Build-Sim-arm64.zip"
}
func getWebdriverAgentFilename(arch string) string {
switch arch {
case "amd64":
return "WebDriverAgentRunner-Build-Sim-x86_64.zip"
case "arm64":
return "WebDriverAgentRunner-Build-Sim-arm64.zip"
default:
// Unsupported architecture
return ""
}
}
🤖 Prompt for AI Agents
In devices/simulator.go around lines 294-299, getWebdriverAgentFilename
currently defaults to the arm64 filename for any non-"amd64" arch; change it to
validate supported architectures explicitly (e.g., accept "amd64" and "arm64"
only), return an empty string for unsupported values, and do not silently assume
arm64. Update every caller to check the returned string and return or propagate
a clear error when it is empty (or accept an error type) so unsupported
architectures are handled upstream instead of producing incorrect filenames.

@gmegidish gmegidish merged commit e41cdf6 into main Nov 29, 2025
15 checks passed
@gmegidish gmegidish deleted the feat-install-wda-from-local-directory branch November 29, 2025 13:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants