diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 53c26aa8..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "configurations": [ - { - "name": "Debug CLI", - "type": "go", - "debugAdapter": "dlv-dap", - "request": "attach", - "mode": "remote", - "remotePath": "${workspaceFolder}", - "port": 2345, - "host": "127.0.0.1", - "preLaunchTask": "Run headless dlv" - } - ] -} \ No newline at end of file diff --git a/.vscode/launch.template.json b/.vscode/launch.template.json new file mode 100644 index 00000000..76f49643 --- /dev/null +++ b/.vscode/launch.template.json @@ -0,0 +1,23 @@ +{ + "configurations": [ + { + "name": "speakeasy run", + "type": "go", + "request": "launch", + "program": "main.go", + "cwd": "/tmp/studio-test-6840674974721771490", + "args": ["run", "--launch-studio"] + }, + { + "name": "Debug CLI headless", + "type": "go", + "debugAdapter": "dlv-dap", + "request": "attach", + "mode": "remote", + "remotePath": "${workspaceFolder}", + "port": 2345, + "host": "127.0.0.1", + "preLaunchTask": "Run headless dlv" + } + ] +} diff --git a/internal/run/source.go b/internal/run/source.go index 1ffbe89e..8159f470 100644 --- a/internal/run/source.go +++ b/internal/run/source.go @@ -71,6 +71,9 @@ func (w *Workflow) RunSource(ctx context.Context, parentStep *workflowTracking.W Source: sourceID, Diagnosis: suggestions.Diagnosis{}, } + defer func() { + w.OnSourceResult(sourceRes) + }() rulesetToUse := "speakeasy-generation" if source.Ruleset != nil { @@ -226,6 +229,7 @@ func (w *Workflow) RunSource(ctx context.Context, parentStep *workflowTracking.W } currentDocument = overlayLocation + overlayStep.Succeed() } sourceRes.OutputPath = currentDocument @@ -240,12 +244,6 @@ func (w *Workflow) RunSource(ctx context.Context, parentStep *workflowTracking.W } } - sourceRes.Diagnosis, err = suggest.Diagnose(ctx, currentDocument) - if err != nil { - w.OnSourceResult(sourceRes) - return "", sourceRes, err - } - // If the source has a previous tracked revision, compute changes against it if w.lockfileOld != nil && !w.SkipChangeReport { if targetLockOld, ok := w.lockfileOld.Targets[targetID]; ok && !utils.IsZeroTelemetryOrganization(ctx) { @@ -256,6 +254,7 @@ func (w *Workflow) RunSource(ctx context.Context, parentStep *workflowTracking.W } } } + if sourceRes.ChangeReport == nil { // If we failed to compute changes, always generate the SDK _ = versioning.AddVersionReport(ctx, versioning.VersionReport{ @@ -267,15 +266,21 @@ func (w *Workflow) RunSource(ctx context.Context, parentStep *workflowTracking.W if !w.SkipLinting { sourceRes.LintResult, err = w.validateDocument(ctx, rootStep, sourceID, currentDocument, rulesetToUse, w.ProjectDir) - w.OnSourceResult(sourceRes) if err != nil { return "", sourceRes, &LintingError{Err: err, Document: currentDocument} } } + step := rootStep.NewSubstep("Diagnosing OpenAPI") + sourceRes.Diagnosis, err = suggest.Diagnose(ctx, currentDocument) + if err != nil { + step.Fail() + return "", sourceRes, err + } + step.Succeed() + rootStep.SucceedWorkflow() - w.OnSourceResult(sourceRes) return currentDocument, sourceRes, nil } @@ -367,6 +372,8 @@ func (w *Workflow) validateDocument(ctx context.Context, parentStep *workflowTra w.validatedDocuments = append(w.validatedDocuments, schemaPath) + step.SucceedWorkflow() + return res, err } diff --git a/internal/studio/launchStudio.go b/internal/studio/launchStudio.go index e5878780..daabbfb8 100644 --- a/internal/studio/launchStudio.go +++ b/internal/studio/launchStudio.go @@ -11,6 +11,7 @@ import ( "os" "os/signal" "syscall" + "time" "github.com/speakeasy-api/speakeasy-core/auth" @@ -107,14 +108,20 @@ func authMiddleware(secret string, next http.Handler) http.Handler { func handler(h func(context.Context, http.ResponseWriter, *http.Request) error) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + start := time.Now() id := generateRequestID() - log.From(r.Context()).Info("handling request", zap.String("method", r.Method), zap.String("path", r.URL.Path), zap.String("request_id", id)) + method := fmt.Sprintf("%-6s", r.Method) // Fixed width 6 characters + path := fmt.Sprintf("%-21s", r.URL.Path) // Fixed width 21 characters + base := fmt.Sprintf("%s %s %s", id, method, path) + log.From(r.Context()).Info(fmt.Sprintf("%s started", base)) ctx := r.Context() if err := h(ctx, w, r); err != nil { - log.From(ctx).Error("error handling request", zap.String("method", r.Method), zap.String("path", r.URL.Path), zap.String("request_id", id), zap.Error(err)) + log.From(ctx).Error(fmt.Sprintf("%s failed: %v", base, err)) respondJSONError(ctx, w, err) + return } - log.From(ctx).Info("request handled", zap.String("method", r.Method), zap.String("path", r.URL.Path), zap.String("request_id", id)) + duration := time.Since(start) + log.From(ctx).Info(fmt.Sprintf("%s completed in %s", base, duration)) } } @@ -198,8 +205,9 @@ func respondJSONError(ctx context.Context, w http.ResponseWriter, err error) { } } +var counter int + func generateRequestID() string { - bytes := make([]byte, 4) - rand.Read(bytes) // Generate random bytes - return hex.EncodeToString(bytes) + counter++ + return fmt.Sprintf("%03d", counter) } diff --git a/internal/studio/sdk/.speakeasy/workflow.lock b/internal/studio/sdk/.speakeasy/workflow.lock index 28fe345d..bf926ace 100644 --- a/internal/studio/sdk/.speakeasy/workflow.lock +++ b/internal/studio/sdk/.speakeasy/workflow.lock @@ -1,8 +1,8 @@ -speakeasyVersion: 0.0.1 +speakeasyVersion: 1.377.1 sources: SpeakeasyStudio-OAS: sourceNamespace: speakeasy-studio-oas - sourceRevisionDigest: sha256:3e9ceaef4799d1b9736195c5a7e23e8beb52cccb308f48cc0f101282acb999b9 + sourceRevisionDigest: sha256:22959a5102700320cb02912c08183eb65b458b4bedb0323bb0ed5ef6d83380c7 sourceBlobDigest: sha256:45f804139bfdc947479c244b5e1d7f3a18b586e760766f176587328c5ed36025 tags: - latest @@ -16,7 +16,7 @@ targets: speakeasy-studio: source: SpeakeasyStudio-OAS sourceNamespace: speakeasy-studio-oas - sourceRevisionDigest: sha256:3e9ceaef4799d1b9736195c5a7e23e8beb52cccb308f48cc0f101282acb999b9 + sourceRevisionDigest: sha256:22959a5102700320cb02912c08183eb65b458b4bedb0323bb0ed5ef6d83380c7 sourceBlobDigest: sha256:45f804139bfdc947479c244b5e1d7f3a18b586e760766f176587328c5ed36025 outLocation: /Users/da/code/speakeasy-cli/internal/studio/sdk spekaeasy-studio: diff --git a/internal/studio/studioHandlers.go b/internal/studio/studioHandlers.go index 537db26a..5204ee83 100644 --- a/internal/studio/studioHandlers.go +++ b/internal/studio/studioHandlers.go @@ -288,9 +288,14 @@ func (h *StudioHandlers) convertLastRunResult(ctx context.Context, step string) WorkingDirectory: h.WorkflowRunner.ProjectDir, Step: step, IsPartial: step != "end", + Took: h.WorkflowRunner.Duration.Milliseconds(), } - ret.Took = h.WorkflowRunner.Duration.Milliseconds() + wf, err := convertWorkflowToComponentsWorkflow(*h.WorkflowRunner.GetWorkflowFile()) + if err != nil { + return &ret, fmt.Errorf("error converting workflow to components.Workflow: %w", err) + } + ret.Workflow = wf if h.WorkflowRunner.Error != nil { errStr := h.WorkflowRunner.Error.Error() @@ -341,12 +346,6 @@ func (h *StudioHandlers) convertLastRunResult(ctx context.Context, step string) ret.SourceResult = *sourceResponse } - wf, err := convertWorkflowToComponentsWorkflow(*h.WorkflowRunner.GetWorkflowFile()) - if err != nil { - return &ret, fmt.Errorf("error converting workflow to components.Workflow: %w", err) - } - ret.Workflow = wf - return &ret, nil } diff --git a/internal/suggest/suggest.go b/internal/suggest/suggest.go index e9b349e7..7925baa4 100644 --- a/internal/suggest/suggest.go +++ b/internal/suggest/suggest.go @@ -3,14 +3,15 @@ package suggest import ( "context" "fmt" - "github.com/speakeasy-api/speakeasy-core/suggestions" - "gopkg.in/yaml.v3" "io" "io/ioutil" "net/http" "strings" "time" + "github.com/speakeasy-api/speakeasy-core/suggestions" + "gopkg.in/yaml.v3" + "github.com/charmbracelet/lipgloss" "github.com/speakeasy-api/openapi-overlay/pkg/overlay" "github.com/speakeasy-api/speakeasy-client-sdk-go/v3/pkg/models/shared"