@@ -7,12 +7,15 @@ import (
77 "fmt"
88 "io"
99 "net/http"
10+ "net/url"
1011 "reflect"
1112 "sort"
1213 "strings"
14+ "time"
1315
1416 "github.com/MakeNowJust/heredoc"
1517 "github.com/cli/cli/v2/api"
18+ fd "github.com/cli/cli/v2/internal/featuredetection"
1619 "github.com/cli/cli/v2/internal/ghrepo"
1720 "github.com/cli/cli/v2/pkg/cmd/workflow/shared"
1821 "github.com/cli/cli/v2/pkg/cmdutil"
@@ -25,6 +28,7 @@ type RunOptions struct {
2528 HttpClient func () (* http.Client , error )
2629 IO * iostreams.IOStreams
2730 BaseRepo func () (ghrepo.Interface , error )
31+ Detector fd.Detector
2832 Prompter iprompter
2933
3034 Selector string
@@ -64,6 +68,8 @@ func NewCmdRun(f *cmdutil.Factory, runF func(*RunOptions) error) *cobra.Command
6468 - Interactively
6569 - Via %[1]s-f/--raw-field%[1]s or %[1]s-F/--field%[1]s flags
6670 - As JSON, via standard input
71+
72+ The created workflow run URL will be returned if available.
6773 ` , "`" ),
6874 Example : heredoc .Doc (`
6975 # Have gh prompt you for what workflow you'd like to run and interactively collect inputs
@@ -260,6 +266,11 @@ func runRun(opts *RunOptions) error {
260266 return err
261267 }
262268
269+ if opts .Detector == nil {
270+ cachedClient := api .NewCachedHTTPClient (c , time .Hour * 24 )
271+ opts .Detector = fd .NewDetector (cachedClient , repo .RepoHost ())
272+ }
273+
263274 ref := opts .Ref
264275
265276 if ref == "" {
@@ -303,34 +314,77 @@ func runRun(opts *RunOptions) error {
303314 }
304315 }
305316
306- path := fmt .Sprintf ("repos/%s/actions/workflows/%d/dispatches" ,
307- ghrepo .FullName (repo ), workflow .ID )
317+ features , err := opts .Detector .ActionsFeatures ()
318+ if err != nil {
319+ return err
320+ }
321+
322+ path := fmt .Sprintf ("repos/%s/%s/actions/workflows/%d/dispatches" , url .PathEscape (repo .RepoOwner ()), url .PathEscape (repo .RepoName ()), workflow .ID )
308323
309- requestByte , err := json . Marshal ( map [string ]interface {}{
324+ requestBody := map [string ]interface {}{
310325 "ref" : ref ,
311326 "inputs" : providedInputs ,
312- })
327+ }
328+
329+ // TODO workflowDispatchRunDetailsCleanup
330+ // We will have to always set the `return_run_details` field to true, unless
331+ // we opt into the the new REST API version, which will probably return the
332+ // details by default.
333+ if features .DispatchRunDetails {
334+ requestBody ["return_run_details" ] = true
335+ }
336+
337+ requestByte , err := json .Marshal (requestBody )
313338 if err != nil {
314339 return fmt .Errorf ("failed to serialize workflow inputs: %w" , err )
315340 }
316341
317342 body := bytes .NewReader (requestByte )
318343
319- err = client .REST (repo .RepoHost (), "POST" , path , body , nil )
344+ var response struct {
345+ WorkflowRunID int64 `json:"workflow_run_id"`
346+ RunURL string `json:"run_url"`
347+ HtmlURL string `json:"html_url"`
348+ }
349+
350+ // Note that the workflow dispatch endpoint used to return 204 No Content
351+ // (with no body, obviously). Now it's possible for the endpoint to also
352+ // return 200 OK with created run details. So, we have to handle both cases
353+ // because old GHE versions still return 204. Even on github.com, we
354+ // may still get 204 for any reason.
355+ //
356+ // Our REST client library is smart enough to ignore JSON unmarshal when it
357+ // receives 204, so we're safe here anyway.
358+ //
359+ // As a related note, the new REST API version (which will come with breaking
360+ // changes) will probably default to return 200 + run details.
361+ err = client .REST (repo .RepoHost (), "POST" , path , body , & response )
320362 if err != nil {
321363 return fmt .Errorf ("could not create workflow dispatch event: %w" , err )
322364 }
323365
324366 if opts .IO .IsStdoutTTY () {
325- out := opts .IO .Out
326367 cs := opts .IO .ColorScheme ()
327- fmt .Fprintf (out , "%s Created workflow_dispatch event for %s at %s\n " ,
368+ fmt .Fprintf (opts . IO . Out , "%s Created workflow_dispatch event for %s at %s\n " ,
328369 cs .SuccessIcon (), cs .Cyan (workflow .Base ()), cs .Bold (ref ))
329370
330- fmt .Fprintln (out )
371+ if response .HtmlURL != "" {
372+ fmt .Fprintln (opts .IO .Out , response .HtmlURL )
373+ }
331374
332- fmt .Fprintf (out , "To see runs for this workflow, try: %s\n " ,
375+ fmt .Fprintln (opts .IO .Out )
376+
377+ if response .WorkflowRunID != 0 {
378+ fmt .Fprintf (opts .IO .Out , "To see the created workflow run, try: %s\n " ,
379+ cs .Boldf ("gh run view %d" , response .WorkflowRunID ))
380+ }
381+
382+ fmt .Fprintf (opts .IO .Out , "To see runs for this workflow, try: %s\n " ,
333383 cs .Boldf ("gh run list --workflow=%q" , workflow .Base ()))
384+ } else {
385+ if response .HtmlURL != "" {
386+ fmt .Fprintln (opts .IO .Out , response .HtmlURL )
387+ }
334388 }
335389
336390 return nil
0 commit comments