Skip to content

Commit 5e94f52

Browse files
Merge pull request #38 from actionforge/welcome
Add debug subcommand and interactive welcome menu
2 parents 4b58772 + 398d150 commit 5e94f52

File tree

13 files changed

+278
-74
lines changed

13 files changed

+278
-74
lines changed

cmd/cmd_debug.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package cmd
2+
3+
import (
4+
"os"
5+
6+
"github.com/actionforge/actrun-cli/sessions"
7+
"github.com/actionforge/actrun-cli/utils"
8+
"github.com/spf13/cobra"
9+
)
10+
11+
var (
12+
flagDebugSessionToken string
13+
flagDebugConfigFile string
14+
)
15+
16+
var cmdDebug = &cobra.Command{
17+
Use: "debug",
18+
Short: "Connect to the web app with a session token",
19+
Run: cmdDebugRun,
20+
}
21+
22+
func init() {
23+
cmdRoot.AddCommand(cmdDebug)
24+
25+
cmdDebug.Flags().StringVar(&flagDebugSessionToken, "session-token", envOr("ACT_SESSION_TOKEN", ""), "Session token from your browser (env: ACT_SESSION_TOKEN)")
26+
cmdDebug.Flags().StringVar(&flagDebugConfigFile, "config-file", "", "The config file to use")
27+
}
28+
29+
func cmdDebugRun(cmd *cobra.Command, args []string) {
30+
err := sessions.RunSessionMode(flagDebugConfigFile, "", flagDebugSessionToken, "flag")
31+
if err != nil {
32+
utils.LogErr.Print(err.Error())
33+
os.Exit(1)
34+
}
35+
}

cmd/cmd_root.go

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func cmdRootRun(cmd *cobra.Command, args []string) {
180180
return
181181
}
182182

