name: repo maintenance on: schedule: - cron: "0 14 * * 1" # every Monday at 2am UTC (6am PST) pull_request: types: [closed] workflow_dispatch: env: PYTHONPATH: ${{ github.workspace }} jobs: package_updates: name: package_updates runs-on: ubuntu-latest if: >- github.repository == 'commaai/openpilot' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') steps: - uses: actions/checkout@v7 - run: ./tools/op.sh setup - name: uv lock run: uv lock --upgrade - name: uv pip tree id: pip_tree run: | echo 'PIP_TREE<> $GITHUB_OUTPUT uv pip tree >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT - name: venv size id: venv_size run: | echo 'VENV_SIZE<> $GITHUB_OUTPUT echo "Total: $(du -sh .venv | cut -f1)" >> $GITHUB_OUTPUT echo "" >> $GITHUB_OUTPUT echo "Top 10 by size:" >> $GITHUB_OUTPUT du -sh .venv/lib/python*/site-packages/* 2>/dev/null \ | grep -v '\.dist-info' \ | grep -v '__pycache__' \ | sort -rh \ | head -10 \ | while IFS=$'\t' read size path; do echo "$size ${path##*/}"; done >> $GITHUB_OUTPUT echo 'EOF' >> $GITHUB_OUTPUT - name: Check tracked dependencies run: python3 tools/vendor/check.py - name: update car docs run: | python openpilot/selfdrive/car/docs.py git add docs/CARS.md - name: Create Pull Request uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 with: author: Vehicle Researcher token: ${{ secrets.ACTIONS_CREATE_PR_PAT }} commit-message: Update Python packages title: '[bot] Update Python packages' branch: auto-package-updates base: master delete-branch: true body: | Automatic PR from repo-maintenance -> package_updates ``` $ du -sh .venv && du -sh .venv/lib/python*/site-packages/* | sort -rh | head -10 ${{ steps.venv_size.outputs.VENV_SIZE }} ``` ``` $ uv pip tree ${{ steps.pip_tree.outputs.PIP_TREE }} ``` labels: bot cleanup_closed_branches: if: github.repository == 'commaai/openpilot' && github.event_name == 'pull_request' runs-on: ubuntu-latest permissions: contents: write pull-requests: read steps: - uses: actions/github-script@v9 with: script: | const { owner, repo } = context.repo; const upstream = `${owner}/${repo}`; const closed = context.payload.pull_request; if (closed) { if (closed.head.repo?.full_name === upstream) { await github.rest.git.deleteRef({ owner, repo, ref: `heads/${closed.head.ref}` }).catch(console.log); } return; } for await (const response of github.paginate.iterator(github.rest.pulls.list, { owner, repo, state: 'closed', per_page: 100, })) { for (const pr of response.data) { if (pr.head.repo?.full_name !== upstream) continue; const branch = pr.head.ref; try { await github.rest.git.deleteRef({ owner, repo, ref: `heads/${branch}`, }); console.log(`Deleted branch ${branch} (PR #${pr.number})`); } catch (error) { if (error.status === 422 || error.status === 403) { console.log(`Skipping branch ${branch} (PR #${pr.number}): ${error.message}`); continue; } throw error; } } }