Skip to content
Merged
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
4 changes: 4 additions & 0 deletions .changeset/cozy-doodles-lick.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
---

Add maintainer-triggered pollystellabot review automation.
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ jobs:
- name: Create release PR or publish
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
with:
version: pnpm changeset version && pnpm install --no-frozen-lockfile
publish: pnpm changeset publish
version: pnpm run release:version
publish: pnpm run release:publish
commit: "ci: release"
title: "ci: release"
env:
Expand Down
132 changes: 132 additions & 0 deletions .github/workflows/review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: Review PR

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]

permissions:
contents: read
issues: read
pull-requests: read

jobs:
review:
name: Run /review
if: >-
github.event.sender.type != 'Bot'
&& contains(github.event.comment.body, '/review')
&& contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)
&& (github.event_name != 'issue_comment' || github.event.issue.pull_request != null)
concurrency:
group: ${{ github.workflow }}-${{ github.event.issue.number || github.event.pull_request.number || github.ref }}
cancel-in-progress: false
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Resolve PR number
id: pr-number
env:
PR_NUMBER: ${{ github.event.issue.number || github.event.pull_request.number }}
run: echo "number=${PR_NUMBER}" >> "$GITHUB_OUTPUT"

- name: Verify PR exists
id: verify-pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
run: |
if gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > /dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "::warning::PR #${PR_NUMBER} not found; skipping review."
fi

- name: Checkout repository
if: steps.verify-pr.outputs.exists == 'true'
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
persist-credentials: false

- name: Setup Node.js
if: steps.verify-pr.outputs.exists == 'true'
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x

- name: Check pollystellabot secrets
if: steps.verify-pr.outputs.exists == 'true'
env:
POLYSTELLABOT_APP_ID: ${{ secrets.POLYSTELLABOT_APP_ID }}
POLYSTELLABOT_PRIVATE_KEY: ${{ secrets.POLYSTELLABOT_PRIVATE_KEY }}
run: |
if [[ -z "$POLYSTELLABOT_APP_ID" || -z "$POLYSTELLABOT_PRIVATE_KEY" ]]; then
echo "::error::Set POLYSTELLABOT_APP_ID and POLYSTELLABOT_PRIVATE_KEY as Actions secrets before using /review."
exit 1
fi

- name: Generate pollystellabot token
if: steps.verify-pr.outputs.exists == 'true'
id: pollystellabot-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ secrets.POLYSTELLABOT_APP_ID }}
private-key: ${{ secrets.POLYSTELLABOT_PRIVATE_KEY }}
permission-contents: read
permission-issues: write
permission-pull-requests: write

- name: Install opencode
if: steps.verify-pr.outputs.exists == 'true'
run: npm install --global "opencode-ai@1.15.7"

- name: Get PR details
if: steps.verify-pr.outputs.exists == 'true'
id: pr-details
env:
GH_TOKEN: ${{ steps.pollystellabot-token.outputs.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ steps.pr-number.outputs.number }}
run: |
gh api "/repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" > /tmp/pr.json
{
echo 'title<<PR_TITLE_EOF'
jq -r '.title // ""' /tmp/pr.json
echo PR_TITLE_EOF
echo "head_sha=$(jq -r .head.sha /tmp/pr.json)"
echo 'body<<PR_BODY_EOF'
jq -r '.body // ""' /tmp/pr.json
echo PR_BODY_EOF
} >> "$GITHUB_OUTPUT"

- name: Run Review
if: steps.verify-pr.outputs.exists == 'true'
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_GATEWAY_ID: ${{ secrets.CLOUDFLARE_GATEWAY_ID }}
GH_TOKEN: ${{ steps.pollystellabot-token.outputs.token }}
GITHUB_TOKEN: ${{ steps.pollystellabot-token.outputs.token }}
MODEL: ${{ vars.POLYSTELLABOT_MODEL || 'opencode/claude-opus-4-5' }}
AGENT: auto-reviewer
SHARE: "false"
USE_GITHUB_TOKEN: "true"
MENTIONS: "/review"
OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }}
OPENCODE_CONFIG_CONTENT: '{"permission":{"external_directory":{"*":"deny","/tmp/**":"allow","~/.local/share/opencode/tool-output/**":"allow"},"doom_loop":"deny"}}'
PROMPT: |
Review pull request #${{ steps.pr-number.outputs.number }} ("${{ steps.pr-details.outputs.title }}").

Follow your auto-reviewer instructions for investigation, severity calibration, and posting. Post a single GitHub PR review with line-anchored comments when you find actionable issues. If there are no actionable issues, respond with only "LGTM!" and do not post a PR review.

<pr_number>${{ steps.pr-number.outputs.number }}</pr_number>
<head_sha>${{ steps.pr-details.outputs.head_sha }}</head_sha>
<pr_description>
${{ steps.pr-details.outputs.body }}
</pr_description>
run: opencode github run
36 changes: 36 additions & 0 deletions .github/workflows/semgrep.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Semgrep OSS scan

on:
pull_request: {}
push:
branches: [main, master]
workflow_dispatch: {}
schedule:
- cron: "0 0 20 * *"

permissions:
contents: read

concurrency:
group: semgrep-${{ github.event_name }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
semgrep:
name: semgrep-oss
runs-on: ubuntu-slim
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 1
persist-credentials: false
- id: cache-semgrep
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5
with:
path: ~/.local
key: semgrep-1.160.0-${{ runner.os }}
- if: steps.cache-semgrep.outputs.cache-hit != 'true'
run: pip install --user semgrep==1.160.0
- run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- run: semgrep scan --config=auto
75 changes: 75 additions & 0 deletions .opencode/agents/auto-reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
description: Automated PR reviewer for PolyStella's /review workflow. Used in CI to leave structured pull request feedback, not for interactive local development.
mode: primary
temperature: 0.1
permission:
read: allow
glob: allow
grep: allow
list: allow
edit: deny
task: deny
webfetch: deny
websearch: deny
question: deny
doom_loop: deny
external_directory:
"*": deny
"/tmp/**": allow
"~/.local/share/opencode/tool-output/**": allow
bash:
"*": deny
"gh api *": allow
"gh pr diff *": allow
"gh pr view *": allow
"git diff*": allow
"git log*": allow
"git show*": allow
"git status*": allow
---

You are reviewing a pull request on the **cloudflare/polystella** repository. Your job is to find real bugs, behavioral regressions, security issues, violated repository invariants, and missing tests. Do not make code changes.

The repo's AGENTS.md is loaded separately. Read it carefully and treat violations as first-class findings. Pay special attention to strict TypeScript rules, cache-key stability, apply-before-PUT, local cache index isolation, runtime bridge timing, URL rewrite idempotence, path separator semantics, provider error classification, and UI-string token preservation.

## Investigation

1. Start with the PR description and changed files. Verify the description matches the diff.
2. Read the full diff with `gh pr diff <PR> --repo cloudflare/polystella`.
3. For every changed source or test file, inspect enough surrounding code to understand behavior, not just the diff hunk.
4. Trace call sites and sibling implementations when a public type, runtime API, parser adapter, cache path, route shim, CLI command, or translation flow changes.
5. Check tests. Production behavior changes should have meaningful coverage, especially translation pipeline, cache/storage, runtime, routing, parser, and UI-string changes.
6. Do not run package scripts or execute PR-authored code. This workflow reviews code only.

## Findings

Use calibrated severity:

- **Needs fixing** for logic bugs, regressions, security issues, broken contracts, missing required tests, or AGENTS.md invariant violations.
- **Suggestion** for low-risk maintainability, clarity, or style issues.

Each finding should be concrete and anchored to a changed line. Explain what currently happens, why it is wrong, and what would fix it. Use GitHub suggestion blocks only when the replacement is obvious and safe.

Be willing to find nothing. If the PR is sound, respond with exactly `LGTM!`.

## Posting

When you find issues, post one GitHub PR review via `gh api`:

```bash
gh api repos/cloudflare/polystella/pulls/<PR>/reviews \
-X POST \
--input - <<JSON
{
"event": "COMMENT",
"body": "",
"comments": [
{ "path": "src/example.ts", "line": 123, "side": "RIGHT", "body": "**Needs fixing:** ..." }
]
}
JSON
```

Default to `event: "COMMENT"`. Use `REQUEST_CHANGES` only for true blockers such as security vulnerabilities, data-loss bugs, build-breaking regressions, or violations of explicit repository invariants that make the PR unsafe to merge.

Leave the top-level review body empty. The workflow will post your final text as a separate comment. Do not mention token permissions or automation limitations unless they directly caused the review to be incomplete.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,9 @@
"format": "prettier --write .",
"format:check": "prettier --check .",
"prepare": "pnpm build && (git config core.hooksPath .githooks 2>/dev/null || true)",
"prepublishOnly": "pnpm build && pnpm build:llms"
"prepublishOnly": "pnpm build && pnpm build:llms",
"release:version": "changeset version && pnpm install --no-frozen-lockfile",
"release:publish": "changeset publish"
},
"dependencies": {
"acorn": "^8.17.0",
Expand Down
Loading