Skip to content

feat(review-skill): add Gogs support to /review handler#2

Draft
troglodyne-bot wants to merge 27 commits into
trogbot_live_codefrom
koan/gogs-review-skill
Draft

feat(review-skill): add Gogs support to /review handler#2
troglodyne-bot wants to merge 27 commits into
trogbot_live_codefrom
koan/gogs-review-skill

Conversation

@troglodyne-bot

Copy link
Copy Markdown
Owner

What

Adds Gogs support to the /review skill so self-hosted Gogs PRs and issues can be queued for review.

Why

The /pr skill already has Gogs support (PR #1). This brings /review to parity — users running Gogs instances can now queue review missions with Gogs URLs the same way they do with GitHub.

How

The routing in handle() now checks:

  1. Bare Gogs repo URL → _handle_gogs_batch (list all open PRs, queue each)
  2. Bare GitHub repo URL → existing _handle_batch
  3. Gogs PR/issue URL → _handle_gogs_single (resolve project, queue one mission)
  4. GitHub PR/issue URL → existing handle_github_skill

Detection is safe: _parse_gogs_repo_url and _try_extract_gogs_pr_or_issue both return None when KOAN_GOGS_HOST is unconfigured, so the GitHub paths are unaffected when Gogs isn't set up.

_list_gogs_open_prs fetches via GogsForge._api (urllib, no gh CLI), normalising the response to the same {number, title, url} shape used by the GitHub path.

Testing

  • 30 tests in test_review_handler.py (all passing): routing tests for new Gogs paths, unit tests for _parse_gogs_repo_url, _try_extract_gogs_pr_or_issue, _list_gogs_open_prs, _handle_gogs_single, and _handle_gogs_batch
  • All pre-existing tests continue to pass (full suite exit 0)

troglodyne and others added 27 commits June 4, 2026 10:21
check_config() hardcoded a KOAN_TELEGRAM_TOKEN/CHAT_ID presence check
that exited non-telegram setups (Slack, Matrix) before the messaging-
provider abstraction ran. Gate the check to
_resolve_provider_name() == "telegram" so each provider's own
configure() does the real credential check.

Also:
- Guard the BOT_TOKEN / CHAT_ID startup log lines to skip on empty
  values (avoids slicing an empty BOT_TOKEN and logging an empty chat).
- Main-loop chat-id filter now matches against both the active
  provider's get_channel_id() and CHAT_ID (telegram-only), letting
  slack/matrix events through while preserving backward-compat with
  tests that patch CHAT_ID directly.

Extracted from WIP commit 14598ab.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bridge banner

The Matrix HTTP fallback returned raw Matrix events as Update.raw_data,
but awake.py's main loop expects Telegram-Bot-API-shaped dicts
(update_id, message.chat.id, …). Sending any message to a room crashed
the bridge with KeyError: 'update_id'. Mint the wrapper in
_parse_room_events.

Also unhardcode the bridge banner provider name; it was stuck on
"telegram" regardless of which provider was actually active.

Extracted from WIP commit 247fc58.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds GogsForge — a ForgeProvider implementation for self-hosted Gogs
(gogs.io) instances, plus a gh-compatible scripts/gogs CLI wrapper for
human use. Configuration is via KOAN_GOGS_HOST and KOAN_GOGS_TOKEN.

- koan/app/gogs_auth.py: env-var helpers (host, token, headers)
- koan/app/gogs_url_parser.py: URL parsing with runtime host pattern
- koan/app/forge/gogs.py: GogsForge (PR create/view/list, issue create,
  API passthrough, fork detection, URL construction)
- scripts/gogs: standalone gh-compatible CLI wrapper using Gogs REST API v1
- forge/registry.py + forge/__init__.py: register gogs, auto-detect by host
- env.example: document KOAN_GOGS_HOST and KOAN_GOGS_TOKEN
- 58 new tests covering auth, URL parsing, forge ops, registry, factory

Also fixes a pre-existing bug in forge/__init__.py where _resolve_forge_config
called the non-existent app.utils.get_koan_root — replaced with os.environ.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Some things needed to be moved around for clarity as to what they
were relevant to.
See _resolve_forge_config in __init.py, it does the same.
There was a TODO comment that this "ought" to happen in the event
that we implement phase two, and it does not appear as though
this will break anything, so we do it.
This way we can't have github.com.nefarious.org match, for example

This is still possible in the case of github.enterprise.nefarious.org,
but I presume this is an intentional use case.
This reverts commit 2ba4dcd.

Apparently this *does* break things.  Feels like a 'load bearing'
bug though.
This follows the pattern established earlier therein.
In Forges we want to prevent github.com.nefarious, but not good.github.com
This way we can see public repos at least.
Nothing else in the project refers to it ever, so you shouldn't use it
At least not until every other place we use github_url in the project
gets similar treatment.
We're able to clone, but not yet fork or discern if we have push perms
I've left TODOS in those places
Extends the gogs CLI wrapper with two new subcommands:

- `gogs repo permissions [--repo OWNER/REPO] [--json FIELDS] [--jq FILTER]`
  Fetches the token's permission level on a repo (admin/push/pull booleans),
  mirroring the `permissions` object from the Gogs API. Defaults to false
  for any field absent from the API response.

- `gogs repo fork [--repo OWNER/REPO] [--org ORGANIZATION]`
  Creates a fork of the given repo via POST /repos/{owner}/{repo}/forks.
  Optionally forks into an organisation. Returns the fork's HTML URL.

Also:
- Fixes pre-existing test bug: test_issue_create_raises_not_implemented now
  correctly expects RuntimeError (the implementation changed on this branch)
- Fixes pre-existing ruff F541 lint error in add_project/handler.py
- Adds 7 new tests covering the two new commands (permissions JSON output,
  defaults, jq filter, field projection; fork URL, org payload, fallback URL)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Detect bare Gogs repo URLs via _parse_gogs_repo_url (for batch mode)
- Detect Gogs PR/issue URLs via _try_extract_gogs_pr_or_issue
- _handle_gogs_single: queue /review mission for a Gogs PR or issue
- _handle_gogs_batch: list open PRs via GogsForge API, queue each
- _list_gogs_open_prs: fetch open PRs from Gogs API, normalise to
  {number, title, url} shape matching the GitHub equivalent
- Routing in handle() tries Gogs batch → GitHub batch → Gogs single
  → GitHub single; Gogs paths are tried iff KOAN_GOGS_HOST is set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants