@@ -72,6 +72,19 @@ func fakeRunV3(id, projectID, phase, outcome, branch, revision string) map[strin
7272 if outcome != "" {
7373 attrs ["current_outcome" ] = outcome
7474 }
75+ // The event VCS carries the commit (subject, url, author) — the only source
76+ // the client reads it from. Only runs that resolved a revision have one.
77+ eventVCS := map [string ]any {
78+ "branch" : branch ,
79+ "revision" : revision ,
80+ }
81+ if revision != "" {
82+ eventVCS ["commit" ] = map [string ]any {
83+ "subject" : "Fix the widget" ,
84+ "url" : "https://github.com/testorg/testrepo/commit/" + revision ,
85+ "author" : map [string ]any {"name" : "Ada Lovelace" , "login" : "ada" },
86+ }
87+ }
7588 return map [string ]any {
7689 "id" : id ,
7790 "attributes" : attrs ,
@@ -80,10 +93,7 @@ func fakeRunV3(id, projectID, phase, outcome, branch, revision string) map[strin
8093 // attributes.vcs above is retained for legacy clients.
8194 "event" : map [string ]any {
8295 "attributes" : map [string ]any {
83- "vcs" : map [string ]any {
84- "branch" : branch ,
85- "revision" : revision ,
86- },
96+ "vcs" : eventVCS ,
8797 },
8898 },
8999 "trigger" : map [string ]any {
@@ -285,6 +295,10 @@ func TestRunGet_ByID_JSON(t *testing.T) {
285295 assert .Check (t , cmp .Equal (out ["phase" ], "ended" ))
286296 assert .Check (t , cmp .Equal (out ["current_outcome" ], "succeeded" ))
287297
298+ commit := out ["commit" ].(map [string ]any )
299+ assert .Check (t , cmp .Equal (commit ["subject" ], "Fix the widget" ))
300+ assert .Check (t , cmp .Equal (commit ["author_name" ], "Ada Lovelace" ))
301+
288302 wfs := out ["workflows" ].([]any )
289303 assert .Check (t , cmp .Len (wfs , 1 ))
290304 jobs := wfs [0 ].(map [string ]any )["jobs" ].([]any )
@@ -461,6 +475,33 @@ func TestRunGet_ProjectDefaultsBranchToMain(t *testing.T) {
461475 assert .Check (t , cmp .Equal (out ["id" ], mainRunID )) // the main-branch run, not feature
462476}
463477
478+ // TestRunGet_NoInteractive_SkipsPicker confirms --no-interactive bypasses the
479+ // picker even in a PTY: a session that would otherwise open the run picker
480+ // instead resolves the latest run and prints its summary, which carries the
481+ // run's full UUID (the picker's first screen never does).
482+ func TestRunGet_NoInteractive_SkipsPicker (t * testing.T ) {
483+ fake := fakes .NewCircleCI (t )
484+ addProjectBySlug (fake , testSlug , runTestProjectID )
485+ runID := "e0000000-0000-4000-8000-0000000000c1"
486+ fake .AddRunV3 (runID , runTestProjectID , fakeRunV3 (runID , runTestProjectID , "ended" , "succeeded" , "main" , "abc1234def5678" ))
487+
488+ env := testenv .New (t )
489+ env .Token = testToken
490+ env .CircleCIURL = fake .URL ()
491+
492+ console := binary .RunCLIInteractive (t , binary.RunOpts {
493+ Binary : binaryPath ,
494+ Args : []string {"run" , "get" , "--project" , testSlug , "--branch" , "main" , "--no-interactive" },
495+ Env : env .Environ (),
496+ WorkDir : t .TempDir (),
497+ })
498+
499+ // The run summary prints the run's full UUID; the picker would show
500+ // "Select a run" instead.
501+ _ , err := console .ExpectString (runID )
502+ assert .NilError (t , err )
503+ }
504+
464505// --- run get (interactive picker) ---
465506
466507const (
@@ -819,7 +860,7 @@ func TestRunGet_Interactive_Back(t *testing.T) {
819860
820861 // The run picker is shown again rather than the program exiting; its option
821862 // lines are rewritten in full, so the run row reappears.
822- _ , err = console .ExpectString ("abc1234 [main]" )
863+ _ , err = console .ExpectString ("[main] abc1234 " )
823864 assert .NilError (t , err )
824865 _ , err = console .Send ("\r " )
825866 assert .NilError (t , err )
@@ -851,7 +892,7 @@ func TestRunGet_Interactive_SwitchBranch(t *testing.T) {
851892 console := startRunGetInteractive (t , env )
852893
853894 // Scoped to main: the main run shows, the feature run does not yet.
854- _ , err := console .ExpectString ("abc1234 [main]" )
895+ _ , err := console .ExpectString ("[main] abc1234 " )
855896 assert .NilError (t , err )
856897
857898 // Cycle main → all branches (no default branch is known here; the cycle is
@@ -864,7 +905,7 @@ func TestRunGet_Interactive_SwitchBranch(t *testing.T) {
864905 assert .NilError (t , err )
865906
866907 // The feature-branch run is now listed.
867- _ , err = console .ExpectString ("facefee [feature]" )
908+ _ , err = console .ExpectString ("[feature] facefee " )
868909 assert .NilError (t , err )
869910
870911 // esc on the first picker quits, so the program exits cleanly.
@@ -882,7 +923,7 @@ func TestRunGet_Interactive_SwitchToMyRuns(t *testing.T) {
882923 console := startRunGetInteractive (t , env )
883924
884925 // Scoped to main: the main run shows, the my-runs entry does not yet.
885- _ , err := console .ExpectString ("abc1234 [main]" )
926+ _ , err := console .ExpectString ("[main] abc1234 " )
886927 assert .NilError (t , err )
887928
888929 switchSeq := "\x1b [Z" // shift+tab (CSI Z)
@@ -892,7 +933,7 @@ func TestRunGet_Interactive_SwitchToMyRuns(t *testing.T) {
892933 // main → all branches → my runs.
893934 _ , err = console .Send (switchSeq )
894935 assert .NilError (t , err )
895- _ , err = console .ExpectString ("facefee [feature]" )
936+ _ , err = console .ExpectString ("[feature] facefee " )
896937 assert .NilError (t , err )
897938 _ , err = console .Send (switchSeq )
898939 assert .NilError (t , err )
@@ -902,7 +943,7 @@ func TestRunGet_Interactive_SwitchToMyRuns(t *testing.T) {
902943 // (The picker title also names the scope "[my runs]", asserted in the ui
903944 // package's flow test — the PTY renderer diffs the title line so it does not
904945 // appear contiguously here.)
905- _ , err = console .ExpectString ("cafed00 [testorg/testrepo:mine]" )
946+ _ , err = console .ExpectString ("[testorg/testrepo:mine] cafed00 " )
906947 assert .NilError (t , err )
907948
908949 // esc on the first picker quits, so the program exits cleanly.
@@ -925,7 +966,7 @@ func TestRunGet_Interactive_NoProject(t *testing.T) {
925966
926967 // The picker opens straight on the user's cross-project runs, its project
927968 // folded into the ref bracket as "[project:branch]".
928- _ , err := console .ExpectString ("cafed00 [testorg/testrepo:mine]" )
969+ _ , err := console .ExpectString ("[testorg/testrepo:mine] cafed00 " )
929970 assert .NilError (t , err )
930971
931972 // esc on the first picker quits, so the program exits cleanly.
@@ -946,7 +987,7 @@ func TestRunGet_Interactive_ProjectNoBranch(t *testing.T) {
946987 })
947988
948989 // The defaulted main branch's run loads (not the feature-branch one).
949- _ , err := console .ExpectString ("abc1234 [main]" )
990+ _ , err := console .ExpectString ("[main] abc1234 " )
950991 assert .NilError (t , err )
951992
952993 // esc on the first picker quits, so the program exits cleanly.
@@ -963,7 +1004,7 @@ func TestRunGet_Interactive_FilterStatus(t *testing.T) {
9631004 env := setupRunGetInteractiveFake (t )
9641005 console := startRunGetInteractive (t , env )
9651006
966- _ , err := console .ExpectString ("abc1234 [main]" )
1007+ _ , err := console .ExpectString ("[main] abc1234 " )
9671008 assert .NilError (t , err )
9681009
9691010 // all statuses → canceled (no canceled runs on main). Match a contiguous
@@ -988,7 +1029,7 @@ func TestRunGet_Interactive_FilterStatusMyRuns(t *testing.T) {
9881029 env := setupRunGetInteractiveFake (t )
9891030 console := startRunGetInteractive (t , env )
9901031
991- _ , err := console .ExpectString ("abc1234 [main]" )
1032+ _ , err := console .ExpectString ("[main] abc1234 " )
9921033 assert .NilError (t , err )
9931034
9941035 switchSeq := "\x1b [Z" // shift+tab (CSI Z)
@@ -998,11 +1039,11 @@ func TestRunGet_Interactive_FilterStatusMyRuns(t *testing.T) {
9981039 // main → all branches → my runs.
9991040 _ , err = console .Send (switchSeq )
10001041 assert .NilError (t , err )
1001- _ , err = console .ExpectString ("facefee [feature]" )
1042+ _ , err = console .ExpectString ("[feature] facefee " )
10021043 assert .NilError (t , err )
10031044 _ , err = console .Send (switchSeq )
10041045 assert .NilError (t , err )
1005- _ , err = console .ExpectString ("cafed00 [testorg/testrepo:mine]" )
1046+ _ , err = console .ExpectString ("[testorg/testrepo:mine] cafed00 " )
10061047 assert .NilError (t , err )
10071048
10081049 // my runs, all statuses → canceled: the one user run succeeded, so the
@@ -1218,6 +1259,12 @@ func TestRunList_JSON(t *testing.T) {
12181259 assert .Check (t , cmp .Equal (out [0 ]["current_outcome" ], "succeeded" ))
12191260 assert .Check (t , cmp .Equal (out [1 ]["current_outcome" ], "failed" ))
12201261
1262+ // The JSON carries the full commit detail (the markdown shows only the subject).
1263+ commit := out [0 ]["commit" ].(map [string ]any )
1264+ assert .Check (t , cmp .Equal (commit ["subject" ], "Fix the widget" ))
1265+ assert .Check (t , cmp .Equal (commit ["author_name" ], "Ada Lovelace" ))
1266+ assert .Check (t , cmp .Equal (commit ["author_login" ], "ada" ))
1267+
12211268 assert .Check (t , golden .String (result .Stdout , t .Name ()+ ".json" ))
12221269}
12231270
0 commit comments