Monitor OneKey PR checks and review threads, fix failures, address comments, and continue until the PR is ready.
61
72%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./.skillshare/skills/1k-monitor-pr-ci/SKILL.mdMonitor a pull request's CI checks and review comments. Auto-fix CI failures, address inline review comments, reply to reviewers, and resolve threads.
For a one-shot, low-context PR status summary, use:
yarn agent:check --profile ci --pr <PR_NUMBER>For monitor automation, prefer the stable machine-readable contract:
yarn agent:check --profile ci --pr <PR_NUMBER> --json-file /tmp/agent-check.jsonRead /tmp/agent-check.json instead of parsing terminal text. The report has
schemaVersion: 1, top-level status / exitCode / failureReasons, and
stable nested objects for remote.pr, remote.checks, and remote.review.
To reply to and resolve a specific review thread without starting the monitor:
yarn agent:review-thread --pr <PR_NUMBER> --list
yarn agent:review-thread --pr <PR_NUMBER> --thread <THREAD_ID> --reply-file <FILE>Use the GraphQL thread id from --list or
remote.review.threads.unresolvedItems[].id; numeric indexes are only for
--dry-run validation.
Use this monitor workflow only when the user wants polling, automatic fixes, or batch review-thread handling.
/1k-monitor-pr-ci https://github.com/OneKeyHQ/app-monorepo/pull/10717 3m
/1k-monitor-pr-ci 10717 5m
/1k-monitor-pr-ci https://github.com/OneKeyHQ/app-monorepo/pull/10717
/1k-monitor-pr-ci 10717
/1k-monitor-pr-ci$ARGUMENTS — Two parts, space-separated:
6m): e.g. 30s, 1m, 2m, 3分钟, 5min, 6mIf $ARGUMENTS is empty, auto-detect PR from current branch and use default 6m interval.
Parse arguments: Split $ARGUMENTS into PR identifier and polling interval.
https://github.com/{owner}/{repo}/pull/{number}s/sec/秒, m/min/分钟/分. Default: 6m$ARGUMENTS is empty, detect PR from current branch:
gh pr list --head "$(git branch --show-current)" --json number --jq '.[0].number'Resolve owner/repo:
gh repo view --json owner,name --jq '"\(.owner.login)/\(.name)"'Confirm and start (no further questions needed):
Monitoring PR #10717 (OneKeyHQ/app-monorepo)
Polling interval: 3m
Starting...Each iteration ([Check N/30]):
Use agent:check as the single read path. It fetches CI checks, PR metadata,
inline comments, and GraphQL review-thread state, then writes a stable
schemaVersion: 1 JSON report.
AGENT_CHECK_JSON="$(mktemp -t agent-check.XXXXXX.json)"
yarn agent:check --profile ci --pr <PR_NUMBER> --json-file "$AGENT_CHECK_JSON" || trueDo not treat a non-zero agent:check exit code as a command failure by itself.
For monitor purposes, non-zero means the JSON contains actionable state such as
pending CI, failed CI, unresolved review threads, draft PR, blocked merge state,
or truncated review data.
Read these fields from the JSON report:
status, exitCode, failureReasonsremote.pr.{number,url,state,reviewDecision,mergeStateStatus,isDraft}remote.checks.counts, remote.checks.failed, remote.checks.pending, remote.checks.gateFailedremote.review.threads.{unresolved,activeUnresolved,dataComplete,unresolvedItems}remote.review.changesRequestedByFallback: If agent:check is unavailable or returns an unsupported
schemaVersion, use raw gh queries for the same four signals. GraphQL remains
required for thread IDs and resolution state. If GraphQL fails, fall back to the
REST API for inline comments:
gh api repos/{owner}/{repo}/pulls/{pr_number}/comments \
--jq '.[] | {id: .id, body: .body, path: .path, line: .original_line, user: .user.login, in_reply_to_id: .in_reply_to_id, created_at: .created_at}'Note: REST fallback can fetch comments and reply to them, but cannot resolve threads (GitHub only supports this via GraphQL). When using REST fallback, skip the resolve step (Step 3d) and log a warning that threads must be resolved manually.
Filter to only unresolved threads (isResolved: false). Skip threads where the last comment is from the current gh user (already replied).
[Check 3/30]
CI Status:
| Check | Status | Duration |
|------------------|---------|----------|
| lint (24.x) | pass | 5m34s |
| unittest (24.x) | pending | - |
Unresolved threads: 3
- src/views/Example.tsx:42 (@reviewer): "Consider using useCallback here"
- src/utils/format.ts:15 (@reviewer): "This should handle null case"
- src/components/Card.tsx:88 (@reviewer): "Typo in variable name"Before choosing an action, classify the agent:check JSON into three buckets:
remote.checks.failedremote.checks.gateFailedremote.checks.pendingIf release-ready-merge-gate is failing, treat it as an expected merge blocker rather than a CI failure to auto-fix.
| CI Status | Unresolved Threads | Action |
|---|---|---|
| Normal failed checks | - | Auto-fix CI failure (Step 2) |
| Gate failure | Has threads | Address threads (Step 3), then report blocked by missing release-ready |
| Gate failure | No threads | Stop waiting and report blocked by missing release-ready |
| Any pending | Has threads | Address threads (Step 3), keep waiting for CI |
| Any pending | No threads | Wait, re-check |
| All pass | Has threads | Address threads (Step 3) |
| All pass | No threads | Done (Step 4) |
For each failed check:
Identify the actionable failed check from the latest poll result.
remote.checks.failed output, not stale output from a previous iteration.name and link.lint (24.x) may fail first on formatting, then fail again on package-version consistency. If the same check name fails again after a push, treat it as a new Step 2 item and continue fixing until no normal failed checks remain.Derive RUN_ID from the failed check link.
https://github.com/{owner}/{repo}/actions/runs/<RUN_ID>/job/<JOB_ID>https://github.com/{owner}/{repo}/runs/<RUN_ID><RUN_ID> from the URL and use that exact run when fetching logs.Get failure log:
gh run view <RUN_ID> --log-failed 2>&1 | tail -100Analyze the failure and determine the cause.
Fixable (lint error, type error, test failure from our changes):
fix: resolve CI <check-name> failurePotentially unrelated or pre-existing (repo-wide package/version consistency failure, failure in files untouched by the PR, or issue that appears to predate the PR):
origin/x or inspect whether the failing condition already exists outside the PR diff.Not fixable (infra issue, flaky test, unrelated failure the user does not want fixed here):
For each unresolved thread:
Read the comment body and the relevant code context. Categorize:
Display a one-line log per thread of what will be done, then proceed to fix immediately. Do NOT wait for user confirmation — only pause for disagree/won't-fix cases.
For each thread that needs a code fix:
Reply explaining what was done, using the REST API:
gh api --method POST \
repos/{owner}/{repo}/pulls/{pr_number}/comments/{comment_database_id}/replies \
-f body='Fixed: [concise explanation of the change]'For questions (no code change needed):
gh api --method POST \
repos/{owner}/{repo}/pulls/{pr_number}/comments/{comment_database_id}/replies \
-f body='[answer to the question]'Keep replies concise. Explain what was changed and why.
After replying, resolve the thread via GraphQL:
gh api graphql -f query='
mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread {
isResolved
}
}
}' -f threadId="THREAD_NODE_ID"Note: Resolve thread requires GraphQL — there is no REST API equivalent. If Step 1b fell back to REST, skip this step and log a warning: "Thread resolve skipped (GraphQL unavailable). Please resolve manually."
After all threads are addressed in this iteration:
git add <specific files>git commit -m "fix: address PR review feedback
- [list each fix made]"git pushAfter pushing fixes, request re-review from the reviewers who left comments:
Get reviewers who left the comments (collected from Step 1b thread data, author.login fields)
Request re-review:
gh pr edit <PR_NUMBER> --add-reviewer <reviewer1>,<reviewer2>Or via API if --add-reviewer doesn't trigger re-review:
gh api --method POST \
repos/{owner}/{repo}/pulls/{pr_number}/requested_reviewers \
-f 'reviewers[]=reviewer1' -f 'reviewers[]=reviewer2'Return to Step 1 (wait for CI to re-run)
If the only remaining failed check is release-ready-merge-gate, stop the polling loop and report:
CI is complete, but merge is blocked by the release-ready gate.
Blocking check:
- release-ready-merge-gate: expected failure until the PR gets the `release-ready` label
Action:
- Add the `release-ready` label to the PR, then run the monitor again if neededDo not:
When all normal CI checks pass and no unresolved threads remain:
All normal CI checks passed. All review threads resolved.
CI:
| Check | Status | Duration |
|------------------|--------|----------|
| lint (24.x) | pass | 5m34s |
| unittest (24.x) | pass | 4m42s |
Review threads: 5 resolved, 0 remaining
PR: <URL>
Status: Ready for re-review / Ready to mergeIf release-ready-merge-gate is still failing, do not use this final report. Use the blocked-state report from Step 3g instead.
[Check N/30]gh run rerun)gh CLI is not authenticatedgh pr view <PR_NUMBER> --json state --jq '.state' each iteration — if CLOSED or MERGED, stop and inform the user)d71e6b7
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.