Skip to content

Commit 10c979a

Browse files
committed
feat: add secret /debug page matching CLI output
1 parent dcdaa71 commit 10c979a

File tree

1 file changed

+44
-37
lines changed

1 file changed

+44
-37
lines changed

cmd/plan/main.go

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package main
22

33
import (
4+
"bytes"
45
"encoding/xml"
56
"flag"
67
"fmt"
8+
"io"
79
"log"
810
"net/http"
911
"os"
@@ -147,87 +149,81 @@ func main() {
147149
}
148150

149151
func debugCmd(ctx *PlanContext) {
150-
fmt.Println("=== Plan Debug Info ===")
152+
writeDebugInfo(os.Stdout, ctx)
153+
}
154+
155+
func writeDebugInfo(w io.Writer, ctx *PlanContext) {
156+
fmt.Fprintln(w, "=== Plan Debug Info ===")
151157

152158
// Build Info
153-
fmt.Println("\n-- Build Information --")
159+
fmt.Fprintln(w, "\n-- Build Information --")
154160
if info, ok := debug.ReadBuildInfo(); ok {
155-
fmt.Printf("Go Version: %s\n", info.GoVersion)
161+
fmt.Fprintf(w, "Go Version: %s\n", info.GoVersion)
156162
for _, setting := range info.Settings {
157163
if setting.Key == "vcs.revision" {
158-
fmt.Printf("Git Revision: %s\n", setting.Value)
164+
fmt.Fprintf(w, "Git Revision: %s\n", setting.Value)
159165
}
160166
if setting.Key == "vcs.time" {
161-
fmt.Printf("Git Time: %s\n", setting.Value)
167+
fmt.Fprintf(w, "Git Time: %s\n", setting.Value)
162168
}
163169
if setting.Key == "vcs.modified" && setting.Value == "true" {
164-
fmt.Println("Git Status: dirty")
170+
fmt.Fprintln(w, "Git Status: dirty")
165171
}
166172
}
167173
} else {
168-
fmt.Println("Build info not available.")
174+
fmt.Fprintln(w, "Build info not available.")
169175
}
170-
fmt.Printf("OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
176+
fmt.Fprintf(w, "OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
171177

172178
// Context Info
173-
fmt.Println("\n-- Context --")
179+
fmt.Fprintln(w, "\n-- Context --")
174180
cwd, _ := os.Getwd()
175-
fmt.Printf("Working Dir: %s\n", cwd)
176-
fmt.Printf("Plan Dir: %s\n", ctx.PlanDir)
177-
fmt.Printf("Plan File: %s\n", ctx.PlanFile)
178-
fmt.Printf("Output Dir: %s\n", ctx.OutputDir)
179-
fmt.Printf("Creation: %s\n", ctx.CreationTime.Format(time.RFC3339))
181+
fmt.Fprintf(w, "Working Dir: %s\n", cwd)
182+
fmt.Fprintf(w, "Plan Dir: %s\n", ctx.PlanDir)
183+
fmt.Fprintf(w, "Plan File: %s\n", ctx.PlanFile)
184+
fmt.Fprintf(w, "Output Dir: %s\n", ctx.OutputDir)
185+
fmt.Fprintf(w, "Creation: %s\n", ctx.CreationTime.Format(time.RFC3339))
180186

181187
// Configuration
182-
fmt.Println("\n-- Configuration --")
183-
fmt.Printf("Username: %s\n", ctx.Config.Username)
184-
fmt.Printf("FullName: %s\n", ctx.Config.FullName)
185-
fmt.Printf("Title: %s\n", ctx.Config.Title)
186-
fmt.Printf("Timezone: %s\n", ctx.Config.Timezone)
188+
fmt.Fprintln(w, "\n-- Configuration --")
189+
fmt.Fprintf(w, "Username: %s\n", ctx.Config.Username)
190+
fmt.Fprintf(w, "FullName: %s\n", ctx.Config.FullName)
191+
fmt.Fprintf(w, "Title: %s\n", ctx.Config.Title)
192+
fmt.Fprintf(w, "Timezone: %s\n", ctx.Config.Timezone)
187193

188194
tmplStatus := "Default (Embedded)"
189195
if len(ctx.Template) > 0 {
190-
// Simple check to see if it matches default is hard since default is embedded in another package
191-
// But if initContext loaded it from disk, we know.
192-
// Actually initContext sets ctx.Template to file content if found, else empty string?
193-
// Re-reading initContext:
194-
// tmplContent is set ONLY if os.ReadFile succeeds.
195-
// But render.New defaults if passed empty string.
196-
// So if ctx.Template is NOT empty, it was loaded from file.
197196
tmplStatus = "Custom (Loaded from file)"
198-
} else {
199-
// It might still be empty string in ctx, but renderer uses default.
200-
tmplStatus = "Default (Embedded)"
201197
}
202-
fmt.Printf("Template: %s\n", tmplStatus)
198+
fmt.Fprintf(w, "Template: %s\n", tmplStatus)
203199

204200
// Git Status of Plan
205-
fmt.Println("\n-- Plan Git Status --")
201+
fmt.Fprintln(w, "\n-- Plan Git Status --")
206202
if _, err := exec.LookPath("git"); err == nil {
207203
cmd := exec.Command("git", "status", "-s", ctx.PlanFile)
208204
cmd.Dir = ctx.PlanDir
209205
out, err := cmd.CombinedOutput()
210206
if err == nil {
211207
status := strings.TrimSpace(string(out))
212208
if status == "" {
213-
fmt.Println("Status: Clean")
209+
fmt.Fprintln(w, "Status: Clean")
214210
} else {
215-
fmt.Printf("Status: %s\n", status)
211+
fmt.Fprintf(w, "Status: %s\n", status)
216212
}
217213
} else {
218-
fmt.Printf("Status: Error checking git status (%v)\n", err)
214+
fmt.Fprintf(w, "Status: Error checking git status (%v)\n", err)
219215
}
220216

221217
cmdLog := exec.Command("git", "log", "-1", "--format=%h - %s (%an)", ctx.PlanFile)
222218
cmdLog.Dir = ctx.PlanDir
223219
outLog, errLog := cmdLog.CombinedOutput()
224220
if errLog == nil {
225-
fmt.Printf("Last Commit: %s", string(outLog))
221+
fmt.Fprintf(w, "Last Commit: %s", string(outLog))
226222
} else {
227-
fmt.Println("Last Commit: (None or not a git repo)")
223+
fmt.Fprintln(w, "Last Commit: (None or not a git repo)")
228224
}
229225
} else {
230-
fmt.Println("Git not found in PATH")
226+
fmt.Fprintln(w, "Git not found in PATH")
231227
}
232228
}
233229

@@ -539,6 +535,17 @@ func build(ctx *PlanContext) {
539535
log.Fatalf("Failed to encode RSS: %v", err)
540536
}
541537

538+
// Generate Debug Page
539+
var debugBuf bytes.Buffer
540+
writeDebugInfo(&debugBuf, ctx)
541+
542+
// Reuse renderer to wrap in template
543+
// We wrap the raw text in a <pre> block for the content
544+
debugContent := fmt.Sprintf("# Debug Info\n\n```text\n%s\n```", debugBuf.String())
545+
if err := renderAndWrite(ctx, []byte(debugContent), time.Now(), filepath.Join(ctx.OutputDir, "debug", "index.html")); err != nil {
546+
log.Printf("Warning: Failed to generate debug page: %v", err)
547+
}
548+
542549
fmt.Println("Build complete.")
543550
}
544551

0 commit comments

Comments
 (0)