Go · 2498 bytes Raw Blame History
1 // SPDX-License-Identifier: AGPL-3.0-or-later
2
3 package main
4
5 import (
6 "encoding/json"
7 "fmt"
8 "os"
9
10 "github.com/spf13/cobra"
11
12 "github.com/tenseleyFlow/shithub/internal/actions/workflow"
13 )
14
15 // adminActionsCmd is the parent group for actions-related operator
16 // subcommands. Currently scoped to read-only inspection (`parse`); will
17 // grow with `runner register`, `runner list`, etc. in S41c.
18 var adminActionsCmd = &cobra.Command{
19 Use: "actions",
20 Short: "Inspect and operate the Actions/CI subsystem",
21 }
22
23 // adminActionsParseCmd reads a workflow YAML file from disk, runs it
24 // through the parser, and prints diagnostics + a canonical JSON
25 // rendering of the parsed AST. No DB or runner dependency — this is
26 // the smoke command operators run when a workflow misbehaves and we
27 // want a deterministic dump of what the parser actually saw.
28 //
29 // Exit codes:
30 // - 0: parse succeeded and produced no Error-severity diagnostics
31 // - 1: parse error (file too large, malformed YAML, IO error)
32 // - 2: parse produced one or more Error-severity diagnostics
33 var adminActionsParseCmd = &cobra.Command{
34 Use: "parse <file>",
35 Short: "Parse a workflow YAML file and print diagnostics + canonical JSON",
36 Long: `Reads a workflow file, runs the v1 parser against it, and prints any
37 diagnostics followed by a canonical JSON rendering of the parsed AST.
38
39 Useful for:
40 - debugging "why is my workflow not picking up changes" reports
41 - validating a workflow file before committing it
42 - producing a stable AST snapshot for inclusion in bug reports
43
44 Exit code 0 = clean parse, 2 = Error-severity diagnostics produced,
45 1 = the file itself was unreadable or oversized.`,
46 Args: cobra.ExactArgs(1),
47 RunE: func(cmd *cobra.Command, args []string) error {
48 path := args[0]
49 src, err := os.ReadFile(path)
50 if err != nil {
51 return fmt.Errorf("read %s: %w", path, err)
52 }
53 wf, diags, err := workflow.Parse(src)
54 if err != nil {
55 return fmt.Errorf("parse %s: %w", path, err)
56 }
57
58 out := cmd.OutOrStdout()
59 errs := 0
60 for _, d := range diags {
61 fmt.Fprintln(out, d.String())
62 if d.Severity == workflow.Error {
63 errs++
64 }
65 }
66 if len(diags) > 0 {
67 fmt.Fprintln(out, "---")
68 }
69
70 enc := json.NewEncoder(out)
71 enc.SetIndent("", " ")
72 if err := enc.Encode(wf); err != nil {
73 return fmt.Errorf("encode AST: %w", err)
74 }
75
76 if errs > 0 {
77 os.Exit(2)
78 }
79 return nil
80 },
81 }
82
83 func init() {
84 adminActionsCmd.AddCommand(adminActionsParseCmd)
85 adminCmd.AddCommand(adminActionsCmd)
86 }
87