package cli import ( "context" "encoding/json" "flag" "fmt" "io" "strings" configkit "gitea.maximumdirect.net/eric/ConfigKit" "gitea.maximumdirect.net/eric/notarius/internal/core/config" ) func runConfigEffective(args []string, stdout, stderr io.Writer, opts Options) int { fs := flag.NewFlagSet("config effective", flag.ContinueOnError) fs.SetOutput(io.Discard) configPath := fs.String("config", "", "config file path") overlay := fs.String("config-overlay", "", "configuration overlay") if err := fs.Parse(args); err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 2 } if fs.NArg() != 0 { fmt.Fprintf(stderr, "notarius: unexpected argument %q\n", fs.Arg(0)) return 2 } loaded, _, err := loadConfigKit(*configPath, *overlay, nil, opts) if err != nil { writeConfigLoadError(stderr, err) return 1 } if err := loaded.WriteEffective(stdout); err != nil { fmt.Fprintf(stderr, "notarius: write effective configuration: %v\n", err) return 1 } return 0 } func runConfigExplain(args []string, stdout, stderr io.Writer, opts Options) int { fs := flag.NewFlagSet("config explain", flag.ContinueOnError) fs.SetOutput(io.Discard) configPath := fs.String("config", "", "config file path") overlay := fs.String("config-overlay", "", "configuration overlay") if err := fs.Parse(args); err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 2 } if fs.NArg() != 1 { fmt.Fprintln(stderr, "notarius: config explain requires exactly one JSON Pointer") return 2 } pointer := fs.Arg(0) parsed, err := configkit.ParsePath(pointer) if err != nil || parsed.String() != pointer { fmt.Fprintf(stderr, "notarius: %q is not a canonical JSON Pointer\n", pointer) return 2 } loaded, _, err := loadConfigKit(*configPath, *overlay, nil, opts) if err != nil { writeConfigLoadError(stderr, err) return 1 } if err := loaded.WriteExplanation(stdout, pointer); err != nil { fmt.Fprintf(stderr, "notarius: write configuration explanation: %v\n", err) return 1 } return 0 } func runConfigValidate(args []string, stdout, stderr io.Writer, opts Options) int { fs := flag.NewFlagSet("config validate", flag.ContinueOnError) fs.SetOutput(io.Discard) configPath := fs.String("config", "", "config file path") overlay := fs.String("config-overlay", "", "configuration overlay") pipelineID := fs.String("pipeline", "", "pipeline ID") onlyRaw := fs.String("only", "", "comma-separated artifact lanes") if err := fs.Parse(args); err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 2 } if fs.NArg() != 0 { fmt.Fprintf(stderr, "notarius: unexpected argument %q\n", fs.Arg(0)) return 2 } if strings.TrimSpace(*onlyRaw) != "" && strings.TrimSpace(*pipelineID) == "" { fmt.Fprintln(stderr, "notarius: --only requires --pipeline") return 2 } only, err := parseOnly(*onlyRaw) if err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 2 } loaded, path, err := loadConfigKit(*configPath, *overlay, nil, opts) if err != nil { writeConfigLoadError(stderr, err) return 1 } if strings.TrimSpace(*pipelineID) == "" { fmt.Fprintf(stdout, "config %q is valid\n", path) return 0 } catalog, err := effectiveCatalog(opts) if err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 1 } effective, err := loaded.Config.Resolve(config.ResolveInput{PipelineID: *pipelineID, Only: only, Catalog: catalog}) if err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 1 } if err := validateExplicitPromptKitProfiles(context.Background(), effective.Config, effectiveLLMProfileIDs(effective.ResolvedPipeline), opts.promptKitAssets); err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 1 } fmt.Fprintf(stdout, "config %q is valid for pipeline %q\n", path, strings.TrimSpace(*pipelineID)) return 0 } func runPipelinesList(args []string, stdout, stderr io.Writer, opts Options) int { fs := flag.NewFlagSet("pipelines list", flag.ContinueOnError) fs.SetOutput(io.Discard) configPath := fs.String("config", "", "config file path") overlay := fs.String("config-overlay", "", "configuration overlay") jsonOutput := fs.Bool("json", false, "write JSON output") if err := fs.Parse(args); err != nil { fmt.Fprintf(stderr, "notarius: %v\n", err) return 2 } if fs.NArg() != 0 { fmt.Fprintf(stderr, "notarius: unexpected argument %q\n", fs.Arg(0)) return 2 } loaded, _, err := loadConfigKit(*configPath, *overlay, nil, opts) if err != nil { writeConfigLoadError(stderr, err) return 1 } ids := sortedPipelineIDs(loaded.Config) if *jsonOutput { payload, err := json.Marshal(struct { Pipelines []string `json:"pipelines"` }{Pipelines: ids}) if err != nil { fmt.Fprintf(stderr, "notarius: marshal pipeline list: %v\n", err) return 1 } fmt.Fprintf(stdout, "%s\n", payload) return 0 } for _, id := range ids { fmt.Fprintln(stdout, id) } return 0 }