Conversation
Create posts an artifact's type, name and body to an issue and returns the new artifact. UploadTarget is the issue lookup for commands that take --attach. Like IsPullRequest it makes one lookup, which also returns the repository ID and the viewer's permission that an upload needs.
gh issue artifact create names an artifact with <file>#<name>, parsed exactly like --attach's alt text: a path that exists wins, then the longest existing path before a #. One exported parser keeps # meaning the same in both.
create makes one artifact for each file or URL argument, in argument order. Text files become documents named after the file, or after #<name>; URLs and .url Internet Shortcut files become links, and a URL is named after its host. --body and --body-file create one artifact, with --name, and --body-file - is the only way standard input is read. --type plan saves documents as plans. Every file is read and checked before any request, so a binary or empty file, or a shortcut without an http(s) URL, fails the whole command. Names gh takes from file names drop the characters artifact names can't contain. --attach uploads each file once for every document that references it, through UploadAndAttachDocuments. A document is saved when any of its files uploaded, since uploads can't be undone, and its line gives the upload error as the reason. One whose files all failed isn't saved. The shared package gains what edit will need too: reading new content with the binary and empty checks, reading .url files, the lookup that also serves --attach, and a result line for an artifact saved despite a failure.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the pull request stack tracked in #14563.
This adds
gh issue artifact createfrom #14525.Description
Issue artifacts are Markdown documents and links attached to an issue. The previous pull requests added the
gh issue artifactcommand group,list,view,deleteanddownload. This one addscreate, with the aliasesaddandnew. It creates one artifact for each file or URL, in argument order:genericdocument named after the file. Text after#names it instead.--type plansaves documents as plans..urlInternet Shortcut file, the kinddownloadwrites, becomes a link to its URL.--bodyand--body-filecreate one artifact, and--namenames it. Standard input is only read with--body-file -.plan (1).mdis namedplan 1.md. Names you type are sent as typed, and the server's error is shown if it refuses one.--attachuploads images and videos and points each document's references at them, as it does forgh issue create. With several documents, each file is uploaded once, and every document that references it gets its URL. An attachment no document references has no one body to be appended to, so it's an error before anything uploads.deleteanddownload. The source column is the file path, the URL, or-for standard input.Every file is read and checked before any request. A binary or empty file, or a shortcut without an http(s) URL, fails the whole command, and nothing is created. After that, each artifact succeeds or fails on its own line, and gh exits 1 if any failed.
The API client gains
Create. The shared package gains whateditwill also need: reading new content with the binary and empty checks, reading.urlfiles, and a result line for an artifact saved despite a failed upload.How did you test this change?
I recorded the built
ghcreating artifacts on one issue in bagtoad/issue-artifacts-demo, each case checked withvieworlist: a file,#<name>, a cleaned-up name, several files, standard input,--body, a plan, a URL, a.urlfile,--attachreplacing a reference and appending an image, two files sharing one upload, an attachment no file references, and piped output. It leaves out the other errors, failed uploads and saves, references resolved from other directories, symlinks, pull requests and GitHub Enterprise Server. Separately, I rangh issue artifact create 28 signin-plan.mdin the demo repository as an account that can read it but not write to it: it printedX Failed to create artifact from signin-plan.md: Not Found, exited 1, and the issue's artifacts didn't change.recording.mp4
Open chapters and agent notes
Key points
#<name>is parsed like--attachalt text. An argument that exists as a path is used whole, sobarista-notes#2.mdworks. Otherwise the longest existing path before a#wins.internal/attachmentsexports its parser asSplitFileArg, unchanged, so#means the same in both.Names gh takes from file names fit the server's rule.
nameFromFilekeeps letters, numbers, accent marks, spaces,.,-and_, then trims the ends to a letter or number. A file name with none of them fails before any request and asks for#<name>or--name, or only--namefor--body-file, which takes its path as typed. A URL is named after its host without the port, since names can't hold:or/. A host that still breaks the rule, such as::1, gets the server's error on its line.An upload can't be undone, so each artifact follows the
--attachrule on its own.attachuploads every file once throughUploadAndAttachDocuments, from earlier in this stack, and then decides for each document:A document that is saved with only some of its files keeps its
createdstatus, and the upload error is its reason. So a script can tell the artifact exists and doesn't create it twice. In a terminal,PrintPartialFailureprints one line on stderr, and gh exits 1:Upload errors keep their whole text on a result line.
failureReasonshortens an API error to the server's message, because the line already names the artifact. An upload error wraps an API error, but its own text names the file and explains the status, so now only an error that is itself an API error is shortened:deleteanddownloadget their errors straight from the client, so their lines don't change.--attachstill refuses a pull request after one lookup. The client's newUploadTargetmakes the same lookup asIsPullRequest, and also asks for the repository ID and permission that an upload needs. Without--attach,createchecks the issue like the other commands.--attachrecords the same telemetry event as the other--attachcommands.gh issuenow passes its telemetry recorder to the artifact commands.A positional
-is refused. Standard input is only read with--body-file -, and-is how a result line names it. The error is "cannot create an artifact from-; use--body-file -to read standard input", shaped like--attach's "cannot attach standard input; --attach needs a file path"../-still reads a file named-.Notes for reviewers
Start with the
createrun function, thenreadSource, which works out each artifact's type, name and content, andattachafter it.TestCreateRunruns each row in a temporary directory, with the client mock for artifact requests and HTTP stubs for uploads. It has rows for failed, partial and never-tried uploads, which the recording can't show.The saved-despite-a-failed-upload line above isn't in #14525, and neither are these messages. Each follows the closest existing message:
--name cannot be blankand--body cannot be blank, like--output cannot be blank.failed to create artifact from plan.md: the name after `#` cannot be blank.failed to create artifact from ---: the file name has no letters or numbers; name it with `#<name>` or `--name`, which endsname it with `--name`for--body-file.--attach can't be used with link artifacts, when every argument is a link.failed to create artifact from standard input: input is empty, and... binary input not supported.broken.url: no URL in the [InternetShortcut] section, andbroken.url: the shortcut doesn't link to an http(s) URL.failed to create artifact from https://ラテ.example/menu: links must be http(s) URLs with a host, in printable ASCII with no spaces.X Failed to create artifact (Root cause): Not Foundfor--body, andX Failed to create artifact from standard input: Not Found.no file references latte-art.png or menu-photo.png; reference them in a file, or attach them when creating a single artifact, for more than one file.Related issues:
gh issue artifact create#14525 is thecreatedesign, with a screen for each scenario.gh issue artifact#14529 is the RFC for the command group.Authorship and follow-up
Who wrote this:
Who answers review comments: