Skip to content
Open
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
28 changes: 26 additions & 2 deletions skills/github-repo-monitor/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ On every subsequent run:
- When a conversation goes idle/finished/error the agent's final response
is posted back as a GitHub comment.

> **Local mode only.** This automation targets the local OpenHands setup
> (`dev:automation` stack). A cloud/webhook variant is out of scope here.
> **Cron polling vs. event triggers:** This skill uses cron polling and works in
> any deployment. If `RUNTIME_URL` is set and does not contain `localhost` or
> `127.0.0.1`, the environment can receive GitHub webhook events directly — prefer
> an event-triggered automation (see the `openhands-automation` skill) rather than
> polling. Use this skill only when `RUNTIME_URL` is unset, empty, or local.

---

Expand Down Expand Up @@ -69,6 +72,25 @@ function without GitHub credentials.

Follow these steps in order.

### Step 0 - Check deployment environment

Check whether the environment can receive GitHub webhook events:

```bash
echo "RUNTIME_URL=${RUNTIME_URL}"
```

- If `RUNTIME_URL` is **set and does not contain `localhost` or `127.0.0.1`** →
tell the user:
*"Your environment has a reachable `RUNTIME_URL` (`$RUNTIME_URL`), so GitHub can
deliver events directly. An event-triggered automation (e.g. `pull_request.opened`
or `issue_comment.created`) using the `openhands-automation` skill would be more
immediate and efficient than cron polling. Continue with this skill only if you
specifically want polling."*
If the user confirms they want polling anyway, continue to Step 1.
- If `RUNTIME_URL` is **unset, empty, or contains `localhost`/`127.0.0.1`** →
proceed directly to Step 1.

### Step 1 - Verify GITHUB_TOKEN

Fetch the secret and run the `curl` check above.
Expand Down Expand Up @@ -303,3 +325,5 @@ Each cron run executes `main.py`, which:
| Same comment processed twice | `processed_comment_ids` cleared | State file was deleted; harmless but duplicate comment may appear |
| Summary never posted | Conversation stuck in `running` | Open the conversation in the OpenHands UI; agent may need input |
| No events detected after first run | `last_poll` in the future | Delete the state file to reset; it will be recreated on next run |
| `Callback error (non-fatal): HTTP Error 409: Conflict` in run logs | Automation service auto-marks the run complete on process exit; explicit `fire_callback("COMPLETED")` at script end then conflicts | Fixed in `scripts/main.py` ≥ this version — the 409 is now caught and ignored silently |
| Automation stops firing after updating it via PATCH | PATCH resets `enabled` to `false` | Follow every PATCH with `{"enabled": true}` to re-activate |
4 changes: 4 additions & 0 deletions skills/github-repo-monitor/scripts/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ def fire_callback(status: str = "COMPLETED", error: str | None = None) -> None:
)
try:
urllib.request.urlopen(req)
except urllib.error.HTTPError as exc:
if exc.code == 409:
return # Run already marked complete by the automation service — ignore.
print(f"Callback error (non-fatal): {exc}")
except Exception as exc:
print(f"Callback error (non-fatal): {exc}")

Expand Down
Loading