Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
36 changes: 36 additions & 0 deletions .github/workflows/copilot-review-notify.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: copilot-review-notify

on:
pull_request_review:
types: [submitted]

jobs:
comment:
if: github.event.review.user.login == 'github-copilot[bot]'
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Add comment noting Copilot review
uses: actions/github-script@v7
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const number = context.payload.pull_request.number;
const url = context.payload.pull_request.html_url;
await github.rest.issues.createComment({
owner,
repo,
issue_number: number,
body: `Automated: GitHub Copilot has submitted a review for ${url}.`
});
- name: Optional Slack notify
if: ${{ secrets.SLACK_WEBHOOK_URL != '' }}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: |
pr_url="${{ github.event.pull_request.html_url }}"
payload=$(jq -n --arg text "Copilot reviewed $pr_url" '{text: $text}')
curl -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK_URL"
48 changes: 48 additions & 0 deletions .github/workflows/wait-for-copilot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: wait-for-copilot

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
wait:
name: Wait for Copilot review
runs-on: ubuntu-latest
permissions:
pull-requests: read
contents: read
concurrency:
group: wait-for-copilot-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- name: Poll for Copilot review (max 15m)
uses: actions/github-script@v7
with:
script: |
const pr = context.payload.pull_request;
const owner = context.repo.owner;
const repo = context.repo.repo;
const number = pr.number;
const deadline = Date.now() + 15 * 60 * 1000; // 15 minutes
const botLogin = 'github-copilot[bot]';

async function hasCopilotFeedback() {
const [reviews, comments] = await Promise.all([
github.rest.pulls.listReviews({ owner, repo, pull_number: number, per_page: 100 }),
github.rest.issues.listComments({ owner, repo, issue_number: number, per_page: 100 }),
]);
const anyReview = reviews.data.some(r => (r.user?.login || '') === botLogin);
const anyComment = comments.data.some(c => (c.user?.login || '') === botLogin);
core.info(`Copilot review detected: ${anyReview}, comment detected: ${anyComment}`);
return anyReview || anyComment;
}

while (Date.now() < deadline) {
if (await hasCopilotFeedback()) {
core.notice('Copilot review found.');
return;
}
await new Promise(r => setTimeout(r, 20_000));
}
core.setFailed('Copilot review not found within 15 minutes.');

50 changes: 50 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,53 @@ If you don’t have the tool:
### Test assertions

- Tests should use pretty_assertions::assert_eq for clearer diffs. Import this at the top of the test module if it isn't already.

## PR Autopilot (agent policy)

The agent may prepare and update PRs when explicitly asked. It follows these guardrails:

- Preconditions
- The user says: “prepare PR”, “update PR”, “trigger Codex review”, “post PR comment”, or “generate review bundle”.
- `gh` is authenticated and SSO‑authorized for the target org/repo.
- Remotes `origin` (fork) and `upstream` (main) are configured.

- Steps (prepare PR)
- Scope check: `git diff --name-only origin/main...HEAD` and confirm only intended files are touched.
- Formatting + lint: `cd codex-rs && just fmt` and `just fix -p <crate>` for touched crates.
- Targeted tests for touched crates (e.g., `cargo test -p codex-tui`).
- Create/checkout a branch, `git add -A`, `git commit`, `git push --set-upstream origin <branch>`.
- Open/update PR with `gh pr create`/`gh pr edit` using a local markdown body file.

- Steps (trigger Codex Review)
- `git fetch upstream && git rebase upstream/main`.
- `git commit --allow-empty -m "chore: re-run Codex Review" && git push --force-with-lease`.

- Steps (comments/body)
- `gh pr comment <number> -R <org/repo> --body-file <path>`.
- `gh pr edit <number> -R <org/repo> --body-file <path>`.

- Guardrails
- Never push unrelated diffs; trim PRs to the intended files.
- Always prefer `--force-with-lease` over `--force`.
- For larger changes, generate a single‑file review bundle (see scripts below) and include a short “How to verify” section.

## PR helpers (scripts + just targets)

We keep a few lightweight commands so the agent (and humans) can perform routine PR tasks reliably.

- `scripts/pr.sh` (invoked by just targets)
- `prepare <branch> <body_md>`: run fmt/fix/tests, push branch, and create/update PR.
- `comment <pr> <md>`: post a PR comment from a file.
- `body <pr> <md>`: update PR body from a file.
- `trigger`: create an empty commit and push to re‑run Codex Review.

- `codex-rs/justfile` (targets)
- `pr-fmt`: `cd codex-rs && just fmt`
- `pr-fix-<crate>`: `cd codex-rs && just fix -p <crate>`
- `pr-tests-<crate>`: e.g., `cd codex-rs && cargo test -p codex-tui`
- `pr-trigger`: empty commit + push with lease
- `pr-body PR=<n> FILE=<path>`: update PR body
- `pr-comment PR=<n> FILE=<path>`: post PR comment
- `review-bundle FILE=<out.md>`: generate a single‑file gist for code review (diffs + excerpts + test plan)

These helpers are safe defaults the agent can call when asked; they also make human review runs reproducible.
Loading