Skip to content

Commit d745bfa

Browse files
authored
feat(ci): issue auto-implement action and workflow (#238)
* feat(ci): add issue auto-implement action and workflow - Add workflow issue-auto-implement.yml (label, comment, PR review triggers) - Add composite action: team check, labels, assess script, implement placeholder, verify loop, create PR - Add assess script (TypeScript/tsx, Claude, fixtures) with vitest tests - Add workflow issue-auto-implement-test.yml to run assess tests on PR - Add README (usage, inputs, testing) and AGENTS.md (flows, verification, next steps) - Use AUTO_IMPLEMENT_* prefix for secrets/vars; require github_allowed_trigger_team Made-with: Cursor * feat(ci): pass context_files into assess and include in Claude prompt - Add CONTEXT_FILES and GITHUB_WORKSPACE to assess step env - Load repo files (AGENTS.md, REFERENCE.md, etc.) and append to assessment prompt - Skip missing files; REPO_ROOT from GITHUB_WORKSPACE or cwd for local runs Made-with: Cursor * feat(ci): fetch all issue comments for assessment - For issues and issue_comment events, call GitHub API for issue comments - Include all comments in Claude prompt (author, date, body) - Fall back to payload comment/comments when API not used Made-with: Cursor * fix(ci): stabilize issue-auto-implement assess tests workflow - Set GITHUB_WORKSPACE in job env so assess script has repo root in CI - Use working-directory instead of cd for install/test step - Add npm cache keyed by assess package-lock.json Made-with: Cursor * fix(ci): do not run main() when assess script is loaded by Vitest In CI the runner sets GITHUB_EVENT_PATH, so the script was invoking main() on import; loadPayload() then threw and process.exit(1) caused Vitest to fail with an unhandled error. Only run main() when GITHUB_EVENT_PATH is set and VITEST is not (i.e. when invoked as script, not by tests). Made-with: Cursor * feat(ci): wire Claude implement step and commit-and-push - Add assess/implement.ts: fetch issue, call Claude for edits JSON, apply files, write commit message - Action: run implement script with env; commit and push using generated commit message - Add .gitignore for .commit_msg; document implement script in AGENTS.md Made-with: Cursor * feat(ci): true implement-verify loop with PREVIOUS_VERIFY_OUTPUT - Implement script accepts PREVIOUS_VERIFY_OUTPUT and adds it to Claude prompt on retry - Single step loops: implement → commit/push → verify; on verify failure retry with output - Create PR uses implement_verify_loop.outcome; document loop in AGENTS.md Made-with: Cursor * refactor(issue-auto-implement): move assess into src/ and test/ - Main code: assess/src/ (index.ts, implement.ts, normalize.ts) - Tests: assess/test/ (index.test.ts, normalize.test.ts) - Fixtures stay at assess/fixtures/ - Update package.json scripts and action.yml to use src/ - Add .env.example, setup-local-env.sh, .gitignore .env; update README/AGENTS paths Made-with: Cursor * refactor(issue-auto-implement): consolidate tests under test/ (unit, integration, fixtures) - test/unit/ — unit tests (npm test), no API - test/integration/ — Claude API tests (npm run test:integration), not in CI - test/fixtures/ — shared event JSONs for both and assess:fixture script - Remove top-level fixtures/ and test-integration/; update vitest configs and paths Made-with: Cursor * chore: ignore auto-implement worktrees Made-with: Cursor * fix(issue-auto-implement): use Claude Code CLI only, single API key - Implement runs only Claude Code CLI (no API path); pass AUTO_IMPLEMENT_ANTHROPIC_API_KEY to CLI - Assess uses only AUTO_IMPLEMENT_ANTHROPIC_API_KEY - Action installs Claude Code CLI in CI when assess outcome is implement - README: add CI/CD checklist; docs for implement and env - AGENTS.md: implement flow and backlog updated Made-with: Cursor * fix(issue-auto-implement): create new PR when previous closed; TS push-and-open-pr - push-and-open-pr.ts: check gh pr view --json state; only skip create when OPEN - run-local-assess.ts: worktree flow, calls pushAndOpenPr, default context - load-dotenv.ts: used by run-local-assess - scripts/push-and-open-pr.sh: optional standalone script Made-with: Cursor * docs(issue-auto-implement): quick start, remove TEST_PLAN refs, add assess:local - README: add How to use (workflow, secrets, trigger label, trigger) - Remove TEST_PLAN.md references from README and AGENTS.md - package.json: add assess:local script Made-with: Cursor
1 parent 5e323d8 commit d745bfa

27 files changed

Lines changed: 4235 additions & 0 deletions
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Issue auto-implement — local development
2+
# Copy to .env and fill in secrets. Do not commit .env.
3+
4+
# Required for assess and implement. Get from https://console.anthropic.com/
5+
# Implement passes this to Claude Code CLI (claude on PATH).
6+
AUTO_IMPLEMENT_ANTHROPIC_API_KEY=
7+
8+
# Required for implement; optional for assess (redirect-to-PR, fetch comments). Run: gh auth token
9+
GITHUB_TOKEN=
10+
11+
# Required for implement. Example: hookdeck/hookdeck-cli
12+
GITHUB_REPOSITORY=
13+
14+
# Required for implement. Issue number to implement.
15+
# ISSUE_NUMBER=
16+
17+
# Optional. Repo root; default inferred from cwd when run from assess/.
18+
# GITHUB_WORKSPACE=
19+
20+
# Optional. Comma-separated paths (relative to repo root) for Claude context.
21+
# CONTEXT_FILES=AGENTS.md,REFERENCE.md
22+
23+
# Optional. Passed from assess step into implement prompt.
24+
# VERIFICATION_NOTES=
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Commit message file written by implement script (never commit)
2+
.commit_msg
3+
4+
# Local env (secrets); do not commit
5+
.env
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# AGENTS.md — Issue auto-implement action
2+
3+
For agents making changes to this action. This file summarizes flows, design decisions, and implementation details.
4+
5+
## Flows
6+
7+
### 1. Issue to first PR
8+
9+
- **Triggers:** `issues.labeled` (prefixed trigger label), `issue_comment.created` on a labeled issue when **no PR exists yet**.
10+
- **Flow:** Normalize event → assess (enough info?) → if `request_info`: post comment, add needs-info label, exit. If `implement`: implement step (push to branch `auto-implement-issue-<N>`) → verify → on fail retry (cap `max_implement_retries`); on pass create PR with "Closes #N", add pr-created label, optional comment.
11+
12+
### 2. Issue comment when PR already exists
13+
14+
- **Trigger:** `issue_comment.created` on an issue that **already has an open PR** for that issue.
15+
- **Flow:** Post a short reply on the issue directing the user to the PR; exit. No assessment or implement.
16+
17+
### 3. PR review → iteration
18+
19+
- **Triggers:** `pull_request_review.submitted`, `pull_request_review_comment.created` when the PR is from an automation branch or body contains "Closes #N".
20+
- **Flow:** Resolve issue number from PR (body "Closes #N"/"Fixes #N" or head branch `auto-implement-issue-<N>`) → assess with issue + review content → implement ("address review feedback"), push to same branch → verify → on pass: do **not** create PR; post comment on the PR summarizing the new commit(s).
21+
22+
## Event normalization
23+
24+
From the workflow event payload, derive:
25+
26+
- **Issue number:** For `issues` or `issue_comment`: `event.issue.number`. For `pull_request_review` or `pull_request_review_comment`: parse PR body for "Closes #N" or "Fixes #N", or PR head branch for `auto-implement-issue-<N>`.
27+
- **PR exists for issue (issue_comment only):** Check whether an open PR exists for that issue (e.g. head branch `auto-implement-issue-<N>` or body "Closes #<N>").
28+
29+
## Assess script
30+
31+
- **Path:** `assess/src/index.ts` (TypeScript), run with `npx tsx src/index.ts` from the assess directory (no build).
32+
- **Input:** Reads event from `GITHUB_EVENT_PATH`; optional context files from input.
33+
- **Output:** JSON with `action` (`implement` | `request_info`), `comment_body` (if request_info), `verification_notes` (optional). Written to file or GITHUB_OUTPUT.
34+
- **When triggered by PR review:** Include PR review body and review comments in the payload sent to Claude.
35+
36+
## Implement script
37+
38+
- **Path:** `assess/src/implement.ts`, run with `npx tsx src/implement.ts` from the assess directory.
39+
- **Env:** `ISSUE_NUMBER`, `GITHUB_REPOSITORY`, `GITHUB_TOKEN`, `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` (required); `VERIFICATION_NOTES`, `GITHUB_WORKSPACE`, `CONTEXT_FILES`, `IMPLEMENT_COMMIT_MSG_FILE`, `PREVIOUS_VERIFY_OUTPUT` (optional).
40+
- **Flow:** Fetches issue title/body from GitHub API, loads context files, then runs **Claude Code CLI** (`claude` on PATH) in the repo root with a prompt; the script passes `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` to the CLI as `ANTHROPIC_API_KEY`. The CLI implements in-repo (Read/Edit/Bash), then the script ensures commit/PR meta files exist (`.commit_msg`, `.pr_title`, `.pr_body` under the action dir). When `PREVIOUS_VERIFY_OUTPUT` is set (e.g. after a failed verify run), it is included in the prompt so the CLI can fix the implementation. In CI, the action installs the CLI (`npm install -g @anthropic-ai/claude-code`) before the implement step when the assess outcome is `implement`.
41+
42+
## Implement–verify loop
43+
44+
- **Single step** `implement_verify_loop`: for each attempt from 1 to `max_implement_retries`, run implement (with `PREVIOUS_VERIFY_OUTPUT` from the previous failure, if any), commit and push, then run `verify_commands`. If verify passes, exit success. If it fails, set the verify output as `PREVIOUS_VERIFY_OUTPUT` and retry. After all attempts, fail. When this step succeeds: if trigger was `pull_request_review` or `pull_request_review_comment`, post a comment on the existing PR (no new PR); otherwise create PR.
45+
46+
## Branch and PR
47+
48+
- Branch name: `auto-implement-issue-<issue_number>`.
49+
- PR title or body must include "Closes #N" (or "Fixes #N") so merging auto-closes the issue.
50+
- On iteration (PR already exists): do not create a new PR; post a comment on the PR summarizing the new commit(s).
51+
52+
## Restricting who can trigger
53+
54+
Only members of the `github_allowed_trigger_team` (input; set via repo variable `AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`) may trigger the flow. First step checks `github.actor` against that team; if the variable is unset or the actor is not a member, fail immediately. Token must have `read:org`.
55+
56+
## Labels
57+
58+
All automation labels use `label_prefix` (default `automation`): `{prefix}/auto-implement`, `{prefix}/needs-info`, `{prefix}/pr-created`. Create via API if missing.
59+
60+
## Local development
61+
62+
Scripts load a `.env` file from the action root or cwd (see README **Local runs**). Key env: `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`, `GITHUB_TOKEN`, `GITHUB_REPOSITORY`, `ISSUE_NUMBER` (implement). Copy `.env.example` to `.env` and fill; optional `./scripts/setup-local-env.sh --with-gh` to set `GITHUB_TOKEN` from `gh auth token`.
63+
64+
## Verification
65+
66+
When changing this action or the assess script:
67+
68+
1. **Run the assess unit tests locally** before committing: `cd .github/actions/issue-auto-implement/assess && npm ci && npm test`. Do not rely on CI alone—catch failures locally first, then push.
69+
2. **CI** runs the same tests in `.github/workflows/issue-auto-implement-test.yml` when you push or open a PR that touches `.github/actions/issue-auto-implement/**`.
70+
3. **Optional:** Run the assess script with a fixture and `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` for end-to-end assessment behavior.
71+
4. **Full workflow:** Trigger manually on a test issue (trigger label or comment). Ensure repo secrets/variables are set. Inspect the Actions run and the issue/PR; re-run after changes to the implement or verify loop.
72+
73+
## Next steps (implementation backlog)
74+
75+
Possible future improvements:
76+
77+
1. **Fetch all issue comments** — For `issues` and `issue_comment` events, optionally call the GitHub API to list all comments on the issue and include them in the assessment payload (not only the single comment from the event).
78+
2. **Optional comment when PR is created** — Input `post_pr_comment` exists; when true, post a short comment on the issue linking to the new PR when one is created.
79+
3. **Local run with fixture and Claude**`npm run assess:fixture` exists; optional end-to-end testing with real `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`.
80+
81+
Done: context files in assess, implement step (Claude Code CLI), implement–verify loop with re-implement on failure, PR review iteration (comment on PR, no new PR), comment when retries exhausted, secrets/variables and README docs, local assess script.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Issue auto-implement action
2+
3+
Reusable composite action for label-triggered issue automation: assess (request more info or implement), implement-verify loop, then create PR or iterate on an existing PR after review.
4+
5+
## How to use (quick start)
6+
7+
1. **Workflow** — Ensure `.github/workflows/issue-auto-implement.yml` exists and calls this action (see the workflow in this repo for the exact `on:` and `uses:`).
8+
2. **Secrets and variable** — In the repo: Settings → Secrets and variables → Actions. Add secret **`AUTO_IMPLEMENT_ANTHROPIC_API_KEY`** (Anthropic API key). Add variable **`AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`** (e.g. `your-org/your-team`); only members of this team can trigger the action.
9+
3. **Trigger label** — Create a label **`automation/auto-implement`** (or `{your-prefix}/auto-implement` if you set `label_prefix`) in the repo so you can add it to issues. The action will create the other labels (`needs-info`, `pr-created`) when it runs.
10+
4. **Trigger** — On an issue, add the label `automation/auto-implement`. The workflow runs: it assesses the issue (request more info vs implement), and if implement, runs the Claude Code CLI and opens a PR. You can also comment on the issue (to add context and re-trigger) or review the PR (to iterate).
11+
12+
## Usage (reference)
13+
14+
Used by `.github/workflows/issue-auto-implement.yml`. Requires `anthropic_api_key` (e.g. from repo secret `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`), `github_allowed_trigger_team` (e.g. from repo variable `AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`), and `github_token` from the workflow.
15+
16+
## Inputs
17+
18+
| Input | Required | Default | Description |
19+
|-------|----------|---------|-------------|
20+
| `anthropic_api_key` | Yes | - | Claude API key. Set via repo secret `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` so multiple actions can use different keys. |
21+
| `github_token` | Yes | - | Token with contents, issues, pull-requests, read:org |
22+
| `context_files` | No | AGENTS.md,REFERENCE.md | Comma-separated paths for assessment context |
23+
| `assessment_reference_issue` | No | 192 | Reference issue number for "enough information" |
24+
| `label_prefix` | No | automation | Prefix for labels (e.g. automation/auto-implement) |
25+
| `verify_commands` | No | go test ./... | Commands run for verification |
26+
| `max_implement_retries` | No | 3 | Max retries on verify failure (cap 5) |
27+
| `github_allowed_trigger_team` | Yes | - | GitHub Team slug (e.g. org/team); only members can trigger. Set via repo variable `AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`. |
28+
| `post_pr_comment` | No | false | When true, post a comment on the issue linking to the new PR when one is created. |
29+
30+
Secrets and variables use an action-specific prefix (e.g. `AUTO_IMPLEMENT_`) so each action can have its own keys/variables and it's clear which workflow uses which. This also avoids clashing with platform-reserved names (e.g. `GITHUB_*`).
31+
32+
## CI/CD: what you need to run this workflow
33+
34+
To use this action in GitHub Actions:
35+
36+
1. **Workflow** — Call the action from a workflow (e.g. `.github/workflows/issue-auto-implement.yml`) on `issues.labeled`, `issue_comment`, `pull_request_review`, and/or `pull_request_review_comment`. The job needs `contents: write`, `issues: write`, `pull-requests: write`.
37+
2. **Secrets** — Add **`AUTO_IMPLEMENT_ANTHROPIC_API_KEY`** (repo secret). Used for the assess step and passed to the Claude Code CLI in the implement step.
38+
3. **Variables** — Add **`AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`** (repo variable, required): GitHub Team slug (e.g. `org/team-name`) whose members may trigger the run.
39+
4. **Token** — Pass `github_token` (e.g. `secrets.GITHUB_TOKEN`) to the action. The team check needs `read:org`; if `GITHUB_TOKEN` lacks it, use a PAT with `read:org` and pass it as the token.
40+
5. **Implement in CI** — The action installs the Claude Code CLI (`@anthropic-ai/claude-code`) when the assess outcome is `implement`, so the workflow does not need to install it. Implement runs in the repo with Read/Edit/Bash; the CLI uses `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`.
41+
42+
No other setup is required. Optionally set `verify_commands` (default `go test ./...`) and `context_files` (default `AGENTS.md,REFERENCE.md`) to match your repo.
43+
44+
## Secrets and variables (repo setup)
45+
46+
- **`AUTO_IMPLEMENT_ANTHROPIC_API_KEY`** (repo secret) — Claude API key for the assess and implement steps. Add under Settings → Secrets and variables → Actions.
47+
- **`AUTO_IMPLEMENT_ALLOWED_TRIGGER_TEAM`** (repo variable, required) — GitHub Team slug (e.g. `org/team-name`) whose members may trigger the workflow. Add under Settings → Secrets and variables → Actions. The first step checks `github.actor` against this team; if unset or not a member, the run fails.
48+
- **Token for team check** — The workflow passes `github_token` (usually `secrets.GITHUB_TOKEN`) to the action. The team check needs `read:org`. If your default `GITHUB_TOKEN` does not have `read:org`, use a PAT with that scope and pass it as the token (e.g. a repo secret) instead.
49+
50+
## Triggers
51+
52+
- **issues.labeled** — prefixed trigger label (e.g. `automation/auto-implement`)
53+
- **issue_comment.created** — on an issue with that label (redirect to PR if PR exists)
54+
- **pull_request_review.submitted** / **pull_request_review_comment.created** — PR from automation branch or with "Closes #N"
55+
56+
## Labels
57+
58+
The action ensures these labels exist (creates them if missing): `{prefix}/auto-implement`, `{prefix}/needs-info`, `{prefix}/pr-created`.
59+
60+
## Testing
61+
62+
From the repo root, run the assess script tests:
63+
64+
```bash
65+
cd .github/actions/issue-auto-implement/assess && npm ci && npm test
66+
```
67+
68+
CI runs these in `.github/workflows/issue-auto-implement-test.yml` when you push or open a PR that touches this action.
69+
70+
**Integration tests (Claude API):** Tests in `assess/test/integration/` call the real Anthropic API. They do not run with `npm test`. From the assess directory, run `npm run test:integration` (requires `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` in `.env` or env). Unit tests live in `assess/test/unit/`; shared fixtures in `assess/test/fixtures/`. You can add integration tests to CI later with the secret configured.
71+
72+
## Local runs (Claude)
73+
74+
Scripts load a **local `.env`** file so you don't have to pass secrets on the command line. They look for `.env` in (1) the action root (`.github/actions/issue-auto-implement/.env`) and (2) the current working directory (e.g. `assess/.env`). Later overrides earlier; shell env still wins.
75+
76+
### Env vars (local)
77+
78+
| Variable | Required for | How to get it |
79+
|----------|--------------|----------------|
80+
| `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` | Assess, Implement | [Anthropic console](https://console.anthropic.com/) → API keys. Assess uses it directly; implement passes it to Claude Code CLI (`claude` on PATH). |
81+
| `GITHUB_TOKEN` | Implement; optional for Assess | `gh auth token`, or a PAT with `repo`, `read:org`. |
82+
| `GITHUB_REPOSITORY` | Implement | `owner/repo` (e.g. `hookdeck/hookdeck-cli`). |
83+
| `ISSUE_NUMBER` | Implement | The issue number to implement. |
84+
| `GITHUB_EVENT_PATH` | Assess (when not using fixture) | Path to event JSON; for fixture: `./fixtures/issue-labeled.json`. |
85+
| `GITHUB_EVENT_NAME` | Assess | e.g. `issues` or `issue_comment`. |
86+
| `GITHUB_WORKSPACE` | Optional | Repo root; default inferred from cwd when run from `assess/`. |
87+
| `CONTEXT_FILES` | Optional | Comma-separated paths (relative to repo root) for Claude context. |
88+
| `VERIFICATION_NOTES` | Optional (Implement) | Notes from assess step. |
89+
| `PREVIOUS_VERIFY_OUTPUT` | Optional (Implement retries) | Previous verify failure output. |
90+
91+
### One-time setup: `.env`
92+
93+
1. From the action root: `cp .env.example .env`
94+
2. Edit `.env` and set at least `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` and (for implement) `GITHUB_TOKEN`. Optionally run `./scripts/setup-local-env.sh --with-gh` to fill `GITHUB_TOKEN` from `gh auth token`; use `--template-only` to only create `.env` from `.env.example`.
95+
96+
### Assess (issue → implement vs request_info)
97+
98+
Uses a fixture as the GitHub event. Claude decides whether to `implement` or `request_info`; output is JSON to stdout.
99+
100+
```bash
101+
cd .github/actions/issue-auto-implement/assess
102+
npm run assess:fixture
103+
```
104+
105+
With `.env` in place, no need to pass the key on the command line. Optional: set `GITHUB_TOKEN` and `GITHUB_REPOSITORY` to exercise redirect-to-PR and fetch-comments. Set `ASSESS_DEBUG=1` to log the prompt sent to Claude and the raw response to stderr. Other fixtures: `GITHUB_EVENT_PATH=./test/fixtures/issue-comment.json GITHUB_EVENT_NAME=issue_comment npx tsx src/index.ts`.
106+
107+
### Implement (issue → Claude Code CLI → files on disk)
108+
109+
Fetches the issue from the GitHub API, then runs **Claude Code CLI** in the repo (`claude` on PATH with Read/Edit/Bash). The CLI implements the issue in-repo and writes commit/PR meta files. Use a branch you can discard or reset. Requires Claude Code CLI installed and `AUTO_IMPLEMENT_ANTHROPIC_API_KEY` set (passed to the CLI).
110+
111+
```bash
112+
cd .github/actions/issue-auto-implement/assess
113+
npm run implement:issue
114+
```
115+
116+
With `.env` set (e.g. `ISSUE_NUMBER`, `GITHUB_REPOSITORY`, `GITHUB_TOKEN`, `AUTO_IMPLEMENT_ANTHROPIC_API_KEY`), no need to pass them inline. Override any var on the command line if needed (e.g. `ISSUE_NUMBER=42 npm run implement:issue`). Then from the repo root inspect `git status` and the commit message at `.github/actions/issue-auto-implement/.commit_msg`. Optionally set `VERIFICATION_NOTES` and `CONTEXT_FILES`.
117+
118+
For implementation details and verification steps, see `AGENTS.md`.
119+
120+
### Local run against a real issue (no workflow events)
121+
122+
To test the full flow locally against a real GitHub issue and create a PR, use the **local assess** script (fetches the issue from the API and runs the same assess logic). With **APPLY=1** the script applies the outcome: posts the request-for-more-info or redirect comment on the issue, or runs implement and push (creates/updates the PR). When the outcome is implement, the script creates or reuses a **worktree** at `.worktrees/auto-implement-issue-<N>` so your current branch is left untouched; implement runs there, then commit/push/PR is done in TypeScript (`assess/src/push-and-open-pr.ts`). The workflow does not need to run; you trigger each step locally and optionally pass **COMMENT_BODY** (after you add a comment on the issue) or **REVIEW_BODY** (after you review the PR).

0 commit comments

Comments
 (0)