Skip to content

feat(integrations): open a GitHub issue when a ticket is created - #31

Open
YJack0000 wants to merge 2 commits into
developfrom
feat/github-ticket-integration
Open

feat(integrations): open a GitHub issue when a ticket is created#31
YJack0000 wants to merge 2 commits into
developfrom
feat/github-ticket-integration

Conversation

@YJack0000

Copy link
Copy Markdown

Hands support cases over to engineering automatically. Once the GitHub integration is connected on an account, every ticket that gets created opens an issue in the configured repository, carrying the contact, ticket type, due date, a link back to the conversation and the customer's first message. The issue link is written back to the conversation as a private note so agents see where the case went. This replaces the standalone support-app → GitHub Issue form: the inbox becomes the single entry point, and GitHub is one integration among the ones an account can turn on.

Closes

Part of the support consolidation into Pathors Inbox (proposal: https://claude.ai/code/artifact/0e4242ef-d418-40ff-9bf5-bb37165d9f75). Board ticket to be linked.

How to test

  1. Settings → Integrations → GitHub → Connect. Fill in a personal access token that can create issues, the repository as owner/repo, and optionally a label.
  2. Open any conversation and create a ticket from the Ticket panel.
  3. Within a few seconds the repository has a new issue titled with the ticket subject; the body lists the contact, ticket type, due date (if set), a link to the conversation, and the customer's first message.
  4. The conversation shows a private note with the issue URL.
  5. Trigger the event again for the same conversation: no second issue is opened (the conversation already carries additional_attributes.github_issue).
  6. Disable the hook: new tickets no longer open issues. Enter a wrong token: the ticket is still created, the failure is logged, nothing is raised.

What changed

  • config/integration/apps.yml: new github app (account hook, single instance). Settings: access_token (required), repository (required, owner/repo pattern), label (optional). Only repository and label are returned to the frontend. The generic integration page renders the form from the schema, so no frontend code.
  • HookListener#ticket_created routes ticket.created to account hooks; HookJob dispatches github to Integrations::Github::ProcessorService.
  • Integrations::Github::ProcessorService: POSTs to the GitHub REST issues endpoint, writes {url, number, repository} into the conversation's additional_attributes.github_issue, creates the private note. Idempotent on that attribute; failures are logged, not raised.
  • en + zh_TW locale entries for the app card, the issue body labels and the private note.
  • Official GitHub mark as the integration logo (light + dark variants, 512×512 like the other cards).
  • Specs: processor service (WebMock: success, skip when already linked, 4xx logged) and hook listener routing (enabled vs disabled hook).

Note: the PAT lives in the hook's settings jsonb, same as the OpenAI integration's api_key. It is kept off the API via visible_properties but is not encrypted at rest. No migration.

Registers a `github` account-level integration. When a ticket is created,
HookListener#ticket_created enqueues HookJob, which hands the event to
Integrations::Github::ProcessorService. The service POSTs to the GitHub
REST issues API with the ticket subject as the title and a markdown body
carrying the contact, ticket type, due date, a link back to the
conversation and the first incoming message.

On success the issue url, number and repository are stored on the
conversation's additional_attributes and a private note with the issue
link is posted so agents see it in the thread; that same attribute makes
a retried job a no-op. A rejected request is logged and dropped.

Settings: access_token (GitHub PAT), repository (owner/repo) and an
optional label applied to every issue. Only repository and label are
returned to the frontend.
@YJack0000

Copy link
Copy Markdown
Author

Follow-up commit 8a91b89: the Personal Access Token field is now a password input (was plain text). Verified on a local preview that the generic hook form renders it masked and the schema/API contract is unchanged.

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.

2 participants