Skip to content

Integrations: GitHub Issues thread-action target (create a linked GitHub issue from a thread) - #50

Merged
MateuszPaulski merged 3 commits into
mainfrom
agent/issue-48
Jul 3, 2026
Merged

Integrations: GitHub Issues thread-action target (create a linked GitHub issue from a thread)#50
MateuszPaulski merged 3 commits into
mainfrom
agent/issue-48

Conversation

@MateuszPaulski

Copy link
Copy Markdown
Collaborator

Summary

Adds a second thread-action target — GitHub Issues — as a new publishable package @airnauts/airside-extension-github, structurally mirroring @airnauts/airside-extension-jira. Clicking "Create GitHub issue" on a thread opens a linked GitHub issue and pins the externalLink back onto the thread (rendered by existing client code). No server or core change — it reuses the ServerExtension / ThreadActionExtension seam and upsertExternalLink persistence (ADR-0034 anticipated this).

Closes #48.

How it maps to the approved spec

  • Package packages/integration-github/@airnauts/airside-extension-github, public factory githubExtension(opts). One thread-action (id:'github.createIssue', provider:'github', slot thread-toolbar, presentation:{style:'primary'}), visibleWhen hides it once a github link exists, run returns { externalLink }.
  • src/client.tsGitHubConfig / createGitHubClientPOST {baseUrl}/repos/{owner}/{repo}/issues via native fetch (no @octokit/*). Headers: authorization: Bearer <token>, accept: application/vnd.github+json, x-github-api-version: 2022-11-28, content-type: application/json. 5s AbortSignal.timeout. Non-2xx and network/abort → IntegrationError('github'); the token never appears in any error message. Maps externalId=String(issue.id), key="#"+number, url=html_url.
  • src/markdown.ts — local buildIssueTitle + buildMarkdownDescription (Markdown analog of Jira's ADF; kept local per spec, not a shared package — that's Integrations: Linear thread-action target (create a linked Linear issue from a thread) #47's work).
  • src/create-issue.ts / src/index.tsrun handler + factory; validates token/owner/repo at construction. externalLink = { provider:'github', externalId, key, label:"GitHub "+key, url, createdAt }.
  • Meta mirrored from Jira (MIT, publishConfig.access:public, type:module, exports→dist, workspace:^ deps, initial version:0.9.1, tsup/tsconfig/README/LICENSE).
  • .changeset/config.json — added to the fixed group; one minor changeset (0.9.1 → 0.10.0 in lockstep).
  • Host wiring — env-gated block in examples/nextjs-host/.../route.ts (AIRSIDE_GITHUB_TOKEN/_OWNER/_REPO) + dep added to the host's package.json.

ADR

Added ADR-0044 (token auth: fine-grained PAT via Bearer, GitHub App deferred with no config-surface change; and fetch, not Octokit). The spec flagged that issue #17's real-time spec may also claim 0044 — please renumber on merge if it collides.

Verification

  • TDD-first: client.test.ts, markdown.test.ts, index.test.ts authored before implementation. pnpm --filter @airnauts/airside-extension-github test → 10 passing.
  • pnpm build green (incl. host route typecheck against the new package).
  • pnpm lint (biome ci) exit 0 — no new warnings in the package.

🤖 Draft opened by airside-agent — automated build of #48.

New publishable package `@airnauts/airside-extension-github` mirroring the
Jira extension: one `thread-action` (`id:'github.createIssue'`,
`provider:'github'`, slot `thread-toolbar`) whose `run` creates a GitHub issue
via `POST /repos/{owner}/{repo}/issues` (native fetch, `Bearer` auth, no
Octokit) and returns an `externalLink` the server persists. `visibleWhen` hides
the action once a github link exists. Issue body is Markdown (local
`buildMarkdownDescription`/`buildIssueTitle`), no server/core change. Wired
env-gated into the Next.js host, added to the changeset `fixed` group with a
minor changeset, and recorded in ADR-0044 (token auth + fetch-not-octokit).

Closes #48.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YC2L9GsNmvyjm6VrUJvX1
@MateuszPaulski

Copy link
Copy Markdown
Collaborator Author

Review — verified findings

Solid, faithful mirror of the jira extension. Two things to fix at merge, plus notes.

1. ADR number collision: this PR's ADR-0044 already exists on main. Main's docs/adr.md now runs through ADR-0047 (ADR-0044 — deleteThread on the repository contract), and PR #70's branch claims ADR-0048. Renumber this entry to the next free slot at merge time.

2. No length cap on the issue body. src/markdown.ts buildMarkdownDescription returns the joined lines uncapped, while the title is truncated to 255. GitHub rejects issue bodies over 65,536 chars with a 422, which the client maps to an IntegrationError — so "Create GitHub issue" permanently fails for very large threads. Truncate with a marker, mirroring the title's treatment. (The jira twin has the same gap in adf.ts — worth a follow-up there.)

Non-issues verified for the record:

  • package.json says 0.9.1 while the fixed group is at 0.10.1 — benign: the package is correctly in the fixed array, and changeset version reconciles the whole group upward, overwriting the stale number.
  • Unencoded owner/repo in the request path — no realistic trigger, since GitHub disallows URL-reserved characters in those names and config is validated non-empty.

Forward-looking: ~80–100 lines (fetch wrapper, hasExternalLink, extension factory glue, the create-succeeds/persist-fails recovery log) are near-verbatim copies of integration-jira. Deliberate per the ADR, but when Linear (#47) would become the third copy, extract a shared createThreadActionExtension seam in the server package so the idempotency and token-never-in-errors invariants live in one place.

Changeset present for the new package. ✅

Renumber this PR's ADR to ADR-0049 (0044-0047 taken on main, 0048 claimed
by PR #70) and update in-repo references. Cap GitHub issue body under the
65,536-char limit with a truncation marker so very large threads still
create an issue instead of failing with a 422.

Airside-Agent-Fix: true
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MateuszPaulski

Copy link
Copy Markdown
Collaborator Author

🤖 airside-agent: addressed "Review — verified findings" in 15b7fb4 — renumbered the colliding ADR-0044 → ADR-0049 (+refs) and capped the issue body under GitHub's 65,536 limit with a truncation marker (+tests); left the benign version-note/encoding/shared-seam items as-is per your notes.

@MateuszPaulski

Copy link
Copy Markdown
Collaborator Author

fix merge conflixts

Resolve docs/adr.md conflict: keep main's ADR-0044..0047 and place this
PR's GitHub-extension ADR-0049 last. Align new
@airnauts/airside-extension-github to the 0.10.1 fixed-group version.

Airside-Agent-Fix: true
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MateuszPaulski

Copy link
Copy Markdown
Collaborator Author

🤖 airside-agent: addressed "fix merge conflicts" in 8406fe7 — merged origin/main and resolved the only conflict (docs/adr.md: kept main's ADR-0044…0047 plus this PR's ADR-0049 last), aligned the new extension-github package to fixed-group 0.10.1, preserved the feature + changeset. Lint/tests/build green; PR is MERGEABLE again.

@MateuszPaulski
MateuszPaulski merged commit 4c27c4e into main Jul 3, 2026
3 checks passed
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.

Integrations: GitHub Issues thread-action target (create a linked GitHub issue from a thread)

1 participant