183-
// if we still have no graph file, go to Session Mode
183+
// if we still have no graph file, show the interactive menu or go to Session Mode
184184
if finalGraphFile == "" || finalCreateDebugSession {
185185
trapfn := func() {
186186
if mousetrap.StartedByExplorer() {
@@ -189,14 +189,54 @@ func cmdRootRun(cmd *cobra.Command, args []string) {
189189
}
190190
}
191191

192-
err := sessions.RunSessionMode(finalConfigFile, finalGraphFile, finalSessionToken, finalConfigValueSource)
193-
if err != nil {
194-
utils.LogErr.Print(err.Error())
192+
// If a session token was explicitly provided or debug session requested,
193+
// go straight to session mode. Otherwise, show the interactive menu.
194+
if finalSessionToken != "" || finalCreateDebugSession {
195+
err := sessions.RunSessionMode(finalConfigFile, finalGraphFile, finalSessionToken, finalConfigValueSource)
196+
if err != nil {
197+
utils.LogErr.Print(err.Error())
198+
trapfn()
199+
os.Exit(1)
200+
}
195201
trapfn()
196-
os.Exit(1)
202+
return
203+
}
204+
205+
sessions.PrintWelcomeMessage()
206+
207+
if !sessions.IsInteractive() {
208+
sessions.PrintUsageHints()
209+
return
210+
}
211+
212+
choice := sessions.PromptMainMenu()
213+
214+
switch choice {
215+
case 1: // Run a graph
216+
graphFile := sessions.PromptGraphFile()
217+
if graphFile == "" {
218+
return
219+
}
220+
finalGraphFile = graphFile
221+
// Fall through to graph execution below.
222+
223+
case 2: // Connect to web debug session (session token)
224+
err := sessions.RunSessionMode(finalConfigFile, "", "", "")
225+
if err != nil {
226+
utils.LogErr.Print(err.Error())
227+
trapfn()
228+
os.Exit(1)
229+
}
230+
trapfn()
231+
return
232+
233+
case 3: // Connect as agent
234+
fmt.Println("Agent mode is not yet implemented.")
235+
return
236+
237+
default:
238+
return
197239
}
198-
trapfn()
199-
return
200240
}
201241

202242
var err error

github/server/cache_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,10 @@ func TestCachePrefixMatch(t *testing.T) {
154154
}
155155

156156
// Download and verify it's one of the two entries (the newest)
157-
getResp, _ := http.Get(dlResp.SignedDownloadURL)
157+
getResp, err := http.Get(dlResp.SignedDownloadURL)
158+
if err != nil {
159+
t.Fatal(err)
160+
}
158161
defer getResp.Body.Close()
159162
data, _ := io.ReadAll(getResp.Body)
160163
if string(data) != "node-modules-bbb" {
@@ -204,7 +207,10 @@ func TestCacheOverwrite(t *testing.T) {
204207
"metadata": map[string]string{"scope": scope},
205208
})
206209
dlResp := decodeResponse[GetCacheEntryDownloadURLResponse](t, resp)
207-
getResp, _ := http.Get(dlResp.SignedDownloadURL)
210+
getResp, err := http.Get(dlResp.SignedDownloadURL)
211+
if err != nil {
212+
t.Fatal(err)
213+
}
208214
defer getResp.Body.Close()
209215
data, _ := io.ReadAll(getResp.Body)
210216
if string(data) != "new-data" {

github/server/legacy_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,10 @@ func TestLegacyChunkedUpload(t *testing.T) {
191191

192192
dlReq, _ := http.NewRequest("GET", contentLocation, nil)
193193
dlReq.Header.Set("Authorization", "Bearer test-token")
194-
dlResp, _ := http.DefaultClient.Do(dlReq)
194+
dlResp, err := http.DefaultClient.Do(dlReq)
195+
if err != nil {
196+
t.Fatal(err)
197+
}
195198
defer dlResp.Body.Close()
196199
data, _ := io.ReadAll(dlResp.Body)
197200
expected := append(chunk1, chunk2...)
@@ -249,7 +252,10 @@ func TestLegacyGzipRoundtrip(t *testing.T) {
249252
client := &http.Client{Transport: transport}
250253
dlReq, _ := http.NewRequest("GET", filesResult.Value[0]["contentLocation"].(string), nil)
251254
dlReq.Header.Set("Authorization", "Bearer test-token")
252-
dlResp, _ := client.Do(dlReq)
255+
dlResp, err := client.Do(dlReq)
256+
if err != nil {
257+
t.Fatal(err)
258+
}
253259
defer dlResp.Body.Close()
254260

255261
if dlResp.Header.Get("Content-Encoding") != "gzip" {

github/server/server_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,10 @@ func TestChunkedUpload(t *testing.T) {
264264
"name": "chunked-artifact",
265265
})
266266
urlResp := decodeResponse[GetSignedArtifactURLResponse](t, resp)
267-
dlResp, _ := http.Get(urlResp.SignedURL)
267+
dlResp, err := http.Get(urlResp.SignedURL)
268+
if err != nil {
269+
t.Fatal(err)
270+
}
268271
defer dlResp.Body.Close()
269272
data, _ := io.ReadAll(dlResp.Body)
270273
expected := append(append(chunk1, chunk2...), chunk3...)
@@ -639,7 +642,10 @@ func TestMigrateArtifact(t *testing.T) {
639642
"name": "migrated-artifact",
640643
})
641644
urlResp := decodeResponse[GetSignedArtifactURLResponse](t, resp)
642-
dlResp, _ := http.Get(urlResp.SignedURL)
645+
dlResp, err := http.Get(urlResp.SignedURL)
646+
if err != nil {
647+
t.Fatal(err)
648+
}
643649
defer dlResp.Body.Close()
644650
data, _ := io.ReadAll(dlResp.Body)
645651
if !bytes.Equal(data, blobContent) {

go.mod

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ require (
1010
github.com/aws/aws-sdk-go-v2/credentials v1.19.6
1111
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.20.18
1212
github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3
13+
github.com/charmbracelet/huh v1.0.0
14+
github.com/charmbracelet/lipgloss v1.1.0
1315
github.com/containerd/errdefs v1.0.0
1416
github.com/docker/docker v28.5.2+incompatible
1517
github.com/fatih/color v1.18.0
@@ -21,6 +23,7 @@ require (
2123
github.com/inconshreveable/mousetrap v1.1.0
2224
github.com/joho/godotenv v1.5.1
2325
github.com/mark3labs/mcp-go v0.44.0
26+
github.com/mattn/go-isatty v0.0.20
2427
github.com/perforce/p4go v1.20252.2872356
2528
github.com/pkg/errors v0.9.1
2629
github.com/rhysd/actionlint v1.7.10
@@ -54,6 +57,7 @@ require (
5457
dario.cat/mergo v1.0.2 // indirect
5558
github.com/Microsoft/go-winio v0.6.2 // indirect
5659
github.com/ProtonMail/go-crypto v1.3.0 // indirect
60+
github.com/atotto/clipboard v0.1.4 // indirect
5761
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect
5862
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.16 // indirect
5963
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect
@@ -69,11 +73,20 @@ require (
6973
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.12 // indirect
7074
github.com/aws/aws-sdk-go-v2/service/sts v1.41.5 // indirect
7175
github.com/aws/smithy-go v1.24.2 // indirect
76+
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
7277
github.com/bahlo/generic-list-go v0.2.0 // indirect
7378
github.com/bmatcuk/doublestar/v4 v4.9.1 // indirect
74-
github.com/buger/jsonparser v1.1.1 // indirect
79+
github.com/buger/jsonparser v1.1.2 // indirect
80+
github.com/catppuccin/go v0.3.0 // indirect
7581
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
7682
github.com/cespare/xxhash/v2 v2.3.0 // indirect
83+
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7 // indirect
84+
github.com/charmbracelet/bubbletea v1.3.6 // indirect
85+
github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect
86+
github.com/charmbracelet/x/ansi v0.9.3 // indirect
87+
github.com/charmbracelet/x/cellbuf v0.0.13 // indirect
88+
github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
89+
github.com/charmbracelet/x/term v0.2.1 // indirect
7790
github.com/clipperhouse/stringish v0.1.1 // indirect
7891
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
7992
github.com/cloudflare/circl v1.6.3 // indirect
@@ -84,7 +97,9 @@ require (
8497
github.com/dlclark/regexp2 v1.11.5 // indirect
8598
github.com/docker/go-connections v0.5.0 // indirect
8699
github.com/docker/go-units v0.5.0 // indirect
100+
github.com/dustin/go-humanize v1.0.1 // indirect
87101
github.com/emirpasic/gods v1.18.1 // indirect
102+
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
88103
github.com/felixge/httpsnoop v1.0.4 // indirect
89104
github.com/gage-technologies/mistral-go v1.1.0 // indirect
90105
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
@@ -112,21 +127,27 @@ require (
112127
github.com/kevinburke/ssh_config v1.4.0 // indirect
113128
github.com/klauspost/compress v1.18.2 // indirect
114129
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
130+
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
115131
github.com/mailru/easyjson v0.7.7 // indirect
116132
github.com/mattn/go-colorable v0.1.14 // indirect
117-
github.com/mattn/go-isatty v0.0.20 // indirect
133+
github.com/mattn/go-localereader v0.0.1 // indirect
118134
github.com/mattn/go-runewidth v0.0.19 // indirect
119135
github.com/mattn/go-shellwords v1.0.12 // indirect
120136
github.com/mitchellh/go-homedir v1.1.0 // indirect
137+
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
121138
github.com/mitchellh/mapstructure v1.5.0 // indirect
122139
github.com/moby/docker-image-spec v1.3.1 // indirect
123140
github.com/moby/sys/atomicwriter v0.1.0 // indirect
124141
github.com/montanaflynn/stats v0.7.1 // indirect
142+
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
143+
github.com/muesli/cancelreader v0.2.2 // indirect
144+
github.com/muesli/termenv v0.16.0 // indirect
125145
github.com/opencontainers/go-digest v1.0.0 // indirect
126146
github.com/opencontainers/image-spec v1.1.1 // indirect
127147
github.com/pjbgf/sha1cd v0.5.0 // indirect
128148
github.com/pkoukk/tiktoken-go v0.1.8 // indirect
129149
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
150+
github.com/rivo/uniseg v0.4.7 // indirect
130151
github.com/robfig/cron/v3 v3.0.1 // indirect
131152
github.com/ryanuber/go-glob v1.0.0 // indirect
132153
github.com/sergi/go-diff v1.4.0 // indirect
@@ -137,6 +158,7 @@ require (
137158
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
138159
github.com/xdg-go/scram v1.2.0 // indirect
139160
github.com/xdg-go/stringprep v1.0.4 // indirect
161+
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
140162
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
141163
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
142164
go.opentelemetry.io/auto/sdk v1.2.1 // indirect

0 commit comments

Comments
 (0)