Skip to content

Load file content from GitHub for cloud runs#2395

Open
k11kirky wants to merge 2 commits into
mainfrom
posthog-code/cloud-run-github-file-fetch
Open

Load file content from GitHub for cloud runs#2395
k11kirky wants to merge 2 commits into
mainfrom
posthog-code/cloud-run-github-file-fetch

Conversation

@k11kirky
Copy link
Copy Markdown
Contributor

Summary

Closes #2390. In cloud runs, clicking a file reference in the chat showed "File content not available" when the agent only ran grep/find (never Read/Edit/Write) against it — leaving no way to see the file.

Now, when the file isn't in the agent's tool calls but we know the repo and branch, fetch the content from GitHub at that branch and render it in the same CodeMirror/markdown editor. Falls back to a "View on GitHub" button if the fetch returns null (404, private without gh auth, etc.).

Implementation

  • New GitService.getGithubFileContent(owner, repo, filePath, ref) using gh api /repos/{owner}/{repo}/contents/{path}?ref=... with Accept: application/vnd.github.raw and URL-encoded path segments.
  • New Zod-validated tRPC procedure git.getGithubFileContent.
  • CodeEditorPanel resolves owner/repo/branch/path from the task + cloud session, strips the sandbox prefix by locating the last /<repo-short-name>/ segment, and renders the fetched content via the same editor used for local files.

Test plan

  • Open a cloud run task where the agent only grep-ed a file (didn't Read it). Click the file mention — the file content loads in the editor.
  • Click a file the agent did Read/Edit — still uses the existing in-memory tool-call content (no GitHub round-trip).
  • Private repo without gh auth → "View on GitHub" fallback button appears and opens the blob URL.
  • Path with spaces or special characters loads correctly.
  • Local (non-cloud) runs unaffected.

Clicking a file reference in a cloud run's chat showed "File content not available" whenever the agent only ran `grep`/`find` against it (never `Read`/`Edit`/`Write`).

Now, when the file isn't in the agent's tool calls but we know the repo and branch, fetch the content from GitHub at that branch via `gh api /repos/{owner}/{repo}/contents/{path}?ref=...` with `Accept: application/vnd.github.raw` and render it in the same editor. Falls back to a "View on GitHub" button if the fetch returns null (404, private without `gh` auth, etc.).

Closes #2390

Generated-By: PostHog Code
Task-Id: 215cdb33-aeaf-40b8-8fcc-70a0024e69bd
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 27, 2026

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/code/src/renderer/features/code-editor/components/CodeEditorPanel.tsx:71-81
`lastIndexOf` incorrectly strips the path when a subdirectory inside the repo shares the repo's short name — a very common pattern in Python projects (e.g., a `posthog` repo that contains a `posthog/` package directory). For an absolute path like `/workspace/runner/abc/posthog/posthog/utils.py`, `lastIndexOf("/posthog/")` matches at the *inner* segment, returning `utils.py` instead of `posthog/utils.py`. The GitHub API call then fetches the wrong file (or a 404), and the blob URL is equally broken.

```suggestion
function toRepoRelativePath(
  repoShortName: string | null,
  path: string,
): string | null {
  if (!path.startsWith("/")) return path;
  if (!repoShortName) return null;
  const marker = `/${repoShortName}/`;
  const idx = path.indexOf(marker);
  if (idx < 0) return null;
  return path.slice(idx + marker.length);
}
```

### Issue 2 of 2
apps/code/src/renderer/features/code-editor/components/CodeEditorPanel.tsx:156
The `repoRelativePath` in `blobUrl` is not URL-encoded, so paths containing spaces, `#`, or `?` will produce a malformed URL. The "View on GitHub" fallback button would silently open a broken link for those files.

```suggestion
      blobUrl: `https://github.com/${owner}/${name}/blob/${branch}/${repoRelativePath.split("/").map(encodeURIComponent).join("/")}`,
```

Reviews (1): Last reviewed commit: "Load file content from GitHub for cloud ..." | Re-trigger Greptile

Comment on lines +71 to +81
function toRepoRelativePath(
repoShortName: string | null,
path: string,
): string | null {
if (!path.startsWith("/")) return path;
if (!repoShortName) return null;
const marker = `/${repoShortName}/`;
const idx = path.lastIndexOf(marker);
if (idx < 0) return null;
return path.slice(idx + marker.length);
}
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.

P1 lastIndexOf incorrectly strips the path when a subdirectory inside the repo shares the repo's short name — a very common pattern in Python projects (e.g., a posthog repo that contains a posthog/ package directory). For an absolute path like /workspace/runner/abc/posthog/posthog/utils.py, lastIndexOf("/posthog/") matches at the inner segment, returning utils.py instead of posthog/utils.py. The GitHub API call then fetches the wrong file (or a 404), and the blob URL is equally broken.

Suggested change
function toRepoRelativePath(
repoShortName: string | null,
path: string,
): string | null {
if (!path.startsWith("/")) return path;
if (!repoShortName) return null;
const marker = `/${repoShortName}/`;
const idx = path.lastIndexOf(marker);
if (idx < 0) return null;
return path.slice(idx + marker.length);
}
function toRepoRelativePath(
repoShortName: string | null,
path: string,
): string | null {
if (!path.startsWith("/")) return path;
if (!repoShortName) return null;
const marker = `/${repoShortName}/`;
const idx = path.indexOf(marker);
if (idx < 0) return null;
return path.slice(idx + marker.length);
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/code-editor/components/CodeEditorPanel.tsx
Line: 71-81

Comment:
`lastIndexOf` incorrectly strips the path when a subdirectory inside the repo shares the repo's short name — a very common pattern in Python projects (e.g., a `posthog` repo that contains a `posthog/` package directory). For an absolute path like `/workspace/runner/abc/posthog/posthog/utils.py`, `lastIndexOf("/posthog/")` matches at the *inner* segment, returning `utils.py` instead of `posthog/utils.py`. The GitHub API call then fetches the wrong file (or a 404), and the blob URL is equally broken.

```suggestion
function toRepoRelativePath(
  repoShortName: string | null,
  path: string,
): string | null {
  if (!path.startsWith("/")) return path;
  if (!repoShortName) return null;
  const marker = `/${repoShortName}/`;
  const idx = path.indexOf(marker);
  if (idx < 0) return null;
  return path.slice(idx + marker.length);
}
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread apps/code/src/renderer/features/code-editor/components/CodeEditorPanel.tsx Outdated
Address Greptile review feedback:

- Replace ambiguous `lastIndexOf("/<repo-name>/")` heuristic with the exact cloud sandbox prefix `/tmp/workspace/repos/<owner>/<repo>/`. This handles repos whose name matches an inner subdirectory (e.g. `posthog` repo with a `posthog/` package directory) deterministically — the prior heuristic would have stripped one level too many.

- URL-encode each segment of `repoRelativePath` (and the branch) when constructing the GitHub blob URL, so paths with spaces, `#`, or `?` produce a valid link.

Generated-By: PostHog Code
Task-Id: 215cdb33-aeaf-40b8-8fcc-70a0024e69bd
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.

Can't open referenced files on cloud runs

1 participant