Pick the right runner
The tunnel has to run somewhere that can already reach your internal services.GitHub Actions
Tunnels are available on the AI SDET path, which runs generated test code
on MobileBoost devices. Set
mode: ai-sdet on the run-tests action, as
below. See Which runs can use a tunnel.Which runs can use a tunnel
Tunnels work on the AI SDET path:mode: ai-sdet, where MobileBoost runs
generated test code on its own devices. A tunnel terminates on the device host,
so the run has to be on a MobileBoost device for one to exist.
The default mode: gpt-driver runs on a third-party device cloud, which
MobileBoost does not operate and a tunnel cannot reach. Passing tunnel-name
there is an error rather than a silent no-op, so a run never quietly goes ahead
on the public internet while your workflow says otherwise.
What setup-local-tunnel handles for you
- It picks a unique tunnel name per job, derived from the run ID, the attempt number, and the job. Parallel and matrix jobs never collide, and a re-run never collides with the attempt it is replacing.
- It waits until the tunnel is usable before the step finishes, so your tests never start against a tunnel that is not up yet.
- It stops the tunnel in a post step, which runs even when the job fails or is cancelled.
MOBILEBOOST_TUNNEL_NAME for later steps.
Inputs
Other CI providers
Without a ready-made action, do the same three things by hand: unique name, wait for ready, and stop it in a step that always runs.- GitLab CI
- Bitrise
- Jenkins
- CircleCI
MOBILEBOOST_API_KEY as a masked project variable under
Settings > CI/CD > Variables. It is then already in the environment, so
nothing needs to pass it explicitly.after_script runs even when script fails, which is what makes the cleanup
reliable. $CI_JOB_ID is unique per job, so parallel jobs never collide.Give every job a unique tunnel name
A tunnel name identifies one connection. If two jobs use the same name at the same time, the second one is refused rather than silently taking over the first. Build the name from something your CI guarantees is unique:
If you omit
--tunnel-name, mb-local derives one from these variables itself.
A matrix build needs the matrix index too. The run ID alone is shared by every
job in the matrix, so five parallel jobs would fight over one name and four of
them would be refused.
Wait for the tunnel, do not sleep
--wait-for-ready blocks until the tunnel can actually carry traffic, then keeps
running. Use it instead of sleep:
Run a shared tunnel
For teams running many jobs, one long-lived tunnel beats one tunnel per job. It removes tunnel setup from every pipeline, works for cloud-hosted runners, and removes name collisions entirely. Run it on any host inside your network: a small VM, an existing build server, or the box that already hosts staging. It needs no inbound access, so a machine with nothing else exposed is a good home for it.Keep the access key out of your logs
The access key is a credential. Store it in your CI secret store and pass it through the environment rather than--key, so it never appears in a command
line that gets logged.
mb-local never writes the key to its own logs at any verbosity.
Check the exit code
CI should tell a wrong key apart from a network blip.mb-local uses distinct
exit codes so you can:
Full list in the CLI reference.

