chore: import upstream snapshot with attribution
Test Browser Use CLI Install / uv pip install (macos-latest) (push) Waiting to run
Test Browser Use CLI Install / uv pip install (windows-latest) (push) Waiting to run
Test Browser Use CLI Install / uv pip install (ubuntu-latest) (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use from local wheel (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use[cli] from PyPI (push) Failing after 1s
package / pip-install-on-macos-latest-py-3.11 (push) Has been skipped
package / pip-install-on-macos-latest-py-3.13 (push) Has been skipped
package / pip-install-on-ubuntu-latest-py-3.11 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.13 (push) Has been skipped
cloud_evals / trigger_cloud_eval_image_build (push) Failing after 1s
docker / build_publish_image (push) Failing after 1s
Test Browser Use CLI Install / browser-use skill sync (push) Failing after 1s
lint / code-style (push) Failing after 0s
lint / type-checker (push) Failing after 1s
package / pip-build (push) Failing after 1s
lint / syntax-errors (push) Failing after 3s
package / pip-install-on-ubuntu-latest-py-3.13 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.11 (push) Has been skipped
test / ${{ matrix.test_filename }} (push) Has been skipped
test / evaluate-tasks (push) Has been skipped
test / setup-chromium (push) Failing after 2s
test / find_tests (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:02:32 +08:00
commit 4cd2d4af2b
475 changed files with 121829 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
66b3c26df51adec32d42c3b2c0304e0662457298
2be4ba4f7078d47bbeed04baf6f8fb04017df028
+8
View File
@@ -0,0 +1,8 @@
# Contributing to browser-use
We love contributions! Please read through these links to get started:
- 🔢 [Contribution Guidelines](https://docs.browser-use.com/development/contribution-guide)
- 👾 [Local Development Setup Guide](https://docs.browser-use.com/development/local-setup)
- 🏷️ [Issues Tagged: `#help-wanted`](https://github.com/browser-use/browser-use/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22)
- 🔌 [Integration Example Guidelines](../examples/integrations/README.md)
@@ -0,0 +1,114 @@
name: 🎯 AI Agent ✚ Page Interaction Issue
description: Agent fails to detect, click, scroll, input, or otherwise interact with some type of element on some page(s)
labels: ["bug", "element-detection"]
title: "Interaction Issue: ..."
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please fill out the form below to help us reproduce and fix the issue.
- type: markdown
attributes:
value: |
---
> [!IMPORTANT]
> 🙏 Please **go check *right now before filling this out* that that you are *actually* on the [⬆️ LATEST VERSION](https://github.com/browser-use/browser-use/releases)**.
> 🚀 We ship changes every hour and we might've already fixed your issue today!
> <a href="https://github.com/browser-use/browser-use/releases"><img src="https://github.com/user-attachments/assets/4cd34ee6-bafb-4f24-87e2-27a31dc5b9a4" width="500px"/></a>
> If you are running an old version, the **first thing we will ask you to do is *upgrade to the latest version* and try again**:
> - 🆕 [`beta`](https://docs.browser-use.com/development/local-setup): `uv pip install --upgrade git+https://github.com/browser-use/browser-use.git@main`
> - 📦 [`stable`](https://pypi.org/project/browser-use/#history): `uv pip install --upgrade browser-use`
- type: input
id: version
attributes:
label: Browser Use Version
description: |
What version of `browser-use` are you using? (Run `uv pip show browser-use` or `git log -n 1`)
**DO NOT JUST WRITE `latest release` or `main` or a very old version or we will close your issue!**
placeholder: "e.g. 0.4.45 or 62760baaefd"
validations:
required: true
- type: input
id: model
attributes:
label: LLM Model
description: Which LLM model are you using?
placeholder: "e.g. bu-1.0, gpt-5-mini, claude-4-5-sonnet, gemini-2.0-flash, etc."
validations:
required: true
- type: textarea
id: prompt
attributes:
label: Screenshots, Description, and task prompt given to Agent
description: |
A description of the issue + screenshots, and the full task prompt you're giving the agent (redact sensitive data).
To help us fix it even faster, screenshot the Chome devtools [`Computed Styles` pane](https://developer.chrome.com/docs/devtools/css/reference#computed) for each failing element.
placeholder: |
🎯 High-level goal: Compare the prices of 3 items on a few different seller pages
💬 Agent(task='''
1. go to https://example.com and click the "xyz" dropdown
2. type "abc" into search then select the "abc" option <- ❌ agent fails to select this option
3. ...
☝️ please include real URLs 🔗 and screenshots 📸 when possible!
validations:
required: true
- type: textarea
id: html
attributes:
label: "HTML around where it's failing"
description: A snippet of the HTML from the failing page around where the Agent is failing to interact.
render: html
placeholder: |
<form na-someform="abc"> <!-- ⬅️ at least one parent element above -->
<div class="element-to-click">
<div data-isbutton="true">Click me</div>
</div>
<input id="someinput" name="someinput" type="text" /> <!-- ⬅️ failing element -->
...
</form>
validations:
required: true
- type: input
id: os
attributes:
label: Operating System & Browser Versions
description: What operating system and browser are you using?
placeholder: "e.g. Ubuntu 24.04 + playwright chromium v136, Windows 11 + Chrome.exe v133, macOS ..."
validations:
required: false
- type: textarea
id: code
attributes:
label: Python Code Sample
description: Include some python code that reproduces the issue
render: python
placeholder: |
from dotenv import load_dotenv
load_dotenv() # tip: always load_dotenv() before other imports
from browser_use import Agent, BrowserSession, Tools
from browser_use.llm import ChatOpenAI
agent = Agent(
task='...',
llm=ChatOpenAI(model="gpt-4.1"),
browser_session=BrowserSession(headless=False),
)
...
- type: textarea
id: logs
attributes:
label: Full DEBUG Log Output
description: Please copy and paste the *full* log output *from the start of the run*. Make sure to set `BROWSER_USE_LOGGING_LEVEL=DEBUG` in your `.env` or shell environment.
render: shell
placeholder: |
$ python /app/browser-use/examples/browser/real_browser.py
DEBUG [browser] 🌎 Initializing new browser
DEBUG [agent] Version: 0.1.46-9-g62760ba, Source: git
+77
View File
@@ -0,0 +1,77 @@
name: 👾 Library Bug Report
description: Report a bug in the browser-use Python library
labels: ["bug", "triage"]
title: "Bug: ..."
body:
# - type: markdown
# attributes:
# value: |
# Thanks for taking the time to fill out this bug report! Please fill out the form below to help us reproduce and fix the issue.
- type: input
id: version
attributes:
label: Browser Use Version
description: |
What exact version of `browser-use` are you using? (Run `uv pip show browser-use` or `git log -n 1`)
**DO NOT WRITE `latest release` or `main` or a very old version or we will close your issue!**
placeholder: "e.g. 0.4.45 or 62760baaefd"
validations:
required: true
- type: textarea
id: description
attributes:
label: Bug Description, Steps to Reproduce, Screenshots
description: A clear and concise description of what the bug is + steps taken, drag screenshots in showing any error messages and relevant pages.
placeholder: |
1. Installed browser-use library by running: `uv pip install browser-use`
2. Installed the browser by running: `playwright install chromium --with-deps`
3. Ran the code below with the following prompt: `go to example.com and do xyz...`
4. Agent crashed and showed the following error: ...
validations:
required: true
- type: textarea
id: code
attributes:
label: Failing Python Code
description: Include the exact python code you ran that encountered the issue, redact any sensitive URLs and API keys.
render: python
placeholder: |
from dotenv import load_dotenv
load_dotenv() # tip: always load_dotenv() before other imports
from browser_use import Agent, BrowserSession, Tools
from browser_use.llm import ChatOpenAI
agent = Agent(
task='...',
llm=ChatOpenAI(model="gpt-4.1-mini"),
browser_session=BrowserSession(headless=False),
)
...
- type: input
id: model
attributes:
label: LLM Model
description: Which LLM model are you using? (Optional)
placeholder: "e.g. ChatBrowserUse, gpt-4.1-mini, gemini-3-flash-preview, etc."
- type: input
id: os
attributes:
label: Operating System & Browser Versions
description: What operating system and browser are you using? (Optional)
placeholder: "e.g. Ubuntu 24.04 + playwright chromium v136, Windows 11 + Chrome.exe v133, macOS ..."
- type: textarea
id: logs
attributes:
label: Full DEBUG Log Output
description: Please copy and paste the log output. Make sure to set `BROWSER_USE_LOGGING_LEVEL=DEBUG` in your `.env` or shell environment.
render: shell
placeholder: |
$ python /app/browser-use/examples/browser/real_browser.py
DEBUG [browser] 🌎 Initializing new browser
@@ -0,0 +1,93 @@
name: 💡 New Feature or Enhancement Request
description: Suggest an idea or improvement for the browser-use library or Agent capabilities
title: "Feature Request: ..."
type: 'Enhancement'
labels: ['enhancement']
body:
- type: textarea
id: current_problem
attributes:
label: "What is the problem that your feature request solves?"
description: |
Describe the problem or need that your feature request solves, include screenshots and example URLs if relevant.
placeholder: |
e.g. I need to be able to simulate dragging in a circle to test the paint feature on a drawing site: https://example.com/draw
validations:
required: true
- type: textarea
id: proposed_solution
attributes:
label: "What is your proposed solution?"
description: |
Describe the ideal specific solution you'd want, *and whether it fits into any broader scope of changes*.
placeholder: |
e.g. I want to add a default action that can hover/drag the mouse on a path when given a series
of x,y coordinates. More broadly it may be useful add a computer-use/x,y-coordinate-style automation
method fallback that can do complex mouse movements.
validations:
required: true
- type: textarea
id: workarounds_tried
attributes:
label: "What hacks or alternative solutions have you tried to solve the problem?"
description: |
A description of any troubleshooting, alternative approaches, workarounds, or other ideas you've considered to fix the problem.
placeholder: |
e.g. I tried upgrading to the latest version and telling it to hover in the prompt. I also tried
telling the agent to ask for human help (using a custom tools action) when it gets to this
step, then I manually click a browser extension in the navbar that automates the mouse movevement.
validations:
required: false
- type: input
id: version
attributes:
label: What version of browser-use are you currently using?
description: |
Run `uv pip show browser-use` or `git log -n 1` and share the exact number or git hash. DO NOT JUST ENTER `latest release` OR `main`.
We need to know what version of the browser-use library you're running in order to contextualize your feature request.
Sometimes features are already available and just need to be enabled with config on certain versions.
placeholder: "e.g. 0.1.48 or 62760baaefd"
validations:
required: true
- type: markdown
attributes:
value: |
---
> [!IMPORTANT]
> 🙏 Please **go check *right now before filling this out* that that you have tried the [⬆️ LATEST VERSION](https://github.com/browser-use/browser-use/releases)**.
> 🚀 We ship *hundreds* of improvements a day and we might've already added a solution to your need yesterday!
> <a href="https://github.com/browser-use/browser-use/releases"><img src="https://github.com/user-attachments/assets/4cd34ee6-bafb-4f24-87e2-27a31dc5b9a4" width="500px"/></a>
> If you are running an old version, the **first thing we will ask you to do is *try the latest `beta`***:
> - 🆕 [`beta`](https://docs.browser-use.com/development/local-setup): `uv pip install --upgrade git+https://github.com/browser-use/browser-use.git@main`
> - 📦 [`stable`](https://pypi.org/project/browser-use/#history): `pip install --upgrade browser-use`
- type: checkboxes
id: priority
attributes:
label: "How badly do you want this new feature?"
options:
- label: "It's an urgent deal-breaker, I can't live without it"
required: false
- label: "It's important to add it in the near-mid term future"
required: false
- label: "It would be nice to add it sometime in the next 2 years"
required: false
- label: "💪 I'm willing to [start a PR](https://docs.browser-use.com/development/contribution-guide) to work on this myself"
required: false
- label: "💼 My company would spend >$5k on [Browser-Use Cloud](https://browser-use.com) if it solved this reliably for us"
required: false
- type: markdown
attributes:
value: |
---
> [!TIP]
> Start conversations about your feature request in other places too, the more
> 📣 hype we see around a request the more likely we are to add it!
>
> - 👾 Discord: [https://link.browser-use.com/discord](https://link.browser-use.com/discord)
> - 𝕏 Twitter: [https://x.com/browser_use](https://x.com/browser_use)
+55
View File
@@ -0,0 +1,55 @@
name: 📚 Documentation Issue
description: Report an issue in the browser-use documentation
labels: ["documentation"]
title: "Documentation: ..."
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to improve our documentation! Please fill out the form below to help us fix the issue quickly.
- type: dropdown
id: type
attributes:
label: Type of Documentation Issue
description: What type of documentation issue is this?
options:
- Missing documentation
- Incorrect documentation
- Unclear documentation
- Broken link
- Other (specify in description)
validations:
required: true
- type: input
id: page
attributes:
label: Documentation Page
description: Which page or section of the documentation is this about?
placeholder: "e.g. https://docs.browser-use.com/open-source/customize/browser/all-parameters > Display & Appearance > headless"
validations:
required: true
- type: textarea
id: description
attributes:
label: Issue Description
description: "Describe what's wrong or missing in the documentation"
placeholder: e.g. Docs should clarify whether BrowserSession(no_viewport=False) is supported when running in BrowserSession(headless=False) mode...
validations:
required: true
- type: textarea
id: suggestion
attributes:
label: Suggested Changes
description: If you have specific suggestions for how to improve the documentation, please share them
placeholder: |
e.g. The documentation could be improved by adding one more line here:
```diff
Use `BrowserSession(headless=False)` to open the browser window (aka headful mode).
+ Viewports are not supported when headful, if `headless=False` it will force `no_viewport=True`.
```
validations:
required: false
+11
View File
@@ -0,0 +1,11 @@
blank_issues_enabled: false # Set to true if you want to allow blank issues
contact_links:
- name: 🔢 Quickstart Guide
url: https://docs.browser-use.com/quickstart
about: Most common issues can be resolved by following our quickstart guide
- name: 💬 Questions and Help
url: https://link.browser-use.com/discord
about: Please ask questions in our Discord community
- name: 📖 Documentation
url: https://docs.browser-use.com
about: Check our documentation for answers first
+19
View File
@@ -0,0 +1,19 @@
## Reporting Security Issues
If you believe you have found a security vulnerability in browser-use, please report it through coordinated disclosure.
**Please do not report security vulnerabilities through the repository issues, discussions, or pull requests.**
Instead, please open a new [Github security advisory](https://github.com/browser-use/browser-use/security/advisories/new).
Please include as much of the information listed below as you can to help me better understand and resolve the issue:
* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help me triage your report more quickly.
@@ -0,0 +1,43 @@
name: Build Base Image
on:
schedule:
- cron: '0 2 * * 1' # Weekly on Monday
workflow_dispatch:
push:
paths:
- 'Dockerfile.base'
jobs:
build-base:
runs-on: ubuntu-latest
strategy:
matrix:
platform: [linux/amd64, linux/arm64]
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push base image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.base
platforms: ${{ matrix.platform }}
push: true
tags: |
browseruse/browseruse-base:chromium-138-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
browseruse/browseruse-base:latest-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
cache-from: type=registry,ref=browseruse/browseruse-base:buildcache-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
cache-to: type=registry,ref=browseruse/browseruse-base:buildcache-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }},mode=max
+150
View File
@@ -0,0 +1,150 @@
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
pull-requests: read
id-token: write
discussions: write
issues: write
env:
IS_SANDBOX: '1'
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
- run: uv sync --dev --all-extras
- name: Detect installed Playwright version
run: echo "PLAYWRIGHT_VERSION=$(uv pip list --format json | jq -r '.[] | select(.name == "playwright") | .version')" >> $GITHUB_ENV
# - name: Cache chrome binaries
# uses: actions/cache@v4
# with:
# path: |
# /tmp/google-chrome-stable_current_amd64.deb
# key: ${{ runner.os }}-${{ runner.arch }}-chrome-stable
# - name: Install Chrome stable binary
# run: |
# sudo apt-get update -qq \
# && sudo curl -o "/tmp/google-chrome-stable_current_amd64.deb" --no-clobber "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" \
# && sudo apt-get install -y "/tmp/google-chrome-stable_current_amd64.deb" -f
# - run: patchright install chrome --with-deps
# - run: playwright install chrome --with-deps
- name: Cache chromium binaries
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-${{ runner.arch }}-playwright-${{ env.PLAYWRIGHT_VERSION }}-chromium
- run: playwright install chromium --with-deps
# - run: patchright install chromium --with-deps
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@beta
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
model: "claude-opus-4-20250514"
fallback_model: "claude-3-5-sonnet-20241022"
custom_instructions: |
when making any significant changes, start by adding one or two new failing test functions to the most relevant file you can find in tests/ci/*.py, then work on your changes until you get the tests passing.
make sure all lint errors are fixed before committing: `uv run pre-commit --all-files`, you can also use mcp tools to check Github CI status.
make sure to run the whole test file at the end to make sure no other tests in that file started failing due to your changes: `uv run pytest/ci/test_....py`.
if any significant features were added or removed, or any public-facing parameters/signatures changed, make sure to look through docs/*.mdx and examples/**.py and fix any relevant areas that might need to be updated.
branch_prefix: "claude-"
additional_permissions: |
actions: read
claude_env: |
IN_DOCKER: 'true'
BROWSER_USE_CLOUD_SYNC: 'false'
ANONYMIZED_TELEMETRY: 'false'
BROWSER_USE_LOGGING_LEVEL: 'DEBUG'
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
settings: |
{
"permissions": {
"allow": [
"Bash(git:*)",
"Bash(uv:*)",
"Bash(uv run pytest:*)",
"Bash(uv run ruff:*)",
"Bash(uv run pyright:*)",
"Bash(uv run pre-commit:*)",
"Bash(uv pip:*)",
"Bash(uv add:*)",
"Bash(uv sync --all-extras --dev)",
"Bash(.venv/bin/*:*)",
"Bash(.venv/bin/python:*)",
"Bash(sed:*)",
"Bash(rg:*)",
"Bash(jq:*)",
"Bash(find:*)",
"Bash(grep:*)",
"Bash(python:*)",
"Bash(chmod:*)",
"Bash(rm:*)",
"Bash(playwright:*)",
"Bash(uv run playwright:*)",
"Bash(./bin/lint.sh)",
"Bash(./bin/test.sh)",
"WebFetch(*)",
"WebSearch(*)"
],
"additionalDirectories": ["/home/runner/work"]
}
}
allowed_tools: |
Bash(git:*)
Bash(uv:*)
Bash(uv run pytest:*)
Bash(uv run ruff:*)
Bash(uv run pyright:*)
Bash(uv run pre-commit:*)
Bash(uv pip:*)
Bash(uv add:*)
Bash(uv sync --all-extras --dev)
Bash(.venv/bin/*:*)
Bash(.venv/bin/python:*)
Bash(sed:*)
Bash(rg:*)
Bash(jq:*)
Bash(find:*)
Bash(grep:*)
Bash(python:*)
Bash(chmod:*)
Bash(rm:*)
Bash(playwright:*)
Bash(uv run playwright:*)
Bash(./bin/lint.sh)
Bash(./bin/test.sh)
WebFetch(*)
WebSearch(*)
+35
View File
@@ -0,0 +1,35 @@
name: cloud_evals
# Cancel in-progress runs when a new commit is pushed to the same branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
branches:
- main
- 'releases/*'
workflow_dispatch:
inputs:
commit_hash:
description: Commit hash of the library to build the Cloud eval image for
required: false
permissions: {}
jobs:
trigger_cloud_eval_image_build:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
github-token: ${{ secrets.TRIGGER_CLOUD_BUILD_GH_KEY }}
script: |
const result = await github.rest.repos.createDispatchEvent({
owner: 'browser-use',
repo: 'cloud',
event_type: 'trigger-workflow',
client_payload: {"commit_hash": "${{ github.event.inputs.commit_hash || github.sha }}"}
})
console.log(result)
+76
View File
@@ -0,0 +1,76 @@
name: docker
# Cancel in-progress runs when a new commit is pushed to the same branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
branches:
- main
- stable
- 'releases/**'
tags:
- '*'
release:
types: [published]
workflow_dispatch:
jobs:
build_publish_image:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
attestations: write
id-token: write
steps:
- name: Check out the repo
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Compute Docker tags based on tag/branch
id: meta
uses: docker/metadata-action@v5
with:
images: |
browseruse/browseruse
ghcr.io/browser-use/browser-use
tags: |
type=ref,event=branch
type=ref,event=pr
type=pep440,pattern={{version}}
type=pep440,pattern={{major}}.{{minor}}
type=sha
- name: Build and push Docker image
id: push
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
context: .
file: ./Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=browseruse/browseruse:buildcache
cache-to: type=registry,ref=browseruse/browseruse:buildcache,mode=max
+56
View File
@@ -0,0 +1,56 @@
name: Evaluate PR
permissions:
contents: read
pull-requests: write
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
trigger-evaluation:
runs-on: ubuntu-latest
# Only run if PR author has write access
if: |
github.event.pull_request.author_association == 'OWNER' ||
github.event.pull_request.author_association == 'MEMBER' ||
github.event.pull_request.author_association == 'COLLABORATOR'
steps:
- name: Trigger Evaluation settings
id: trigger
continue-on-error: true
run: |
echo "🚀 Triggering evaluation - PR #${{ github.event.pull_request.number }}"
echo "Commit: ${{ github.event.pull_request.head.sha }}"
# You can customize the test here
TEST_CASE="${{ vars.EVAL_TEST_CASE }}"
if [ -z "$TEST_CASE" ]; then
TEST_CASE="InteractionTasks_v8"
fi
response=$(curl -X POST \
"${{ secrets.EVAL_PLATFORM_URL }}/api/triggerInteractionTasksV6" \
-H "Authorization: Bearer ${{ secrets.EVAL_PLATFORM_KEY }}" \
-H "Content-Type: application/json" \
-d "{
\"commitSha\": \"${{ github.event.pull_request.head.sha }}\",
\"prNumber\": ${{ github.event.pull_request.number }},
\"branchName\": \"${{ github.event.pull_request.head.ref }}\",
\"testCase\": \"${TEST_CASE}\",
\"githubRepo\": \"${{ github.repository }}\"
}" -s)
echo "Response: $response"
# Check if trigger was was successful
if echo "$response" | jq -e '.success == true' > /dev/null; then
echo "✅ Evaluation triggered successfully"
exit 0
else
echo "Failed"
echo "$response"
exit 1
fi
+125
View File
@@ -0,0 +1,125 @@
name: Test Browser Use CLI Install
on:
push:
branches:
- main
paths:
- 'browser_use/cli.py'
- 'browser_use/skills/**'
- 'skills/browser-use/SKILL.md'
- 'browser_use/skills/browser-use/SKILL.md'
- 'scripts/sync_browser_harness_skill.py'
- 'pyproject.toml'
- '.github/workflows/install-script.yml'
pull_request:
paths:
- 'browser_use/cli.py'
- 'browser_use/skills/**'
- 'skills/browser-use/SKILL.md'
- 'browser_use/skills/browser-use/SKILL.md'
- 'scripts/sync_browser_harness_skill.py'
- 'pyproject.toml'
- '.github/workflows/install-script.yml'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
check-browser-use-skill:
name: browser-use skill sync
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check generated Browser Use skill
run: python3 scripts/sync_browser_harness_skill.py --check
test-pip-install:
name: uv pip install (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Add uv to PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Create venv and install browser-use
run: |
uv venv .venv --python 3.11
uv pip install --python .venv .
- name: Add venv to PATH
run: |
echo "$PWD/.venv/bin" >> $GITHUB_PATH
echo "$PWD/.venv/Scripts" >> $GITHUB_PATH
- name: Verify Browser Use CLI
run: |
browser-use --help
browser-use auth --help
browser-use skill show
- name: Verify aliases
run: |
browseruse --help
bu --help
browser --help
test-uvx-local-wheel:
name: uvx browser-use from local wheel
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Add uv to PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Build wheel from current branch
run: |
uv venv .venv --python 3.11
source .venv/bin/activate
uv pip install build
python -m build --wheel
- name: Verify uvx Browser Use CLI
run: |
WHEEL=$(ls dist/*.whl)
uvx --from "$WHEEL" browser-use --help
uvx --from "$WHEEL" browser-use auth --help
uvx --from "$WHEEL" browser-use skill show
test-uvx-pypi:
name: uvx browser-use[cli] from PyPI
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
steps:
- name: Install uv
run: curl -LsSf https://astral.sh/uv/install.sh | sh
- name: Add uv to PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Verify uvx Browser Use CLI
run: |
uvx "browser-use[cli]" --help
uvx "browser-use[cli]" auth --help
uvx "browser-use[cli]" skill show
+54
View File
@@ -0,0 +1,54 @@
name: lint
# Cancel in-progress runs when a new commit is pushed to the same branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
branches:
- main
- stable
- 'releases/**'
tags:
- '*'
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
lint-syntax:
name: syntax-errors
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- run: uv run ruff check --no-fix --select PLE
lint-style:
name: code-style
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
with:
enable-cache: true
- run: uv python install 3.11
- run: uv sync --dev --all-extras --python 3.11 --refresh-package browser-use-core
- run: uv run --no-sync pre-commit run --all-files --show-diff-on-failure
lint-typecheck:
name: type-checker
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
- run: uv sync --dev --all-extras --refresh-package browser-use-core # install extras for examples to avoid pyright missing imports errors-
- run: uv run --no-sync pyright
+64
View File
@@ -0,0 +1,64 @@
name: package
# Cancel in-progress runs when a new commit is pushed to the same branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
branches:
- main
- stable
- 'releases/**'
tags:
- '*'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
name: pip-build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- run: uv build --python 3.12
- uses: actions/upload-artifact@v4
with:
name: dist-artifact
path: |
dist/*.whl
dist/*.tar.gz
build_test:
name: pip-install-on-${{ matrix.os }}-py-${{ matrix.python-version }}
needs: build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.11", "3.13"]
env:
ANONYMIZED_TELEMETRY: 'false'
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- uses: actions/download-artifact@v4
with:
name: dist-artifact
- name: Set up venv and test for OS/Python versions
shell: bash
run: |
uv venv /tmp/testenv --python ${{ matrix.python-version }} --clear
if [[ "$RUNNER_OS" == "Windows" ]]; then
. /tmp/testenv/Scripts/activate
else
source /tmp/testenv/bin/activate
fi
uv pip install *.whl
python -c 'from browser_use import Agent, BrowserProfile, BrowserSession, Tools, ActionModel, ActionResult'
+142
View File
@@ -0,0 +1,142 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
name: publish
# Cancel in-progress runs when a new commit is pushed to the same branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
release:
types: [published] # publish full release to PyPI when a release is created on Github
# schedule:
# - cron: "0 17 * * FRI" # tag a pre-release on Github every Friday at 5 PM UTC
workflow_dispatch:
inputs:
create_tag:
description: "Create the next pre-release tag before publishing"
required: false
default: true
type: boolean
permissions:
contents: write
id-token: write
jobs:
tag_pre_release:
if: github.event_name == 'workflow_dispatch' && inputs.create_tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create pre-release tag
run: |
git fetch --tags
latest_tag=$(git tag --list --sort=-v:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+(rc[0-9]+)?$' | head -n 1)
if [ -z "$latest_tag" ]; then
echo "Failed to find the latest git tag from list:" > /dev/stderr
git tag --list --sort=-v:refname
exit 1
else
# Bump the tag rc version
if [[ "$latest_tag" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(rc([0-9]+))?$ ]]; then
major="${BASH_REMATCH[1]}"
minor="${BASH_REMATCH[2]}"
patch="${BASH_REMATCH[3]}"
rc="${BASH_REMATCH[5]}"
echo "latest_tag: ${major}.${minor}.${patch}rc${rc:-0}"
if [ -z "$rc" ]; then
# No rc, so bump patch and set rc=1 # 0.2.1 -> 0.2.2rc1
patch=$((patch + 1))
new_tag="${major}.${minor}.${patch}rc1"
else
if [ "$rc" -ge 99 ]; then
echo "Error: rc version is already at 99 for tag $latest_tag, refusing to increment further." > /dev/stderr
exit 1
fi
rc=$((rc + 1))
new_tag="${major}.${minor}.${patch}rc${rc}" # 0.2.1rc1 -> 0.2.1rc2
fi
else
echo "Error: latest_tag '$latest_tag' does not match expected version pattern." > /dev/stderr
exit 1
fi
fi
echo "new_tag: $new_tag"
git tag $new_tag
git push origin $new_tag
publish_to_pypi:
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
environment: release
permissions:
contents: write # for the stable-branch push at the end
id-token: write # for PyPI trusted-publishing OIDC
actions: read # for the env protection verification step
env:
IN_DOCKER: 'True'
ANONYMIZED_TELEMETRY: 'false'
steps:
- name: Verify release environment is protected (fail-closed)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
ENV_NAME="release"
if ! RESP="$(gh api -H 'Accept: application/vnd.github+json' \
"/repos/${GITHUB_REPOSITORY}/environments/${ENV_NAME}" 2>/dev/null)"; then
echo "::error::Environment '${ENV_NAME}' does not exist (or is inaccessible). Create it at https://github.com/${GITHUB_REPOSITORY}/settings/environments/new with required reviewers and prevent_self_review enabled, then re-run."
exit 1
fi
HAS_REVIEWERS="$(echo "$RESP" | jq -r '[.protection_rules[]? | select(.type == "required_reviewers")] | length')"
if [ "${HAS_REVIEWERS:-0}" -lt 1 ]; then
echo "::error::Environment '${ENV_NAME}' exists but has no required-reviewers protection rule."
exit 1
fi
SELF_REVIEW_BLOCKED="$(echo "$RESP" | jq -r '[.protection_rules[]? | select(.type=="required_reviewers") | .prevent_self_review] | any')"
if [ "$SELF_REVIEW_BLOCKED" != "true" ]; then
echo "::error::Environment '${ENV_NAME}' must have prevent_self_review enabled. Without it, the gate collapses to one identity when the dispatcher is also a reviewer."
exit 1
fi
echo "::notice::Environment '${ENV_NAME}' is protected with prevent_self_review. OK."
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
- run: uv sync
- run: uv run --no-sync ruff check --no-fix --select PLE # quick check for syntax errors to avoid waiting time doing the rest of the build
- run: uv build
# - name: Detect installed Playwright version
# run: echo "PLAYWRIGHT_VERSION=$(uv pip list --format json | jq -r '.[] | select(.name == "playwright") | .version')" >> $GITHUB_ENV
# - name: Cache playwright binaries
# uses: actions/cache@v3
# with:
# path: |
# ~/.cache/ms-playwright
# key: ${{ runner.os }}-playwright-${{ env.PLAYWRIGHT_VERSION }}
- run: uvx playwright install chrome
- run: uvx playwright install chromium
# TODO: just depend on the other test.yml action for this instead of re-running the tests here
# - run: uv run pytest tests/ci/test_tools.py # final sanity check: run a few of the tests before release
# publish to PyPI
- run: uv publish --trusted-publishing always
- name: Push to stable branch (if stable release)
if: github.event_name == 'release' && !contains(github.ref_name, 'rc')
run: |
git checkout -b stable
git push origin -f stable
+108
View File
@@ -0,0 +1,108 @@
name: 'Manage stale issues and PRs'
on:
schedule:
- cron: '0 2 * * *' # Run daily at 2:00 AM UTC
workflow_dispatch: # Allow manual triggering
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
with:
# General settings
repo-token: ${{ secrets.GITHUB_TOKEN }}
# Days before marking as stale (more lenient for AI/browser automation project)
days-before-stale: 60
days-before-close: 14
# Different timing for PRs vs issues
days-before-pr-stale: 45
days-before-pr-close: 14
# Stale labels
stale-issue-label: 'stale'
stale-pr-label: 'stale'
# Remove stale label when there's activity
remove-stale-when-updated: true
remove-issue-stale-when-updated: true
remove-pr-stale-when-updated: true
# Messages
stale-issue-message: |
👋 This issue has been automatically marked as stale because it hasn't had activity for 60 days.
**⚡ We've made significant progress recently!** Please test with the latest version of browser-use to see if this issue has been resolved. If the issue persists, please let us know by commenting below.
**To keep this issue open:**
- Add a comment explaining why this is still relevant after testing the latest version
- Add the `pinned` label if this is an important long-term issue
- Reference it in a PR if you're working on a fix
**This will be automatically closed in 14 days** if no further activity occurs.
Thanks for contributing to browser-use! 🤖 If you have questions, join our [Discord](https://discord.gg/uC9hDSbt).
stale-pr-message: |
👋 This PR has been automatically marked as stale because it hasn't had activity for 45 days.
**To keep this PR open:**
- Rebase against the latest main branch
- Address any review feedback or merge conflicts
- Add a comment explaining the current status
- Add the `work-in-progress` label if you're still actively working on this
**This will be automatically closed in 14 days** if no further activity occurs.
Thanks for contributing to browser-use! 🤖
close-issue-message: |
🔒 This issue was automatically closed because it was stale for 14 days with no activity.
**Don't worry!** If this issue is still relevant:
- **First, test with the latest version** - we've made tons of improvements recently!
- **Reopen it** if you have permissions and the issue persists
- **Create a fresh issue** with updated information if the problem still exists after testing the latest version
- **Join our [Discord](https://discord.gg/uC9hDSbt)** to discuss
We appreciate your contribution to browser-use! 🤖
close-pr-message: |
🔒 This PR was automatically closed because it was stale for 14 days with no activity.
**Don't worry!** If you'd like to continue this work:
- **Reopen this PR** and rebase against main
- **Create a fresh PR** with updated changes
- **Join our [Discord](https://discord.gg/uC9hDSbt)** if you need help
Thanks for contributing to browser-use! 🤖
# Comprehensive exemptions for AI/browser automation project
exempt-issue-labels: 'pinned,security,bug,enhancement,good-first-issue,help-wanted,documentation,ci,breaking-change,feature-request,roadmap'
exempt-pr-labels: 'pinned,work-in-progress,wip,breaking-change,security,dependencies,ci'
exempt-milestones: true
exempt-all-assignees: true
exempt-all-pr-assignees: true
# Don't mark issues/PRs stale if they have recent PR references
exempt-pr-author: true
# Advanced settings
operations-per-run: 200 # More conservative to avoid rate limits
ascending: true # Process oldest issues first
# Enable debug output
debug-only: false
# Only process issues/PRs, not drafts
include-only-assigned: false
# Additional safety: don't close issues with many reactions (community interest)
ignore-issue-updates: false
ignore-pr-updates: false
+337
View File
@@ -0,0 +1,337 @@
name: test
permissions:
actions: read
contents: write
pull-requests: write # Allow writing comments on PRs
issues: write # Allow writing comments on issues
statuses: write # Allow writing statuses on PRs
discussions: write
# Cancel in-progress runs when a new commit is pushed to the same branch/PR
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
push:
branches:
- main
- stable
- 'releases/**'
tags:
- '*'
pull_request:
workflow_dispatch:
jobs:
setup-chromium:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- name: Get week number for cache key
id: week
run: echo "number=$(date +%Y-W%U)" >> $GITHUB_OUTPUT
- name: Cache chromium binaries
id: cache-chromium
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-${{ runner.arch }}-chromium-${{ steps.week.outputs.number }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-chromium-
- name: Install Chromium if not cached
if: steps.cache-chromium.outputs.cache-hit != 'true'
run: uvx playwright install chromium --with-deps --no-shell
find_tests:
runs-on: ubuntu-latest
timeout-minutes: 5 # Prevent hanging
outputs:
TEST_FILENAMES: ${{ steps.lsgrep.outputs.TEST_FILENAMES }}
# ["test_browser", "test_tools", "test_browser_session", "test_tab_management", ...]
steps:
- uses: actions/checkout@v4
with:
# Force fresh checkout to avoid any caching issues
fetch-depth: 1
- id: lsgrep
run: |
echo "🔍 Discovering test files at $(date)"
echo "Git commit: $(git rev-parse HEAD)"
echo "Git branch: $(git branch --show-current)"
echo ""
TEST_FILENAMES="$(find tests/ci -name 'test_*.py' -type f | sed 's|^tests/ci/||' | sed 's|\.py$||' | jq -R -s -c 'split("\n")[:-1]')"
echo "TEST_FILENAMES=${TEST_FILENAMES}" >> "$GITHUB_OUTPUT"
echo "📋 Test matrix: $TEST_FILENAMES"
# https://code.dblock.org/2021/09/03/generating-task-matrix-by-looping-over-repo-files-with-github-actions.html
- name: Check that at least one test file is found
run: |
if [ -z "${{ steps.lsgrep.outputs.TEST_FILENAMES }}" ]; then
echo "Failed to find any test_*.py files in tests/ci/ folder!" > /dev/stderr
exit 1
fi
tests:
needs: [setup-chromium, find_tests]
runs-on: ubuntu-latest
timeout-minutes: 4 # Reduced timeout - tests should complete quickly or retry
env:
IN_DOCKER: 'True'
ANONYMIZED_TELEMETRY: 'false'
BROWSER_USE_LOGGING_LEVEL: 'DEBUG'
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
AZURE_OPENAI_KEY: ${{ secrets.AZURE_OPENAI_KEY }}
AZURE_OPENAI_ENDPOINT: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
BROWSER_USE_API_KEY: ${{ secrets.BROWSER_USE_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
strategy:
matrix:
test_filename: ${{ fromJson(needs.find_tests.outputs.TEST_FILENAMES || '["FAILED_TO_DISCOVER_TESTS"]') }}
# autodiscovers all the files in tests/ci/test_*.py
# - test_browser
# - test_tools
# - test_browser_session
# - test_tab_management
# ... and more
name: ${{ matrix.test_filename }}
steps:
- name: Check that the previous step managed to find some test files for us to run
run: |
if [[ "${{ matrix.test_filename }}" == "FAILED_TO_DISCOVER_TESTS" ]]; then
echo "Failed get list of test files in tests/ci/test_*.py from find_tests job" > /dev/stderr
exit 1
fi
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
- name: Cache uv packages and venv
uses: actions/cache@v4
with:
path: |
~/.cache/uv
.venv
key: ${{ runner.os }}-uv-venv-${{ hashFiles('pyproject.toml') }}
restore-keys: |
${{ runner.os }}-uv-venv-
- run: uv sync --dev --all-extras --refresh-package browser-use-core
- name: Get week number for cache key
id: week
run: echo "number=$(date +%Y-W%U)" >> $GITHUB_OUTPUT
- name: Cache chromium binaries
id: cache-chromium
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-${{ runner.arch }}-chromium-${{ steps.week.outputs.number }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-chromium-
- name: Install Chromium browser if not cached
if: steps.cache-chromium.outputs.cache-hit != 'true'
run: uvx playwright install chromium --with-deps --no-shell
- name: Cache browser-use extensions
uses: actions/cache@v4
with:
path: |
~/.config/browseruse/extensions
key: ${{ runner.os }}-browseruse-extensions-${{ hashFiles('browser_use/browser/profile.py') }}
restore-keys: |
${{ runner.os }}-browseruse-extensions-
- name: Check if test file exists
id: check-file
run: |
TEST_FILE="tests/ci/${{ matrix.test_filename }}.py"
if [ -f "$TEST_FILE" ]; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "✅ Test file found: $TEST_FILE"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "❌ Test file not found: $TEST_FILE"
echo "This file may have been renamed or removed. Current test files:"
find tests/ci -name 'test_*.py' -type f | sed 's|tests/ci/||' | sed 's|\.py$||' | sort
fi
- name: Run test with retry
if: steps.check-file.outputs.exists == 'true'
uses: nick-fields/retry@v3
with:
timeout_minutes: 4
max_attempts: 1
retry_on: error
command: pytest "tests/ci/${{ matrix.test_filename }}.py"
evaluate-tasks:
needs: setup-chromium
runs-on: ubuntu-latest
timeout-minutes: 8 # Allow more time for agent eval
env:
IN_DOCKER: 'true'
BROWSER_USE_CLOUD_SYNC: 'false'
ANONYMIZED_TELEMETRY: 'false'
BROWSER_USE_LOGGING_LEVEL: 'DEBUG'
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PERPLEXITY_API_KEY: ${{ secrets.PERPLEXITY_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
BROWSER_USE_API_KEY: ${{ secrets.BROWSER_USE_API_KEY }}
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
with:
enable-cache: true
activate-environment: true
- name: Cache uv packages and venv
uses: actions/cache@v4
with:
path: |
~/.cache/uv
.venv
key: ${{ runner.os }}-uv-venv-${{ hashFiles('pyproject.toml') }}
restore-keys: |
${{ runner.os }}-uv-venv-
- run: uv sync --dev --all-extras --refresh-package browser-use-core
- name: Get week number for cache key
id: week
run: echo "number=$(date +%Y-W%U)" >> $GITHUB_OUTPUT
- name: Cache chromium binaries
id: cache-chromium
uses: actions/cache@v4
with:
path: |
~/.cache/ms-playwright
key: ${{ runner.os }}-${{ runner.arch }}-chromium-${{ steps.week.outputs.number }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-chromium-
- name: Install Chromium browser if not cached
if: steps.cache-chromium.outputs.cache-hit != 'true'
run: uvx playwright install chromium --with-deps --no-shell
- name: Cache browser-use extensions
uses: actions/cache@v4
with:
path: |
~/.config/browseruse/extensions
key: ${{ runner.os }}-browseruse-extensions-${{ hashFiles('browser_use/browser/profile.py') }}
restore-keys: |
${{ runner.os }}-browseruse-extensions-
- name: Run agent tasks evaluation and capture score
id: eval
uses: nick-fields/retry@v3
with:
timeout_minutes: 4
max_attempts: 1
retry_on: error
command: |
python tests/ci/evaluate_tasks.py > result.txt
cat result.txt
echo "PASSED=$(grep '^PASSED=' result.txt | cut -d= -f2)" >> $GITHUB_ENV
echo "TOTAL=$(grep '^TOTAL=' result.txt | cut -d= -f2)" >> $GITHUB_ENV
echo "DETAILED_RESULTS=$(grep '^DETAILED_RESULTS=' result.txt | cut -d= -f2-)" >> $GITHUB_ENV
- name: Print agent evaluation summary
run: |
echo "Agent tasks passed: $PASSED / $TOTAL"
- name: Write agent evaluation summary to workflow overview
run: |
if [ "$PASSED" = "$TOTAL" ]; then
COLOR="green"
else
COLOR="yellow"
fi
echo "<h2>Agent Tasks Score: <span style='color:$COLOR;'>$PASSED/$TOTAL</span></h2>" >> $GITHUB_STEP_SUMMARY
- name: Comment PR with agent evaluation results
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
continue-on-error: true
with:
script: |
const passed = parseInt(process.env.PASSED);
const total = parseInt(process.env.TOTAL);
const detailedResults = JSON.parse(process.env.DETAILED_RESULTS);
const score = `${passed}/${total}`;
const percentage = Math.round((passed / total) * 100);
// Fail the workflow if 0% pass rate
if (percentage === 0) {
core.setFailed(`Evaluation failed: 0% pass rate (${passed}/${total})`);
}
// Create detailed table
let tableRows = '';
detailedResults.forEach(result => {
const emoji = result.success ? '✅' : '❌';
const status = result.success ? 'Pass' : 'Fail';
tableRows += `| ${result.task} | ${emoji} ${status} | ${result.reason} |\n`;
});
const comment = `## Agent Task Evaluation Results: ${score} (${percentage}%)
<details>
<summary>View detailed results</summary>
| Task | Result | Reason |
|------|--------|--------|
${tableRows}
Check the [evaluate-tasks job](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for detailed task execution logs.
</details>`;
// Find existing comment to update or create new one
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('Agent Task Evaluation Results')
);
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: comment
});
} else {
// Create new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}