Skip to content

--attach stack 5/8: Add the flag and upload behind it - #14181

Merged
BagToad merged 2 commits into
bagtoad/attach-uploadfrom
bagtoad/attach-flag
Aug 25, 2026
Merged

--attach stack 5/8: Add the flag and upload behind it#14181
BagToad merged 2 commits into
bagtoad/attach-uploadfrom
bagtoad/attach-flag

Conversation

@BagToad

@BagToad BagToad commented Aug 18, 2026

Copy link
Copy Markdown
Member

Part of the pull request stack tracked in #14186.

Description

This is the fifth layer of the stack. The first commit adds the flag and reads its values. The second ties uploading to rewriting and decides when the resulting markdown is safe to write. No command offers the flag yet.

The flag is repeatable and takes a file path, optionally followed by # and alt text. Without alt text the file name is used. Every named file is validated before anything is uploaded.

Naming the same file twice is refused, and that includes a file and a symlink to it, and a file and a hard link to it, since both would upload the same bytes twice. An empty value is refused too, which is what a script produces when a variable is unset.

Conflicting flags are checked while the flag is being read, rather than in each command, so a command that offers the flag cannot forget to check them.

The flag is registered as a string array rather than a string slice, because a string slice splits on commas and a comma is legal in a file name:

cmd.Flags().StringArray(flagName, nil, "Attach an image or video `file`, in <file>#<alt text> format")

How did you test this change?

The whole stack was built and the failure path was exercised by hand against a private test repository. Three files were attached with the middle one made unreadable. Exactly one upload request left the machine for three attached files, the command exited non zero and named the file that failed, and the comment was still posted carrying the one file that did upload.

When the only attached file failed, nothing was posted at all and the command said so.

Duplicate detection was exercised with a plain duplicate, with a symlink to the same file, and with a hard link to it.

Key points

An upload cannot be undone and there is no endpoint to delete an uploaded asset. That single fact drives the design of the second commit.

The function reports how many assets reached the server, and a caller writes the body only when that count is above zero. Markdown that does not reference an uploaded asset would orphan that asset for good. A count of zero means nothing was uploaded, so nothing is lost by writing nothing.

Uploading stops at the first failure and nothing after it is attempted. A reference to a file that did not upload keeps its local path, so a partial failure leaves a body containing links that do not resolve. That is the accepted cost of writing a body that already carries a real uploaded asset, and it is a thing a user will see.

Notes for reviewers

The count returned by the upload function is the whole safety mechanism. Read that first, then read the callers in the layers above to see how it is used.

Authorship and follow-up

Who wrote this:

  • A human wrote it.
  • An agent wrote it under close human direction.
  • An agent wrote it independently, and no human has guided the implementation beyond the initial prompt.

Who answers review comments:

  • @BagToad will read and reply directly. Name the account.
  • An agent will draft replies and @BagToad will read them before they are posted.
  • Nobody has explicitly committed to replying.

@BagToad BagToad changed the title bagtoad/attach flag --attach stack 5/8: Add the flag and upload behind it Aug 18, 2026
@BagToad
BagToad marked this pull request as ready for review August 18, 2026 05:56
@BagToad
BagToad requested a review from a team as a code owner August 18, 2026 05:56
@BagToad
BagToad requested review from babakks and a balanced review from Copilot August 18, 2026 05:56

@kyleyoungsr82-ai kyleyoungsr82-ai left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot AI 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.

Pull request overview

Adds internal --attach plumbing for validated image/video uploads and Markdown rewriting. No command exposes the flag yet.

Changes:

  • Parses, validates, and deduplicates attachments.
  • Uploads assets with partial-failure handling.
  • Adds comprehensive attachment tests and helpers.
Show a summary per file
File Description
internal/attachments/flags.go Implements flag parsing and validation.
internal/attachments/flags_test.go Tests flag behavior and conflicts.
internal/attachments/attach.go Coordinates uploads and Markdown updates.
internal/attachments/attach_test.go Tests upload and rewriting flows.
internal/attachments/test.go Provides shared attachment test helpers.

Review details

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 5/5 changed files
  • Comments generated: 5
  • Review effort level: Balanced

Comment thread internal/attachments/flags.go
Comment thread internal/attachments/flags.go
Comment thread internal/attachments/flags.go
Comment thread internal/attachments/attach.go
Comment thread internal/attachments/flags.go
BagToad and others added 2 commits August 18, 2026 14:11
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

@babakks babakks left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for this one, @BagToad! 🙏

The orchestration in UploadAndAttach is nicely reasoned, especially stopping at the first upload failure and returning the partial markdown plus an uploaded count so we never orphan an asset that already reached the server. The parseArg splitter handling # in filenames by probing the longest existing path is clever, and the coverage across both test files is great.

My main piece of feedback is about a design concern rather than a bug, so I'm approving to keep the stack moving with the understanding that it lands in a follow-up:

  • Flag-wise intimacy between attachments and command packages. I'd like us to fix the coupling where this package reaches into command-owned flags. checkFlagConflicts inspects --web, --delete-last, and --dry-run, which the package has no business knowing about, and FromFlagValues looks the flag up by name. I left a sketch of a design that encapsulates the flag in an AttachFlag type returned from an AddAttachFlag(cmd, name, shorthand) constructor, with FromFlagValues becoming a method on it. The commands would then own their own mut-ex checks (even at the cost of a little duplication).

Smaller stuff in the inline comments: an os.Lstat swap (with a stubbable indirection) to sidestep symlink resolution, a refs to args rename to avoid clashing with attachmentRef, reordering the empty-addition check in appendParagraph, and a help-text nitpick.

Nice work! 🚀

Comment thread internal/attachments/flags.go
Comment thread internal/attachments/flags.go
Comment thread internal/attachments/flags.go
Comment thread internal/attachments/flags.go
Comment thread internal/attachments/attach.go
Comment thread internal/attachments/attach.go
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.

4 participants