chore: bump minijinja from 2.21.0 to 2.23.0 #960
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Generated by tend 0.1.17. Regenerate with: uvx tend@latest init | |
| # | |
| # Do not edit this file directly — it will be overwritten on regeneration. | |
| # To customize behavior, edit the relevant skill (for example, | |
| # `running-tend`) in this repo's .claude/skills/ directory, or open an issue at | |
| # https://github.com/max-sixty/tend/issues for changes that need to | |
| # happen upstream in the tend-ci-runner plugin. | |
| name: tend-mention | |
| on: | |
| issues: | |
| types: [edited] | |
| issue_comment: | |
| types: [created, edited] | |
| # The review events reach only the `relay` job below: their runs carry | |
| # `refs/pull/N/merge`, which the operational secrets' environment does not | |
| # admit, so the secret-bearing jobs see them re-entered as a | |
| # `repository_dispatch` instead. Same-repo PRs only — the notifications poll | |
| # covers fork PRs. | |
| pull_request_review: | |
| types: [submitted] | |
| # `created` is intentionally absent. Modern GitHub fires *both* | |
| # pull_request_review and pull_request_review_comment for every newly-created | |
| # inline comment (the standalone POST /pulls/PR/comments endpoint, the | |
| # /replies endpoint, the "Add single comment" UI button, and reviews | |
| # submitted with inline comments — all empirically verified). Subscribing to | |
| # `created` would produce a duplicate dispatch whose handle runs collide on | |
| # the tend-mention-handle-PR concurrency group, with the loser cancelled and | |
| # posted as a CANCELLED check_run on the PR head SHA — which renders the | |
| # PR's statusCheckRollup as FAILURE even though the bot did its job from the | |
| # sibling run. Edits have no sibling event (review submissions don't fire on | |
| # edits), so we still need to listen for `edited` to catch edit-to-summon | |
| # ("@bot" added to an existing comment after the fact). | |
| pull_request_review_comment: | |
| types: [edited] | |
| # The relay's re-entry point. GitHub creates this run even though a | |
| # `GITHUB_TOKEN` triggered it — `workflow_dispatch` and `repository_dispatch` | |
| # are the two events exempt from the rule that token-triggered events start | |
| # no workflow — and it carries the default branch, which the environment | |
| # admits. | |
| repository_dispatch: | |
| types: [tend-mention-review] | |
| jobs: | |
| # The secretless half of the review path: move the event onto a ref the | |
| # environment admits, and nothing else. The merge ref itself can never be | |
| # admitted — a same-repo `pull_request` run executes the PR head's own | |
| # workflow files on that same ref, so admitting it would hand a pushed | |
| # workflow the secrets the environment exists to deny. All judgement lives | |
| # in `verify`, which re-reads the review or comment from the API, so a | |
| # skipped event costs one extra short run rather than a second copy of the | |
| # heuristics here. | |
| relay: | |
| # Fork PRs are excluded to hold long-standing behaviour: the notifications | |
| # poll covers them, and it applies author-association tiers that this path | |
| # does not. What the filter buys is that no fork head is checked out into a | |
| # secret-bearing run; it is not an authorship gate, since a mention from | |
| # any user with read access already wakes `handle` on a same-repo PR. | |
| # Widening this is a separate decision, and moot while a fork run's token | |
| # is refused the dispatch POST (403, probed). A dispatched run fails the | |
| # event check, so the relay cannot re-enter itself. | |
| if: | | |
| (github.event_name == 'pull_request_review' || | |
| github.event_name == 'pull_request_review_comment') && | |
| github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: ubuntu-24.04 | |
| # No secrets here. `contents: write` is what the dispatch POST needs, and | |
| # is the whole of what this token can do — probed both ways on a live | |
| # repo: an otherwise identical same-repo run declaring `contents: read` | |
| # is refused with 403, so a narrower token would leave every review | |
| # mention unanswered rather than merely unprivileged. It grants nobody a | |
| # new capability: only someone who can already push a branch can open the | |
| # same-repo PR whose workflow file this is, and they could declare any | |
| # permissions they liked in it. The merge restriction is what bounds that, | |
| # here as everywhere. | |
| permissions: | |
| contents: write | |
| steps: | |
| # Identifiers only: `verify` re-reads the review or comment from the | |
| # API, so the words the bot weighs and acts on are the ones GitHub | |
| # holds, and a forged dispatch faces the same scrutiny as a relayed one. | |
| - name: Re-enter on an admitted ref | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh api "repos/$GITHUB_REPOSITORY/dispatches" \ | |
| -f event_type=tend-mention-review \ | |
| -f "client_payload[kind]=${{ github.event_name }}" \ | |
| -f "client_payload[pr]=${{ github.event.pull_request.number }}" \ | |
| -f "client_payload[id]=${{ github.event.review.id || github.event.comment.id }}" | |
| verify: | |
| # Skip comments on the issues tend files about its own health: the action | |
| # auto-comments on those when a run fails or is refused, and without this | |
| # guard those comments re-trigger tend-mention, producing a | |
| # self-sustaining ~1 run/minute loop until the underlying condition | |
| # clears. The prompt's self-loop guard can't help here because the model | |
| # never executes — the action fails before Claude starts. A relayed review | |
| # enters as `repository_dispatch` and is judged in the check step below, | |
| # against the record the API holds. | |
| if: | | |
| github.event_name == 'repository_dispatch' || | |
| (github.event_name == 'issues' && | |
| contains(github.event.issue.body, '@prql-bot')) || | |
| (github.event_name == 'issue_comment' && | |
| contains(github.event.issue.labels.*.name, 'tend-outage') == false && contains(github.event.issue.labels.*.name, 'tend-rate-limit') == false) | |
| runs-on: ubuntu-24.04 | |
| environment: | |
| name: tend | |
| deployment: false | |
| outputs: | |
| should_run: ${{ steps.check.outputs.should_run }} | |
| reason: ${{ steps.check.outputs.reason }} | |
| url: ${{ steps.check.outputs.url }} | |
| ts: ${{ steps.check.outputs.ts }} | |
| steps: | |
| - name: Verify bot engagement | |
| id: check | |
| run: | | |
| # shellcheck shell=bash | |
| # Pre-check for tend-mention: decide whether the mention is addressed to the | |
| # bot — by name or by engagement — and so whether the agent boots at all. | |
| # | |
| # Inlined into the generated workflow (adopter repos have no copy of this | |
| # file), so it stays self-contained: env in, GITHUB_OUTPUT out. | |
| # | |
| # env: BOT_NAME, EVENT_NAME, COMMENT_BODY, COMMENT_AUTHOR, COMMENT_AUTHOR_TYPE, | |
| # ISSUE_BODY, ISSUE_OR_PR_NUMBER, ISSUE_AUTHOR, PR_URL, PAYLOAD_KIND, | |
| # PAYLOAD_PR, PAYLOAD_ID, GITHUB_REPOSITORY, GITHUB_OUTPUT, GITHUB_TOKEN | |
| # out: should_run, reason, url, ts | |
| # A relayed review event arrives as identifiers only ({kind, pr, id}): resolve | |
| # them against the API before judging anything, so the words weighed below are | |
| # the ones GitHub holds rather than whatever the payload carried. Any | |
| # write-scoped actor can POST a dispatch, so a forged payload faces the same | |
| # checks a real event does — and fetching by PR and id binds the two, so a | |
| # payload pairing a real review with some other PR dies here instead of | |
| # steering the handle job. The ids are spliced into API paths here and into the | |
| # prompt later, so reject anything but digits at this edge. | |
| KIND="$EVENT_NAME" | |
| if [ "$EVENT_NAME" = "repository_dispatch" ]; then | |
| KIND="$PAYLOAD_KIND" | |
| if ! [[ "$PAYLOAD_PR" =~ ^[0-9]+$ && "$PAYLOAD_ID" =~ ^[0-9]+$ ]]; then | |
| echo "malformed dispatch payload — skipping" | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| case "$KIND" in | |
| pull_request_review) | |
| if ! REVIEW=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PAYLOAD_PR/reviews/$PAYLOAD_ID"); then | |
| echo "review $PAYLOAD_ID not found on PR $PAYLOAD_PR — skipping" | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| REVIEW_AUTHOR=$(echo "$REVIEW" | jq -r '.user.login') | |
| # REST reports the state uppercase (a webhook payload's is lowercase); | |
| # normalize so the terminal-approval gate below reads one shape. | |
| REVIEW_STATE=$(echo "$REVIEW" | jq -r '.state | ascii_downcase') | |
| COMMENT_BODY=$(echo "$REVIEW" | jq -r '.body // ""') | |
| echo "url=$(echo "$REVIEW" | jq -r '.html_url')" >> "$GITHUB_OUTPUT" | |
| # A review without `submitted_at` (a PENDING one, which only a forged | |
| # dispatch can name) would otherwise write the string `null`, which | |
| # handle's `date -d` rejects — failing the job red where the empty-value | |
| # guard would have skipped it. | |
| echo "ts=$(echo "$REVIEW" | jq -r '.submitted_at // empty')" >> "$GITHUB_OUTPUT" | |
| ;; | |
| pull_request_review_comment) | |
| if ! COMMENT=$(gh api "repos/$GITHUB_REPOSITORY/pulls/comments/$PAYLOAD_ID"); then | |
| echo "comment $PAYLOAD_ID not found — skipping" | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| # Comments fetch by id alone, so bind the PR explicitly. | |
| if [ "$(echo "$COMMENT" | jq -r '.pull_request_url')" != "https://api.github.com/repos/$GITHUB_REPOSITORY/pulls/$PAYLOAD_PR" ]; then | |
| echo "comment $PAYLOAD_ID does not belong to PR $PAYLOAD_PR — skipping" | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| COMMENT_AUTHOR=$(echo "$COMMENT" | jq -r '.user.login') | |
| COMMENT_BODY=$(echo "$COMMENT" | jq -r '.body // ""') | |
| echo "url=$(echo "$COMMENT" | jq -r '.html_url')" >> "$GITHUB_OUTPUT" | |
| echo "ts=$(echo "$COMMENT" | jq -r '.updated_at')" >> "$GITHUB_OUTPUT" | |
| ;; | |
| *) | |
| echo "unknown dispatch kind '$KIND' — skipping" | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| ;; | |
| esac | |
| fi | |
| # Mentions always run | |
| if [ "$KIND" = "issues" ]; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # The bot's own comments never summon it (its PAT-based User account is | |
| # invisible to the Bot-type skip below). Placed *before* the mention check, | |
| # since a bot comment can quote a prior @-mention. Comments only: the bot's | |
| # review *submissions* are judged with the review kind below — a review carries | |
| # reviewer-role signal a comment can't. | |
| if { [ "$KIND" = "issue_comment" ] || [ "$KIND" = "pull_request_review_comment" ]; } \ | |
| && [ "$COMMENT_AUTHOR" = "$BOT_NAME" ]; then | |
| echo "should_run=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| if [ -n "$COMMENT_BODY" ] && printf '%s\n' "$COMMENT_BODY" | grep -qF "@$BOT_NAME"; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| echo "reason=mention" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Other bots' undirected comments (deploy notifications, CI status) summon by | |
| # mention only, never by the engagement heuristics below — which would boot a | |
| # no-op session per notification, twice when the source bot edits its comment. | |
| if [ "$KIND" = "issue_comment" ] && [ "$COMMENT_AUTHOR_TYPE" = "Bot" ]; then | |
| echo "should_run=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # A review's record includes review.body (checked above) but NOT the bodies of | |
| # the inline comments attached to the review. Fetch them so a first-contact | |
| # @-mention inside an inline comment is detected on PRs where the bot has no | |
| # prior engagement. One object per line, so `--paginate` concatenates pages | |
| # instead of reducing within one. Keep the `{body, in_reply_to_id}` | |
| # construction: `in_reply_to_id` is an *optional* property, absent rather than | |
| # null on a fresh comment, and building the object normalizes absent to null so | |
| # the `== null` select below counts both shapes. A bare `.in_reply_to_id` | |
| # stream would emit nothing for a fresh comment and count every review as | |
| # reply-only. | |
| if [ "$KIND" = "pull_request_review" ]; then | |
| INLINE=$(gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PAYLOAD_PR/reviews/$PAYLOAD_ID/comments" \ | |
| --jq '.[] | {body, in_reply_to_id}') | |
| if printf '%s\n' "$INLINE" | jq -r '.body' | grep -qF "@$BOT_NAME"; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| echo "reason=mention" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| FRESH_INLINE=$(printf '%s\n' "$INLINE" | jq -s '[.[] | select(.in_reply_to_id == null)] | length') | |
| # A contentless approval — no body, no inline comments — asks for nothing, | |
| # whoever submitted it, and the bot cannot merge on its own. Without this it | |
| # reads as engagement below and boots a session whose only outcome is a | |
| # silent exit. `approved` and `$INLINE` empty are both load-bearing: a bare | |
| # COMMENTED review is how GitHub wraps a human's inline reply (not terminal), | |
| # and an approval whose nits live inline is a request to the PR's author — on | |
| # a bot-authored PR, a role the bot has to act in. | |
| if [ "$REVIEW_STATE" = "approved" ] \ | |
| && [ -z "$COMMENT_BODY" ] \ | |
| && [ -z "$INLINE" ]; then | |
| echo "should_run=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| fi | |
| # Non-mention: check bot engagement | |
| if [ "$KIND" = "issue_comment" ]; then | |
| ISSUE_NUMBER="$ISSUE_OR_PR_NUMBER" | |
| if [ -z "$PR_URL" ]; then | |
| if [ "$ISSUE_AUTHOR" = "$BOT_NAME" ]; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| if printf '%s\n' "$ISSUE_BODY" | grep -qF "@$BOT_NAME"; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| # Don't reduce inside jq: `gh api --paginate` applies `--jq` once per page, | |
| # so `| length` emits one count per page rather than one overall. Past 100 | |
| # comments the variable holds e.g. `100\n7`, a numeric test on it errors | |
| # with `integer expression expected`, and the failed test falls through to | |
| # should_run=false — the bot goes quiet on its most-engaged threads. | |
| # Capture the per-element stream and test it for emptiness — the bare | |
| # substitution also keeps a failing `gh api` fatal under GHA's default | |
| # `bash -e`. | |
| BOT_COMMENTS=$(gh api --paginate "repos/$GITHUB_REPOSITORY/issues/$ISSUE_NUMBER/comments" \ | |
| --jq ".[] | select(.user.login == \"$BOT_NAME\") | .id") | |
| if [ -n "$BOT_COMMENTS" ]; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| PR_NUMBER="$ISSUE_NUMBER" | |
| else | |
| PR_NUMBER="$PAYLOAD_PR" | |
| fi | |
| PR_AUTHOR=$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json author --jq '.author.login') | |
| # The bot's own review summons a session in exactly one shape: the reviewer | |
| # role handing work to the author role — fresh content (a body, or an inline | |
| # comment that isn't a reply) on a PR the bot authored. On another author's PR | |
| # the review session already did whatever the review warranted; an empty-body | |
| # reply-only review is the synthetic container GitHub wraps around an inline | |
| # reply — the same comment the self-comment skip above drops on its other event | |
| # path. Either would otherwise read as engagement below (the BOT_REVIEWS | |
| # heuristic counts this very review) and boot a session that exits silently. | |
| # Sits *after* the inline @-mention scan, so an explicit summons the bot quotes | |
| # still wins. | |
| if [ "$KIND" = "pull_request_review" ] && [ "$REVIEW_AUTHOR" = "$BOT_NAME" ]; then | |
| if [ "$PR_AUTHOR" = "$BOT_NAME" ] \ | |
| && { [ -n "$COMMENT_BODY" ] || [ "$FRESH_INLINE" -gt 0 ]; }; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| echo "reason=participation" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| echo "should_run=false" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| if [ "$PR_AUTHOR" = "$BOT_NAME" ]; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| echo "reason=participation" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| # Captured, not counted — see the note on the issue-comment lookup above. | |
| BOT_REVIEWS=$(gh api --paginate "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/reviews" \ | |
| --jq ".[] | select(.user.login == \"$BOT_NAME\") | .id") | |
| if [ -n "$BOT_REVIEWS" ]; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| echo "reason=participation" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| BOT_COMMENTS=$(gh api --paginate "repos/$GITHUB_REPOSITORY/issues/$PR_NUMBER/comments" \ | |
| --jq ".[] | select(.user.login == \"$BOT_NAME\") | .id") | |
| if [ -n "$BOT_COMMENTS" ]; then | |
| echo "should_run=true" >> "$GITHUB_OUTPUT" | |
| echo "reason=participation" >> "$GITHUB_OUTPUT"; exit 0 | |
| fi | |
| echo "should_run=false" >> "$GITHUB_OUTPUT" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }} | |
| BOT_NAME: prql-bot | |
| EVENT_NAME: ${{ github.event_name }} | |
| COMMENT_BODY: ${{ github.event.comment.body }} | |
| COMMENT_AUTHOR: ${{ github.event.comment.user.login }} | |
| COMMENT_AUTHOR_TYPE: ${{ github.event.comment.user.type }} | |
| ISSUE_BODY: ${{ github.event.issue.body }} | |
| ISSUE_OR_PR_NUMBER: ${{ github.event.issue.number }} | |
| ISSUE_AUTHOR: ${{ github.event.issue.user.login }} | |
| PR_URL: ${{ github.event.issue.pull_request.url }} | |
| PAYLOAD_KIND: ${{ github.event.client_payload.kind }} | |
| PAYLOAD_PR: ${{ github.event.client_payload.pr }} | |
| PAYLOAD_ID: ${{ github.event.client_payload.id }} | |
| # The dispatch arm covers a relayed inline comment, whose id the check | |
| # step verified belongs to this PR; a review *submission* has no single | |
| # comment to react to, so it gets no eyes — same as when the events | |
| # arrived directly. | |
| - name: React with eyes | |
| if: | | |
| steps.check.outputs.should_run == 'true' | |
| && ((github.event.comment && contains(github.event.comment.body, '@prql-bot')) | |
| || (github.event.client_payload.kind == 'pull_request_review_comment' | |
| && steps.check.outputs.reason == 'mention')) | |
| run: | | |
| gh api "repos/$REPO/$TARGET/reactions" -f content=eyes --silent \ | |
| || echo "::warning::could not add the eyes reaction" | |
| env: | |
| REPO: ${{ github.repository }} | |
| TARGET: ${{ github.event_name == 'issue_comment' | |
| && format('issues/comments/{0}', github.event.comment.id) | |
| || format('pulls/comments/{0}', github.event.comment.id || github.event.client_payload.id) }} | |
| GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }} | |
| handle: | |
| needs: verify | |
| if: needs.verify.outputs.should_run == 'true' | |
| concurrency: | |
| group: ${{ github.workflow }}-handle-${{ github.event.issue.number || github.event.client_payload.pr }} | |
| cancel-in-progress: false | |
| runs-on: ubuntu-24.04 | |
| environment: | |
| name: tend | |
| deployment: false | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| actions: read | |
| issues: write | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| token: ${{ secrets.TEND_BOT_TOKEN }} | |
| - uses: ./.github/actions/tend-setup | |
| - name: Check out PR branch | |
| if: | | |
| (github.event_name == 'issue_comment' && github.event.issue.pull_request.url != '') || | |
| github.event_name == 'repository_dispatch' | |
| run: | | |
| PR_STATE=$(gh pr view "$PR_NUMBER" --json state --jq '.state') | |
| if [ "$PR_STATE" = "OPEN" ]; then | |
| gh pr checkout "$PR_NUMBER" | |
| else | |
| echo "::warning::PR is $PR_STATE — staying on default branch" | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }} | |
| PR_NUMBER: ${{ github.event_name == 'issue_comment' && github.event.issue.number || github.event.client_payload.pr }} | |
| - 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: | |
| # A relayed event's timestamp comes from verify, which read it off | |
| # the API record — the dispatch payload never carries one to spoof. | |
| EVENT_TS: ${{ github.event.comment.updated_at || needs.verify.outputs.ts || github.event.issue.updated_at }} | |
| - uses: max-sixty/tend/claude@0.1.17 | |
| with: | |
| github_token: ${{ secrets.TEND_BOT_TOKEN }} | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| bot_name: prql-bot | |
| model: opus | |
| 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.client_payload.kind == 'pull_request_review_comment' && needs.verify.outputs.reason == 'mention' | |
| && format('You were mentioned in an inline review comment on PR #{0} ({1}, comment ID {2}). Read the full context, then respond. If changes are requested, make them, commit, and push.', github.event.client_payload.pr, needs.verify.outputs.url, github.event.client_payload.id)) | |
| || (github.event.client_payload.kind == 'pull_request_review_comment' | |
| && format('An inline review comment was posted on a PR where you previously participated (PR #{0}, {1}, comment ID {2}). Read the full context. Only respond if the comment is directed at you or requests changes.', github.event.client_payload.pr, needs.verify.outputs.url, github.event.client_payload.id)) | |
| || (github.event.client_payload.kind == 'pull_request_review' && needs.verify.outputs.reason == 'mention' | |
| && format('A review was submitted on PR #{0} that mentions you ({1}, review ID {2}). Read the review and full context, then respond. If changes were requested, make them, commit, and push.', github.event.client_payload.pr, needs.verify.outputs.url, github.event.client_payload.id)) | |
| || (github.event.client_payload.kind == 'pull_request_review' | |
| && format('A review was submitted on a PR where you previously participated (PR #{0}, {1}, review ID {2}). Read the review and full context. If it requests changes or asks questions, respond appropriately — including when you authored the review: a review your review workflow left on your own PR is your reviewer role speaking, not a self-loop, so action it. Exit silently for a plain approval, a review with no actionable content, or one between other participants.', github.event.client_payload.pr, needs.verify.outputs.url, github.event.client_payload.id)) | |
| || (contains(github.event.comment.body, '@prql-bot') | |
| && format('You were mentioned in a comment ({0}). Read the full context and respond. If changes are requested, make them, 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. If the conversation is between other participants, exit silently.', github.event.comment.html_url) | |
| }} | |
| - name: Restore local setup actions for POST cleanup | |
| if: always() | |
| run: | | |
| dir=.github/actions/tend-setup | |
| git checkout "$GITHUB_SHA" -- "$dir" || | |
| echo "::warning::could not restore $dir from $GITHUB_SHA; POST cleanup of the local action may fail" | |
| - name: Remove the eyes reaction | |
| if: | | |
| always() | |
| && ((github.event.comment && contains(github.event.comment.body, '@prql-bot')) | |
| || (github.event.client_payload.kind == 'pull_request_review_comment' | |
| && needs.verify.outputs.reason == 'mention')) | |
| run: | | |
| REACTION_ID=$(gh api "repos/$REPO/$TARGET/reactions?content=eyes" \ | |
| --jq ".[] | select(.user.login == \"$BOT_NAME\") | .id" | head -n1) | |
| if [ -n "$REACTION_ID" ]; then | |
| gh api -X DELETE "repos/$REPO/$TARGET/reactions/$REACTION_ID" --silent \ | |
| || echo "::warning::could not remove the eyes reaction" | |
| fi | |
| env: | |
| REPO: ${{ github.repository }} | |
| TARGET: ${{ github.event_name == 'issue_comment' | |
| && format('issues/comments/{0}', github.event.comment.id) | |
| || format('pulls/comments/{0}', github.event.comment.id || github.event.client_payload.id) }} | |
| BOT_NAME: prql-bot | |
| GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }} |