Files
SenrokaiandClaude Fable 5 c1e7f6363d Pin the reviewer, bound its run, and wake it when a pull request reopens
Junie has been reviewing pull requests here since the key was added, and eight
of the last eight runs succeeded. What it was not, was configured like the
sibling repositories, and three of those differences are worth closing.

The action was referenced as `@v1`. It is the only third-party action in this
repository and the only one handed a repository secret, so its definition
should not be able to change under us. `v1` and `v1.7.5` resolve to the same
commit today — the pin is not about which code runs now, it is about who gets
to decide that later.

There was no timeout. A run that goes wrong hangs rather than stops, and the
pull request shows a pending check until Actions gives up on its own six hours
later. Forty-five minutes, not the thirty the siblings use: the longest review
this repository has actually had ran thirty-five, on the largest diff so far,
and a ceiling that cuts a successful review short is worse than none.

And a pull request closed and reopened had had no review since it was closed.

Left alone deliberately: the absent-key step, which says so in the run summary
instead of failing a pull request for a reason that has nothing to do with its
code, and the lack of a `branches:` filter — work here stacks feature onto
feature, and filtering on main would skip every pull request in a chain but the
last.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016jxMkwA2rbicdGxHosecYi
2026-08-20 17:59:15 +02:00

85 lines
4.5 KiB
YAML

name: Junie review
# JetBrains' Junie agent reads each pull request and leaves inline review comments. It runs
# alongside CI rather than as part of it: CI answers whether the code works, this answers whether
# it reads well, and a review comment should never be able to turn the build red.
on:
pull_request:
# `reopened` because a pull request closed and reopened has had no review since it was
# closed, and `ready_for_review` because the draft guard below would otherwise skip a pull
# request opened as a draft forever. No `branches:` filter: work here stacks feature onto
# feature, so filtering on main would skip every pull request in a chain but the last.
types: [opened, synchronize, reopened, ready_for_review]
# A review of the previous push is stale the moment a new one lands, so supersede it rather than
# letting two reviews comment on the same pull request. Keyed by pull request rather than by ref
# so a push to `main` never cancels a review.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: true
# Read the code, write the review. `issues: write` is what posts the summary comment — GitHub
# treats a pull request's conversation timeline as an issue.
permissions:
contents: read
pull-requests: write
issues: write
jobs:
review:
name: Review the diff
runs-on: ubuntu-latest
# A ceiling, not a target: a run that goes wrong hangs rather than stops, and the pull
# request shows a pending check until it does. Set above the longest review this repository
# has actually had — 35 minutes, on the largest diff so far — rather than at the sibling
# repositories' 30, which would have cut that one short.
timeout-minutes: 45
# Drafts are work in progress and forks cannot see `JUNIE_API_KEY` — GitHub withholds secrets
# from `pull_request` runs on forked branches, so the job would fail on a missing key rather
# than say anything useful about the code.
if: >-
github.event.pull_request.draft == false &&
github.event.pull_request.head.repo.full_name == github.repository
env:
# Whether the key exists, resolved once here because `secrets` is not one of the contexts a
# step's `if` can read, while `env` is.
HAS_JUNIE_KEY: ${{ secrets.JUNIE_API_KEY != '' }}
steps:
# Without the key the action exits on "Missing required input", which would mark every pull
# request failed for a reason that has nothing to do with its code. Say so in the run
# summary and stop instead — visible to anyone who looks, blocking nobody who doesn't.
- name: Explain the absent key
if: env.HAS_JUNIE_KEY != 'true'
run: |
echo "No \`JUNIE_API_KEY\` secret is set, so this pull request was not reviewed." >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "Generate a key at <https://junie.jetbrains.com/cli> and add it under" >> "$GITHUB_STEP_SUMMARY"
echo "Settings → Secrets and variables → Actions." >> "$GITHUB_STEP_SUMMARY"
- uses: actions/checkout@v5
if: env.HAS_JUNIE_KEY == 'true'
with:
# Junie reads the diff through the GitHub API, so the full history it would otherwise
# clone is never used.
fetch-depth: 1
# Pinned to a commit rather than to `v1`: this is the only third-party action here and it
# is handed a repository secret, so its definition should not be able to change under us.
# `v1` resolves to this same commit today; the pin is about who gets to move it. The pin
# covers this definition only — the composite pulls its own dependencies by tag and fetches
# the Junie CLI over the network. Bump by resolving the new release's commit, never by
# moving a tag name.
- uses: JetBrains/junie-github-action@3f6a906f11c6f67c76efaf3d3264bbb615f9ce29 # v1.7.5
if: env.HAS_JUNIE_KEY == 'true'
# An opinion, not a gate. If Junie is down or rate-limited that is worth seeing in the
# log, but it is not a reason to hold a pull request whose tests pass.
continue-on-error: true
with:
junie_api_key: ${{ secrets.JUNIE_API_KEY }}
# The action's built-in review prompt. Replace with a prompt block to review against
# criteria of our own.
prompt: code-review
# Rewrite one comment on each push instead of stacking a new one per revision, so the
# conversation shows the current state of the review rather than its history.
use_single_comment: "true"