Skip to content

fix(github): create contributor issues via installation tokens instead of a flat PAT - #7467

Merged
loopover-orb[bot] merged 1 commit into
mainfrom
claude/orb-github-issue-automation-080318
Jul 20, 2026
Merged

fix(github): create contributor issues via installation tokens instead of a flat PAT#7467
loopover-orb[bot] merged 1 commit into
mainfrom
claude/orb-github-issue-automation-080318

Conversation

@JSONbored

@JSONbored JSONbored commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • Every other GitHub write in this codebase (labels, comments, check-runs) authenticates via the installation-token/Orb-broker path (src/github/app.ts, src/orb/broker-client.ts), which works on any repo the caller's GitHub App or Orb-brokered install is actually installed on. Issue creation was the one write left on a separate, flat operator PAT (LOOPOVER_CONTRIBUTOR_ISSUE_TOKEN / GITHUB_PUBLIC_TOKEN) that had to independently hold write access to whichever repo was targeted.
  • Adds src/github/issues.ts (createInstallationIssue), mirroring src/github/labels.ts's existing pattern, and migrates contributor-issue-draft.ts's createGitHubContributorIssue onto it. createInstallationToken already picks the local App key or the Orb broker transparently depending on deployment config, so this one call site now works either way with no changes needed at the call site.
  • Removes the now-fully-unused LOOPOVER_CONTRIBUTOR_ISSUE_TOKEN env var (src/env.d.ts, .env.example, and a vestigial reference in a route test that never actually exercised it).
  • This is the blocking prerequisite (tracked as #7425, a sub-issue of the ORB self-hoster issue/milestone-planning epic #7424) for building a repo-agnostic, selfhoster-facing issue-planning MCP tool on top of the same auth path.
  • Left out of scope, documented in Spec: generalize GitHub write path for issue/milestone creation off flat-PAT onto installation-token/Orb-broker #7425: src/upstream/ruleset.ts's fileUpstreamDriftIssues (create+update+find+validate, hardcoded to loopover's own tracker repo only) stays on its existing PAT path — a separably-sized migration not required to unblock the rest of the epic, and a narrower risk surface since it never targets an arbitrary selfhosted repo.

Scope

  • The PR title follows type(scope): short summary Conventional Commit format, for example fix(api): restore profile access checks.
  • This PR is focused and does not mix unrelated backend, UI, MCP, docs, dependency, and deploy changes.
  • This follows CONTRIBUTING.md and does not reintroduce GitHub Pages, VitePress, site/, or CNAME.
  • I linked a currently open issue this PR resolves (e.g. Closes #123) — a linked open issue is required for every contributor PR.

Validation

  • git diff --check
  • npm run actionlint (ran as part of npm run selfhost:env-reference:check/typecheck pass below; no workflow files touched)
  • npm run typecheck
  • npm run test:coverage locally — full unsharded suite: 1009 files / 19188 tests passed. 9 failures across 3 unrelated miner test files (local-branch.test.ts, miner-init-verify-token.test.ts, miner-self-review-context.test.ts) reproduce identically on a clean main checkout with this branch's changes stashed out — confirmed pre-existing and unrelated (flagged separately, not fixed here to keep this PR focused). New/changed code (src/github/issues.ts, the migrated createGitHubContributorIssue) is 100% branch-covered.
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate (pre-existing adm-zip/github-actionlint advisory, no fix available, unrelated to this change)
  • New or changed behavior has unit/integration tests for new branches, fallback paths, and sanitizer boundaries

If any required check was skipped, explain why:

  • ui:lint / ui:typecheck / ui:build not run: this PR touches no files under apps/loopover-ui/** — a backend-only auth-path migration in src/.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • Auth, cookie, CORS, GitHub App, Cloudflare, or session changes include negative-path tests (invalid repo names, non-2xx GitHub responses, dry-run suppression, missing installation — all covered in test/unit/github-issues.test.ts and the updated test/unit/contributor-issue-draft.test.ts).
  • API/OpenAPI/MCP behavior is updated and tested where needed. (N/A — no route/MCP surface changed, only the internal write mechanism.)
  • UI changes use live API data or real empty/error/loading states, not production mock/demo fallbacks. (N/A — no UI changed.)
  • Visible UI changes include a UI Evidence section below. (N/A — backend-only change.)
  • Public docs/changelogs are updated where needed. (N/A — no user-facing docs affected; the removed env var was never documented outside .env.example.)

UI Evidence

N/A — this is a backend-only change with no visible UI, frontend, or docs surface.

Notes

  • Sub-issue of #7424 (Epic: ORB self-hoster issue & milestone planning routine).

Closes #7425

…d of a flat PAT

Every other GitHub write (labels, comments, check-runs) goes through the
installation-token/Orb-broker path so it works on any repo the App/Orb is
installed on. Issue creation was the one write left needing a separately
configured PAT with its own write access to whichever repo was targeted.
Adds src/github/issues.ts (createInstallationIssue) and migrates
contributor-issue-draft.ts onto it, clearing the way for a repo-agnostic
selfhoster-facing issue-planning tool to reuse the same auth path.

Closes #7425
@JSONbored JSONbored self-assigned this Jul 20, 2026
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.33%. Comparing base (25decd9) to head (a5b675a).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7467      +/-   ##
==========================================
- Coverage   91.35%   91.33%   -0.02%     
==========================================
  Files         716      717       +1     
  Lines       72990    73002      +12     
  Branches    21628    21628              
==========================================
+ Hits        66678    66679       +1     
- Misses       5272     5279       +7     
- Partials     1040     1044       +4     
Flag Coverage Δ
shard-1 34.06% <0.00%> (+1.38%) ⬆️
shard-2 39.24% <0.00%> (+3.12%) ⬆️
shard-3 32.60% <0.00%> (-1.93%) ⬇️
shard-4 39.53% <0.00%> (-3.35%) ⬇️
shard-5 36.58% <90.47%> (-0.40%) ⬇️
shard-6 34.33% <71.42%> (+0.77%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/github/issues.ts 100.00% <100.00%> (ø)
src/services/contributor-issue-draft.ts 96.77% <100.00%> (-0.07%) ⬇️

... and 2 files with indirect coverage changes

@loopover-orb loopover-orb Bot added the gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. label Jul 20, 2026
@loopover-orb

loopover-orb Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Tip

✅ LoopOver review result - approve/merge recommended

Review updated: 2026-07-20 11:11:43 UTC

7 files · 1 AI reviewer · no blockers · readiness 100/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This PR replaces the flat-PAT GitHub issue creation path with the installation-token/Orb-broker path already used by labels/comments/check-runs, adding `src/github/issues.ts:createInstallationIssue` and threading `installationId` through `createGitHubContributorIssue`. The migration is correct: validation happens before token minting, a missing `installationId` fails closed exactly like the old missing-token check, and the broad try/catch around the now-throwing Octokit call preserves the prior `skipped_create_failed` null-return contract for callers. Test coverage is thorough, covering both the local-App-key and Orb-broker paths, dry-run suppression, malformed responses, and the pause/freeze regression test updated to prove the brake (not the token gate) is what blocks the POST.

Nits — 5 non-blocking
  • src/services/contributor-issue-draft.ts: the broad `catch` around `createInstallationIssue` swallows all Octokit errors (network, auth, malformed repo name) into the same `skipped_create_failed` bucket — consider logging the error type/status alongside the message for easier triage later.
  • The console.warn structured log in contributor-issue-draft.ts is a reasonable addition, not a real debug leftover, but confirm it matches the codebase's existing structured-logging convention rather than being a one-off pattern.
  • If `context.repo` can be undefined/null when `generateContributorIssueDrafts` calls `createGitHubContributorIssue`, double check that path is exercised by a test (installationId undefined → early null return) similar to the existing 'invalid repo names' test.
  • Consider extracting `parseRepoFullName` into a shared helper across labels.ts/assignees.ts/issues.ts now that a third near-identical copy exists, even though the PR description explains this mirrors the current house convention.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.

Decision drivers

  • ✅ Code review — No blockers (1 reviewer)
  • ✅ Gate result — Passing (No configured blocker found.)
Context & advisory signals — never blocks the verdict
Signal Result Evidence
Linked issue ✅ Linked #7425
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 28 registered-repo PR(s), 21 merged, 377 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 28 PR(s), 377 issue(s).
Improvement ✅ Minor risk: clean · value: minor · LLM: moderate
Linked issue satisfaction

Partially addressed
The PR adds a shared createInstallationIssue resolver (App-key/broker via existing withInstallationTokenRetry) and migrates contributor-issue-draft.ts's writer onto it with fail-closed behavior and test coverage for both branches, satisfying most deliverables, but explicitly leaves ruleset.ts's fileUpstreamDriftIssues on the flat-PAT path, which the issue lists as an open scope item requiring an e

Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, Ruby, Go, JavaScript, MDX, Shell, Solidity
  • Official Gittensor activity: 28 PR(s), 377 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Start here: Treat this as maintainer-lane context rather than normal contributor-lane activity.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
🧪 Chat with LoopOver

Ask LoopOver a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @loopover ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @loopover chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @loopover mention with a real question is routed to the closest matching read-only command automatically — no exact syntax required.

Full command reference: https://loopover.ai/docs/loopover-commands

🧪 Experimental — new and may change.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by LoopOver, a quiet PR intelligence layer for OSS maintainers.

  • Re-run LoopOver review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoopOver approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 4f29819 into main Jul 20, 2026
17 checks passed
@loopover-orb
loopover-orb Bot deleted the claude/orb-github-issue-automation-080318 branch July 20, 2026 11:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Spec: generalize GitHub write path for issue/milestone creation off flat-PAT onto installation-token/Orb-broker

1 participant