Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
pull_request:
branches:
- main
- next
workflow_dispatch:

jobs:
Expand Down
50 changes: 50 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: release-please
on:
push:
branches:
- next

concurrency:
group: release-please-next
cancel-in-progress: false

permissions:
contents: write
pull-requests: write

jobs:
release-please:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false

- uses: googleapis/release-please-action@v4
id: release
with:
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
target-branch: next
config-file: release-please-config.json
manifest-file: .release-please-manifest.json

# release-please tags/releases the existing `next` commit in place; it
# does not itself update `main`. Once a release actually landed, fast
# forward `main` to that commit so `main` always reflects the latest
# released state. This never force-pushes: `git push <ref>:main`
# without `-f` is rejected by git/GitHub if it isn't a fast-forward,
# so a divergent `main` fails loudly instead of being overwritten.
- name: Fast-forward main to the released next commit
if: steps.release.outputs.releases_created == 'true'
env:
GH_TOKEN: ${{ secrets.RELEASE_PLEASE_TOKEN }}
run: |
set -euo pipefail
git fetch origin next main
if ! git merge-base --is-ancestor origin/main origin/next; then
echo "::error::origin/main is not an ancestor of origin/next — refusing to fast-forward" >&2
exit 1
fi
git push "https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git" origin/next:main
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "5.2.0"
".": "5.3.0"
}
5 changes: 1 addition & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
configured_endpoints: 150
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/droidrun/droidrun-cloud-7cec88e5c0ed1f90579cbbf740bb13588e96f075f10beec368d52a977260a9d9.yml
openapi_spec_hash: 91e423c7355759d210dbbaa040fc1313
config_hash: 0636636df2adbdea4b2e982ab5c858d4
configured_endpoints: 217
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 5.3.0 (2026-08-20)

Full Changelog: [v5.2.0...v5.3.0](https://github.com/droidrun/mobilerun-sdk-python/compare/v5.2.0...v5.3.0)

### Features

* **bootstrap:** repo-driven STLC pipeline ([8bd21c0](https://github.com/droidrun/mobilerun-sdk-python/commit/8bd21c08cd24053976d4fe7e3b15717b3f30379a))


### Bug Fixes

* **ci:** serialize release-please, ff main, drop prerelease ([332dcb7](https://github.com/droidrun/mobilerun-sdk-python/commit/332dcb7a384078489bae09fb7005a15b72b86246))

## 5.2.0 (2026-08-13)

Full Changelog: [v5.1.0...v5.2.0](https://github.com/droidrun/mobilerun-sdk-python/compare/v5.1.0...v5.2.0)
Expand Down
41 changes: 22 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@ Use the Mobilerun MCP Server to enable AI assistants to interact with this API,

## Documentation

The REST API documentation can be found on [docs.mobilerun.ai](https://docs.mobilerun.ai). The full API of this library can be found in [api.md](api.md).
The full API of this library can be found in [api.md](api.md).

## Installation

```sh
# install from PyPI
pip install mobilerun-sdk
# install from the production repo
pip install git+ssh://git@github.com/droidrun/mobilerun-sdk-python.git
```

> [!NOTE]
> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install mobilerun-sdk`

## Usage

The full API of this library can be found in [api.md](api.md).
Expand All @@ -41,11 +44,11 @@ client = Mobilerun(
api_key=os.environ.get("MOBILERUN_CLOUD_API_KEY"), # This is the default and can be omitted
)

tasks = client.tasks.list()
print(tasks.items)
devices = client.devices.list()
print(devices.items)
```

While you can provide a `api_key` keyword argument,
While you can provide an `api_key` keyword argument,
we recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)
to add `MOBILERUN_CLOUD_API_KEY="My API Key"` to your `.env` file
so that your API Key is not stored in source control.
Expand All @@ -65,8 +68,8 @@ client = AsyncMobilerun(


async def main() -> None:
tasks = await client.tasks.list()
print(tasks.items)
devices = await client.devices.list()
print(devices.items)


asyncio.run(main())
Expand All @@ -81,8 +84,8 @@ By default, the async client uses `httpx` for HTTP requests. However, for improv
You can enable this by installing `aiohttp`:

```sh
# install from PyPI
pip install mobilerun-sdk[aiohttp]
# install from the production repo
pip install 'mobilerun-sdk[aiohttp] @ git+ssh://git@github.com/droidrun/mobilerun-sdk-python.git'
```

Then you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:
Expand All @@ -99,8 +102,8 @@ async def main() -> None:
api_key=os.environ.get("MOBILERUN_CLOUD_API_KEY"), # This is the default and can be omitted
http_client=DefaultAioHttpClient(),
) as client:
tasks = await client.tasks.list()
print(tasks.items)
devices = await client.devices.list()
print(devices.items)


asyncio.run(main())
Expand Down Expand Up @@ -172,7 +175,7 @@ from mobilerun_sdk import Mobilerun
client = Mobilerun()

try:
client.tasks.list()
client.devices.list()
except mobilerun_sdk.APIConnectionError as e:
print("The server could not be reached")
print(e.__cause__) # an underlying Exception, likely raised within httpx.
Expand Down Expand Up @@ -215,7 +218,7 @@ client = Mobilerun(
)

# Or, configure per-request:
client.with_options(max_retries=5).tasks.list()
client.with_options(max_retries=5).devices.list()
```

### Timeouts
Expand All @@ -238,7 +241,7 @@ client = Mobilerun(
)

# Override per-request:
client.with_options(timeout=5.0).tasks.list()
client.with_options(timeout=5.0).devices.list()
```

On timeout, an `APITimeoutError` is thrown.
Expand Down Expand Up @@ -279,11 +282,11 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to
from mobilerun_sdk import Mobilerun

client = Mobilerun()
response = client.tasks.with_raw_response.list()
response = client.devices.with_raw_response.list()
print(response.headers.get('X-My-Header'))

task = response.parse() # get the object that `tasks.list()` would have returned
print(task.items)
device = response.parse() # get the object that `devices.list()` would have returned
print(device.items)
```

These methods return an [`APIResponse`](https://github.com/droidrun/mobilerun-sdk-python/tree/main/src/mobilerun_sdk/_response.py) object.
Expand All @@ -297,7 +300,7 @@ The above interface eagerly reads the full response body when you make the reque
To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.

```python
with client.tasks.with_streaming_response.list() as response:
with client.devices.with_streaming_response.list() as response:
print(response.headers.get("X-My-Header"))

for line in response.iter_lines():
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ or products provided by Mobilerun, please follow the respective company's securi

### Mobilerun Terms and Policies

Please contact support@droidrun.ai for any questions or concerns regarding the security of our services.
Please contact lucius@droidrun.ai for any questions or concerns regarding the security of our services.

---

Expand Down
Loading