Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions generator/src/tend/templates/mention.yaml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,20 @@ jobs:
exit 0
fi

# The Bot-type check above only catches GitHub App / Bot accounts.
# Our own bot is a PAT-based User account, so its comments fall
# through to the engagement heuristics below (bot-authored issue, or
# "bot has prior comments") and spin up a handle job that the prompt's
# self-loop guard then exits silently — pure waste. The bot never
# needs to respond to its own comment, so skip here. Runs after the
# @-mention check so a (hypothetical) self-summons is still honored.
# Fires on, e.g., the monthly tracking-issue rollover where the bot
# posts evidence-gist links on its own issue.
if [ "$EVENT_NAME" = "issue_comment" ] && [ "$COMMENT_AUTHOR" = "<<cfg.bot_name>>" ]; then
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi

# The bot's own empty-body APPROVED review is terminal — nothing to
# act on. The engagement heuristic below counts this very review
# (BOT_REVIEWS > 0) and would spin up a no-op session. Gate on three
Expand Down Expand Up @@ -171,6 +185,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.<<cfg.bot_token_secret>> }}
EVENT_NAME: ${{ github.event_name }}
COMMENT_BODY: ${{ github.event.comment.body || github.event.review.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 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ jobs:
exit 0
fi

# The Bot-type check above only catches GitHub App / Bot accounts.
# Our own bot is a PAT-based User account, so its comments fall
# through to the engagement heuristics below (bot-authored issue, or
# "bot has prior comments") and spin up a handle job that the prompt's
# self-loop guard then exits silently ? pure waste. The bot never
# needs to respond to its own comment, so skip here. Runs after the
# @-mention check so a (hypothetical) self-summons is still honored.
# Fires on, e.g., the monthly tracking-issue rollover where the bot
# posts evidence-gist links on its own issue.
if [ "$EVENT_NAME" = "issue_comment" ] && [ "$COMMENT_AUTHOR" = "test-bot" ]; then
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi

# The bot's own empty-body APPROVED review is terminal ? nothing to
# act on. The engagement heuristic below counts this very review
# (BOT_REVIEWS > 0) and would spin up a no-op session. Gate on three
Expand Down Expand Up @@ -156,6 +170,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
COMMENT_BODY: ${{ github.event.comment.body || github.event.review.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 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ jobs:
exit 0
fi

# The Bot-type check above only catches GitHub App / Bot accounts.
# Our own bot is a PAT-based User account, so its comments fall
# through to the engagement heuristics below (bot-authored issue, or
# "bot has prior comments") and spin up a handle job that the prompt's
# self-loop guard then exits silently ? pure waste. The bot never
# needs to respond to its own comment, so skip here. Runs after the
# @-mention check so a (hypothetical) self-summons is still honored.
# Fires on, e.g., the monthly tracking-issue rollover where the bot
# posts evidence-gist links on its own issue.
if [ "$EVENT_NAME" = "issue_comment" ] && [ "$COMMENT_AUTHOR" = "test-bot" ]; then
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi

# The bot's own empty-body APPROVED review is terminal ? nothing to
# act on. The engagement heuristic below counts this very review
# (BOT_REVIEWS > 0) and would spin up a no-op session. Gate on three
Expand Down Expand Up @@ -156,6 +170,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
COMMENT_BODY: ${{ github.event.comment.body || github.event.review.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 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ jobs:
exit 0
fi

# The Bot-type check above only catches GitHub App / Bot accounts.
# Our own bot is a PAT-based User account, so its comments fall
# through to the engagement heuristics below (bot-authored issue, or
# "bot has prior comments") and spin up a handle job that the prompt's
# self-loop guard then exits silently ? pure waste. The bot never
# needs to respond to its own comment, so skip here. Runs after the
# @-mention check so a (hypothetical) self-summons is still honored.
# Fires on, e.g., the monthly tracking-issue rollover where the bot
# posts evidence-gist links on its own issue.
if [ "$EVENT_NAME" = "issue_comment" ] && [ "$COMMENT_AUTHOR" = "test-bot" ]; then
echo "should_run=false" >> "$GITHUB_OUTPUT"
exit 0
fi

# The bot's own empty-body APPROVED review is terminal ? nothing to
# act on. The engagement heuristic below counts this very review
# (BOT_REVIEWS > 0) and would spin up a no-op session. Gate on three
Expand Down Expand Up @@ -156,6 +170,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.TEND_BOT_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
COMMENT_BODY: ${{ github.event.comment.body || github.event.review.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 }}
Expand Down
43 changes: 43 additions & 0 deletions generator/tests/test_generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,49 @@ def test_mention_verify_skips_bot_comments_without_mention(tmp_path: Path) -> No
)


def test_mention_verify_skips_self_authored_comments(tmp_path: Path) -> None:
"""The bot's own comments must not spin up a handle session.

The Bot-type check only catches GitHub App / Bot accounts. Tend's own bot
is a PAT-based User account, so its comments fall through to the engagement
heuristics (bot-authored issue, or "bot has prior comments") and reach the
handle job, which exits silently via the prompt's self-loop guard — pure
waste. This recurs on the monthly tracking-issue rollover (review-reviewers
posts evidence-gist links on its own issue) and on duplicate-tracking
notices. Skip self-authored `issue_comment` events at the gate."""
cfg = Config.load(_minimal_config(tmp_path))
workflows = {wf.filename: wf for wf in generate_all(cfg)}
mention = workflows["tend-mention.yaml"]
data = yaml.safe_load(mention.content)
check_step = next(
s for s in data["jobs"]["verify"]["steps"] if s.get("id") == "check"
)
run = check_step["run"]

assert check_step["env"].get("COMMENT_AUTHOR") == (
"${{ github.event.comment.user.login }}"
), (
"verify must wire github.event.comment.user.login so the script can "
"recognize the bot's own (User-type) comments"
)

assert '"$COMMENT_AUTHOR" = "test-bot"' in run, (
"verify must short-circuit issue_comment events authored by the bot "
"itself — its User-type account is missed by the Bot-type check"
)

# The self-authored guard must run after the @-mention check (so a
# self-summons is still honored) and before the bot-authored-issue
# short-circuit that would otherwise spin up the no-op session.
mention_idx = run.index("grep -qF '@test-bot'")
self_guard_idx = run.index('"$COMMENT_AUTHOR" = "test-bot"')
issue_author_idx = run.index('"$ISSUE_AUTHOR" = "test-bot"')
assert mention_idx < self_guard_idx < issue_author_idx, (
"self-authored comment guard must run after the @-mention check and "
"before the bot-authored-issue short-circuit"
)


def test_mention_verify_no_concurrency(tmp_path: Path) -> None:
"""verify job must not have concurrency — a non-mention comment can cancel
an explicit @bot mention if both arrive on the same PR within seconds (#93)."""
Expand Down
Loading