feat: attach already-uploaded objects to a PR/issue by key or URL - #706
Conversation
- apps/api: new POST /v1/workspaces/:workspace/github/attach endpoint (canonical dual-auth surface). Resolves a source key or uploads.sh URL (storage host, embed host, /f/ page) to a key in the calling workspace, in-bucket-copies it into the PR/issue attachment prefix (respecting the gh/private/<id>/ layout when it applies), merges D1 metadata additively (source's existing metadata preserved; gh.repo/gh.kind/gh.number/gh.ref stamped fresh), and runs the normal managed-comment sync. Copy by default; move: true deletes the source after a successful copy. Idempotent — re-attaching the same source to the same target overwrites the destination key in place. Same workspace-token auth and repo-link claim posture as the existing comment/promote routes. - packages/uploads (CLI): uploads attach --pr/--issue <arg>... now treats an arg that does not exist on disk as a candidate object key or URL instead of erroring file not found, calling the new endpoint via a bounded-concurrency batch. Existing local files always win. New --move flag. Updated the not-found error message for a bad key/URL arg. - apps/mcp: the hosted promote tool gained an explicit keys argument (alongside its existing branch-staged sweep) that reuses the same server-side attach logic; one bad key degrades into attachFailures rather than aborting the batch. - Tests at each layer (server route, CLI command, hosted MCP tool) plus a changeset for the CLI package.
🦋 Changeset detectedLatest commit: 5bf67a3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (2)
🚫 Excluded labels (none allowed) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
There was no way to attach an already-uploaded file to a PR or issue without
downloading and re-uploading it. Closes #702.
What changed
Server — new
POST /v1/workspaces/:workspace/github/attachon thecanonical dual-auth surface (
apps/api/src/routes/github-attach.ts,github-attach.ts,github-attach-service.ts):gh/private/<id>/...layout when the repo resolves to private mode(same
resolveGhKeyContextSafeused by promote).existing D1 metadata rides along unchanged;
gh.repo/gh.kind/gh.number/gh.refare stamped fresh on top. This is the one deliberatedivergence from
github-promote.ts, which does a full-replacegh.*-onlycopy — an attach source can carry arbitrary metadata (
path/viewport/state/a prior attachment's own tags) worth preserving.postManagedComment) — oneAPI call both attaches and refreshes the comment, unlike branch-staged
promote which leaves that to a separate CLI call.
files:write) and implicit repo-link claimposture as the existing
comment/promoteroutes.move: truedeletes the source only after a successfulcopy.
destination key in place.
Only added to the canonical
/v1/workspaces/:workspace/github/*vertical —no legacy bearer-only twin, since this is a new route rather than a moved one.
CLI (
packages/uploads) —uploads attach --pr/--issue <arg>...: an argthat doesn't exist on disk is now tried as a workspace object key or
uploads.sh URL against the new endpoint instead of erroring
file not found. Existing on-disk files always win. New--moveflag.Mixed batches (local files + keys/URLs) work in one call.
Hosted MCP (
apps/mcp) — thepromotetool gained an explicitkeysargument (array of keys/URLs), independent of and combinable with its
existing branch-staged sweep. One bad key degrades into
attachFailuresrather than aborting the batch;
branchis no longer required as long askeysis given.Tests
apps/api/src/routes/github-attach-route.test.ts— 12 cases (bad body,auth, 404 on missing source, copy + additive metadata, all three URL
spellings, cross-workspace URL rejection, idempotent overwrite, move,
issue target).
packages/uploads/test/commands-attach.test.ts— newdescribeblock:key/URL attach,
--move, mixed local+remote batch, updated not-foundmessage,
--movemisuse guard.apps/mcp/test/mcp-branch-promote.test.ts—keysalongside/withoutbranch, partial-failure degrade, updated required-args usage error.pnpm test(4469 tests),pnpm typecheck, andpnpm checkall pass.Deviations from the issue text
--move(issue draft also mentioned--from-keyas analternative disambiguator for the positional arg — not needed since a
URL/key is essentially never also a valid local path).
pr/issue(mutually exclusive) rather than ageneric
kind/numpair, mirroring the CLI's own--pr/--issueflags.the note above.
Relationship to #700 / #701
github-attach.ts's copy/resolve logicas-is for an "adopt = attach-by-reference" flow.
uploads attach --pr <num> <key>...is nowactionable end to end.