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
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:
@@ -0,0 +1,2 @@
|
||||
66b3c26df51adec32d42c3b2c0304e0662457298
|
||||
2be4ba4f7078d47bbeed04baf6f8fb04017df028
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(*)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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'
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user