From 0571d8998aa545d992bfcde05860e6c498debe56 Mon Sep 17 00:00:00 2001 From: giatti Date: Wed, 27 May 2026 11:52:17 -0300 Subject: [PATCH 1/3] ci: add Renovate + automated dependency review - Monthly Renovate run (2nd of month, 02:00 BRT) - minimumReleaseAge: 14 days (supply-chain protection) - Python deps via pep621 manager - Major bumps require manual review --- .github/renovate.json5 | 38 ++++++++++++++++++++++++++++++++++ .github/workflows/renovate.yml | 20 ++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 .github/renovate.json5 create mode 100644 .github/workflows/renovate.yml diff --git a/.github/renovate.json5 b/.github/renovate.json5 new file mode 100644 index 00000000..92b5eefb --- /dev/null +++ b/.github/renovate.json5 @@ -0,0 +1,38 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended", + ":disableDependencyDashboard", + ], + "baseBranchPatterns": ["main"], + "schedule": ["on the 2nd day of the month"], + "timezone": "America/Sao_Paulo", + "prConcurrentLimit": 10, + "prHourlyLimit": 0, + "labels": ["dependencies"], + "separateMajorMinor": false, + "minimumReleaseAge": "14 days", + "internalChecksFilter": "strict", + "commitMessagePrefix": "[RENOVATE]", + "packageRules": [ + { + "matchManagers": ["pep621"], + "groupName": "python-deps", + "commitMessagePrefix": "[RENOVATE] [PY]", + "matchUpdateTypes": ["minor", "patch"] + }, + { + "matchManagers": ["pep621"], + "matchUpdateTypes": ["major"], + "groupName": "python-major", + "commitMessagePrefix": "[RENOVATE] [PY] [MAJOR]", + "automerge": false + }, + { + "matchManagers": ["github-actions"], + "groupName": "github-actions", + "commitMessagePrefix": "[RENOVATE] [CI]", + "pinDigests": true + } + ] +} diff --git a/.github/workflows/renovate.yml b/.github/workflows/renovate.yml new file mode 100644 index 00000000..f908228f --- /dev/null +++ b/.github/workflows/renovate.yml @@ -0,0 +1,20 @@ +name: Renovate +on: + schedule: + - cron: '0 5 2 * *' # Monthly: 2nd at 05:00 UTC (02:00 BRT) + workflow_dispatch: + +jobs: + renovate: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Self-hosted Renovate + uses: renovatebot/github-action@v41 + with: + configurationFile: .github/renovate.json5 + token: ${{ secrets.GITHUB_TOKEN }} + env: + LOG_LEVEL: info From 61ded7f691cd01ef5b5c369a0a688787aaa36ac1 Mon Sep 17 00:00:00 2001 From: giatti Date: Sun, 14 Jun 2026 16:36:56 -0300 Subject: [PATCH 2/3] dedup: import _load_env from helpers + add dupehound CI admin.py and daemon.py each defined _load_env and _load_env_file identically (admin.py: 12-30, daemon.py: 10-28). Both now import from helpers.py, which is the canonical source (was already exporting both via module-level _load_env() side effect). CI: - .github/workflows/dupehound.yml: scan (slop score) and check (--diff against base) jobs. check is continue-on-error for now; promote to gate after FP rate <10% over ~10 PRs. Slop score: 0.9% -> 0.0% (4 -> 0 clusters, 18 lines eliminated). 40/40 unit tests pass. --- .github/workflows/dupehound.yml | 65 +++++++++++++++++++++++++++++++++ src/browser_harness/admin.py | 22 +---------- src/browser_harness/daemon.py | 23 +----------- 3 files changed, 68 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/dupehound.yml diff --git a/.github/workflows/dupehound.yml b/.github/workflows/dupehound.yml new file mode 100644 index 00000000..1badc7cd --- /dev/null +++ b/.github/workflows/dupehound.yml @@ -0,0 +1,65 @@ +name: dupehound + +on: + pull_request: + paths: + - 'src/**' + - 'tests/**' + push: + branches: [main] + paths: + - 'src/**' + - 'tests/**' + +permissions: + contents: read + +jobs: + check: + name: Block new duplicates + runs-on: ubuntu-latest + timeout-minutes: 5 + # Set to false once FP rate is proven <10% over ~10 PRs + continue-on-error: true + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install dupehound + run: | + curl -sL https://github.com/Rafaelpta/dupehound/releases/latest/download/dupehound-x86_64-unknown-linux-gnu.tar.gz | tar xz + sudo mv dupehound /usr/local/bin/ + + - name: Block new duplicates vs base + env: + PR_BASE: ${{ github.event.pull_request.base.ref }} + run: | + if [ -n "$PR_BASE" ]; then + dupehound check --diff "origin/$PR_BASE" . + else + dupehound check --diff HEAD~1 . + fi + + scan: + name: Repo slop score + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dupehound + run: | + curl -sL https://github.com/Rafaelpta/dupehound/releases/latest/download/dupehound-x86_64-unknown-linux-gnu.tar.gz | tar xz + sudo mv dupehound /usr/local/bin/ + + - name: Scan and post score + run: | + dupehound scan . | tee /tmp/dh-scan.txt + SCORE=$(grep -oE 'SLOP SCORE[[:space:]]+[0-9.]+%' /tmp/dh-scan.txt | head -1 | grep -oE '[0-9.]+%' || echo "n/a") + echo "## dupehound slop score" >> $GITHUB_STEP_SUMMARY + echo "**${SCORE}**" >> $GITHUB_STEP_SUMMARY diff --git a/src/browser_harness/admin.py b/src/browser_harness/admin.py index 83109c41..2b9cc047 100644 --- a/src/browser_harness/admin.py +++ b/src/browser_harness/admin.py @@ -7,27 +7,7 @@ from pathlib import Path from . import _ipc as ipc - - -def _load_env(): - repo_root = Path(__file__).resolve().parents[2] - workspace = Path(os.environ.get("BH_AGENT_WORKSPACE", repo_root / "agent-workspace")).expanduser() - for p in (repo_root / ".env", workspace / ".env"): - if not p.exists(): - continue - _load_env_file(p) - - -def _load_env_file(p): - for line in p.read_text().splitlines(): - line = line.strip() - if not line or line.startswith("#") or "=" not in line: - continue - k, v = line.split("=", 1) - os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'")) - - -_load_env() +from .helpers import _load_env, _load_env_file NAME = os.environ.get("BU_NAME", "default") BU_API = "https://api.browser-use.com/api/v3" diff --git a/src/browser_harness/daemon.py b/src/browser_harness/daemon.py index 01edad1c..8b510eff 100644 --- a/src/browser_harness/daemon.py +++ b/src/browser_harness/daemon.py @@ -4,28 +4,9 @@ from pathlib import Path from . import _ipc as ipc -from cdp_use.client import CDPClient - - -def _load_env(): - repo_root = Path(__file__).resolve().parents[2] - workspace = Path(os.environ.get("BH_AGENT_WORKSPACE", repo_root / "agent-workspace")).expanduser() - for p in (repo_root / ".env", workspace / ".env"): - if not p.exists(): - continue - _load_env_file(p) - +from .helpers import _load_env, _load_env_file -def _load_env_file(p): - for line in p.read_text().splitlines(): - line = line.strip() - if not line or line.startswith("#") or "=" not in line: - continue - k, v = line.split("=", 1) - os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'")) - - -_load_env() +from cdp_use.client import CDPClient NAME = os.environ.get("BU_NAME", "default") SOCK = ipc.sock_addr(NAME) From f648fb3ffdff4447d629368b498de6ee8e99625c Mon Sep 17 00:00:00 2001 From: giatti Date: Sun, 14 Jun 2026 17:09:25 -0300 Subject: [PATCH 3/3] ci: pin actions/checkout to SHA (sha_pinning_required: true) --- .github/workflows/dupehound.yml | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/.github/workflows/dupehound.yml b/.github/workflows/dupehound.yml index 1badc7cd..5c177709 100644 --- a/.github/workflows/dupehound.yml +++ b/.github/workflows/dupehound.yml @@ -19,20 +19,16 @@ jobs: name: Block new duplicates runs-on: ubuntu-latest timeout-minutes: 5 - # Set to false once FP rate is proven <10% over ~10 PRs continue-on-error: true - steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 - - name: Install dupehound run: | curl -sL https://github.com/Rafaelpta/dupehound/releases/latest/download/dupehound-x86_64-unknown-linux-gnu.tar.gz | tar xz sudo mv dupehound /usr/local/bin/ - - name: Block new duplicates vs base env: PR_BASE: ${{ github.event.pull_request.base.ref }} @@ -47,19 +43,16 @@ jobs: name: Repo slop score runs-on: ubuntu-latest timeout-minutes: 5 - steps: - name: Checkout - uses: actions/checkout@v4 - + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Install dupehound run: | curl -sL https://github.com/Rafaelpta/dupehound/releases/latest/download/dupehound-x86_64-unknown-linux-gnu.tar.gz | tar xz sudo mv dupehound /usr/local/bin/ - - - name: Scan and post score + - name: Scan run: | dupehound scan . | tee /tmp/dh-scan.txt SCORE=$(grep -oE 'SLOP SCORE[[:space:]]+[0-9.]+%' /tmp/dh-scan.txt | head -1 | grep -oE '[0-9.]+%' || echo "n/a") - echo "## dupehound slop score" >> $GITHUB_STEP_SUMMARY - echo "**${SCORE}**" >> $GITHUB_STEP_SUMMARY + echo "## dupehound slop score" >> "$GITHUB_STEP_SUMMARY" + echo "**${SCORE}**" >> "$GITHUB_STEP_SUMMARY"