diff --git a/.config/tend.toml b/.config/tend.toml index 9c07e0486ccd..0094d228af9e 100644 --- a/.config/tend.toml +++ b/.config/tend.toml @@ -3,12 +3,12 @@ bot_name = "prql-bot" [secrets] bot_token = "PRQL_BOT_GITHUB_TOKEN" -[setup] -uses = ["./.github/actions/tend-setup"] +[[setup]] +uses = "./.github/actions/tend-setup" [workflows.ci-fix] watched_workflows = ["tests"] -[workflows.renovate] +[workflows.weekly] # Dependabot already handles dependency updates for this project. enabled = false diff --git a/.github/workflows/tend-ci-fix.yaml b/.github/workflows/tend-ci-fix.yaml index 09cb25ed790d..36a9466c67b1 100644 --- a/.github/workflows/tend-ci-fix.yaml +++ b/.github/workflows/tend-ci-fix.yaml @@ -5,7 +5,7 @@ on: workflow_run: workflows: ["tests"] types: [completed] - branches: [main] + branches: ["main"] jobs: fix-ci: @@ -20,7 +20,6 @@ jobs: steps: - uses: actions/checkout@v6 with: - ref: main fetch-depth: 0 fetch-tags: true token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} @@ -33,7 +32,7 @@ jobs: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} bot_name: prql-bot prompt: | - /tend:tend-ci-fix ${{ github.event.workflow_run.id }} + /tend-ci-runner:ci-fix ${{ github.event.workflow_run.id }} - Run URL: ${{ github.event.workflow_run.html_url }} - Commit: ${{ github.event.workflow_run.head_sha }} - Commit message: ${{ github.event.workflow_run.head_commit.message }} diff --git a/.github/workflows/tend-mention.yaml b/.github/workflows/tend-mention.yaml index daaa0dc80034..ad2773337326 100644 --- a/.github/workflows/tend-mention.yaml +++ b/.github/workflows/tend-mention.yaml @@ -6,6 +6,9 @@ on: types: [edited] issue_comment: types: [created, edited] + # Works for same-repo PRs only; secrets unavailable on fork PRs (no _target variant exists) + pull_request_review: + types: [submitted] pull_request_review_comment: types: [created, edited] @@ -18,10 +21,9 @@ jobs: (github.event_name == 'issue_comment' && github.event.comment.user.login != 'prql-bot') || (github.event_name == 'pull_request_review_comment' && - github.event.comment.user.login != 'prql-bot') - concurrency: - group: ${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number }} - cancel-in-progress: true + github.event.comment.user.login != 'prql-bot') || + (github.event_name == 'pull_request_review' && + github.event.review.user.login != 'prql-bot') runs-on: ubuntu-24.04 outputs: should_run: ${{ steps.check.outputs.should_run }} @@ -85,7 +87,7 @@ jobs: env: GH_TOKEN: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} EVENT_NAME: ${{ github.event_name }} - COMMENT_BODY: ${{ github.event.comment.body }} + COMMENT_BODY: ${{ github.event.comment.body || github.event.review.body }} ISSUE_BODY: ${{ github.event.issue.body }} ISSUE_OR_PR_NUMBER: ${{ github.event.issue.number }} ISSUE_AUTHOR: ${{ github.event.issue.user.login }} @@ -108,6 +110,9 @@ jobs: handle: needs: verify if: needs.verify.outputs.should_run == 'true' + concurrency: + group: ${{ github.workflow }}-handle-${{ github.event.issue.number || github.event.pull_request.number }} + cancel-in-progress: false runs-on: ubuntu-24.04 timeout-minutes: 60 permissions: @@ -126,7 +131,8 @@ jobs: - name: Check out PR branch if: | (github.event_name == 'issue_comment' && github.event.issue.pull_request.url != '') || - github.event_name == 'pull_request_review_comment' + github.event_name == 'pull_request_review_comment' || + github.event_name == 'pull_request_review' run: | PR_STATE=$(gh pr view "$PR_NUMBER" --json state --jq '.state') if [ "$PR_STATE" = "OPEN" ]; then @@ -140,18 +146,40 @@ jobs: - uses: ./.github/actions/tend-setup + - name: Compute queue delay + id: delay + run: | + if [ -z "$EVENT_TS" ]; then + echo "seconds=" >> "$GITHUB_OUTPUT" + exit 0 + fi + event_epoch=$(date -d "$EVENT_TS" +%s) + echo "seconds=$(( $(date +%s) - event_epoch ))" >> "$GITHUB_OUTPUT" + env: + EVENT_TS: ${{ github.event.comment.created_at || github.event.review.submitted_at || github.event.issue.updated_at }} + - uses: max-sixty/tend@v1 with: github_token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} bot_name: prql-bot prompt: >- + ${{ steps.delay.outputs.seconds + && format('This job started {0}s after the triggering event (over ~40s means it was queued). ', + steps.delay.outputs.seconds) || '' }}Before acting, + check recent comments: exit silently if the bot already responded + to the trigger; handle any other unaddressed comments too. + ${{ github.event_name == 'issues' && format('An issue was updated with a mention of you ({0}). Read it and respond.', github.event.issue.html_url) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@prql-bot') && format('You were mentioned in an inline review comment on PR #{0} ({1}, review comment ID {2}). Read the full PR context (description, diff, recent comments, CI status) and respond. If they are requesting changes, make the changes, commit, and push. Reply in the review thread using `gh api repos/{3}/pulls/{0}/comments/{2}/replies -f body="..."` — do not create a new top-level comment.', (github.event_name == 'issue_comment' && github.event.issue.number || github.event.pull_request.number), github.event.comment.html_url, github.event.comment.id, github.repository)) || (github.event_name == 'pull_request_review_comment' && format('A user left an inline review comment on a PR where you previously participated (PR #{0}, {1}, review comment ID {2}). Read the full context. Only respond if the comment is directed at you or requests changes. Reply in the review thread using `gh api repos/{3}/pulls/{0}/comments/{2}/replies -f body="..."`.', (github.event_name == 'issue_comment' && github.event.issue.number || github.event.pull_request.number), github.event.comment.html_url, github.event.comment.id, github.repository)) + || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@prql-bot') + && format('A review was submitted on PR #{0} that mentions you ({1}). Read the review and full PR context (description, diff, comments, CI status), then respond. If changes were requested, make them, commit, and push.', github.event.pull_request.number, github.event.review.html_url)) + || (github.event_name == 'pull_request_review' + && format('A review was submitted on a PR where you previously participated (PR #{0}, {1}). Read the review and full PR context. If the review requests changes or asks questions, respond appropriately. If the review approves or is between humans, exit silently.', github.event.pull_request.number, github.event.review.html_url)) || (contains(github.event.comment.body, '@prql-bot') && format('You were mentioned in a comment ({0}). Read the full issue or PR (description, diff, recent comments, CI status) and respond. If they are requesting changes, make the changes, commit, and push.', github.event.comment.html_url)) || format('A user commented on an issue/PR where you previously participated ({0}). Read the full context. Only respond if the comment is directed at you, asks a question you can help with, or requests changes you can make. A comment that responds to concerns you raised in a review is directed at you — briefly acknowledge that the concerns are resolved (or explain why they are not). If the conversation is between humans, exit silently.', github.event.comment.html_url) diff --git a/.github/workflows/tend-nightly.yaml b/.github/workflows/tend-nightly.yaml index 1105e4dc3487..3c1fe7ba4f71 100644 --- a/.github/workflows/tend-nightly.yaml +++ b/.github/workflows/tend-nightly.yaml @@ -3,7 +3,7 @@ name: tend-nightly on: schedule: - - cron: '17 6 * * *' + - cron: "17 6 * * *" workflow_dispatch: jobs: @@ -19,7 +19,6 @@ jobs: steps: - uses: actions/checkout@v6 with: - ref: main fetch-depth: 0 fetch-tags: true token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} @@ -32,4 +31,4 @@ jobs: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} bot_name: prql-bot prompt: | - /tend:tend-nightly + /tend-ci-runner:nightly diff --git a/.github/workflows/tend-notifications.yaml b/.github/workflows/tend-notifications.yaml new file mode 100644 index 000000000000..978852bfccf5 --- /dev/null +++ b/.github/workflows/tend-notifications.yaml @@ -0,0 +1,34 @@ +# Generated by tend. Regenerate with: uvx tend init + +name: tend-notifications +on: + schedule: + - cron: "*/15 * * * *" + workflow_dispatch: + +jobs: + notifications: + runs-on: ubuntu-24.04 + timeout-minutes: 60 + permissions: + contents: write + pull-requests: write + id-token: write + actions: read + issues: write + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + fetch-tags: true + token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} + + - uses: ./.github/actions/tend-setup + + - uses: max-sixty/tend@v1 + with: + github_token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + bot_name: prql-bot + prompt: | + /tend-ci-runner:notifications diff --git a/.github/workflows/tend-review.yaml b/.github/workflows/tend-review.yaml index 92d790c302ac..b2fb199d4571 100644 --- a/.github/workflows/tend-review.yaml +++ b/.github/workflows/tend-review.yaml @@ -4,20 +4,13 @@ name: tend-review on: pull_request_target: types: [opened, synchronize, ready_for_review, reopened] - pull_request_review: - types: [submitted] jobs: review: - if: | - (github.event_name == 'pull_request_target' && - github.event.pull_request.draft == false) || - (github.event_name == 'pull_request_review' && - github.event.pull_request.user.login == 'prql-bot' && - github.event.review.user.login != 'prql-bot' && - (github.event.review.state != 'approved' || github.event.review.body)) + if: >- + github.event.pull_request.draft == false concurrency: - group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true runs-on: ubuntu-24.04 timeout-minutes: 60 @@ -28,30 +21,13 @@ jobs: actions: read issues: write steps: - - name: Checkout (initial review) - if: github.event_name == 'pull_request_target' - uses: actions/checkout@v6 + - uses: actions/checkout@v6 with: ref: refs/pull/${{ github.event.pull_request.number }}/merge fetch-depth: 0 fetch-tags: true token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} - - name: Checkout (review response) - if: github.event_name == 'pull_request_review' - uses: actions/checkout@v6 - with: - fetch-depth: 0 - fetch-tags: true - token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} - - - name: Check out PR branch (review response) - if: github.event_name == 'pull_request_review' - run: gh pr checkout "$PR_NUMBER" - env: - GH_TOKEN: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} - PR_NUMBER: ${{ github.event.pull_request.number }} - - uses: ./.github/actions/tend-setup - uses: max-sixty/tend@v1 @@ -59,12 +35,6 @@ jobs: github_token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} bot_name: prql-bot - use_sticky_comment: ${{ github.event_name == 'pull_request_target' }} + use_sticky_comment: true prompt: >- - ${{ github.event_name == 'pull_request_target' - && format('/tend:tend-review {0}', github.event.pull_request.number) - || format( - 'A review was submitted on your PR #{0} ({1}). Read the review and full PR context (description, diff, comments, CI status), then respond appropriately. If changes were requested, make them, commit, and push. If questions were asked, answer them.', - github.event.pull_request.number, - github.event.review.html_url - ) }} + ${{ format('/tend-ci-runner:review {0}', github.event.pull_request.number) }} diff --git a/.github/workflows/tend-triage.yaml b/.github/workflows/tend-triage.yaml index 56f319deef6d..ae2041d1b3b3 100644 --- a/.github/workflows/tend-triage.yaml +++ b/.github/workflows/tend-triage.yaml @@ -12,7 +12,6 @@ concurrency: jobs: triage: if: >- - github.event.issue.user.type != 'Bot' && github.event.issue.user.login != 'prql-bot' runs-on: ubuntu-24.04 timeout-minutes: 60 @@ -25,7 +24,6 @@ jobs: steps: - uses: actions/checkout@v6 with: - ref: main fetch-depth: 0 fetch-tags: true token: ${{ secrets.PRQL_BOT_GITHUB_TOKEN }} @@ -38,4 +36,4 @@ jobs: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} bot_name: prql-bot prompt: | - /tend:tend-triage ${{ github.event.issue.number }} + /tend-ci-runner:triage ${{ github.event.issue.number }}