Unify session-aware CLI parsing and add session-id compatibility

This commit is contained in:
2026-05-23 13:47:39 +00:00
parent 96b886e711
commit a6b0c33e9f
9 changed files with 137 additions and 307 deletions

View File

@@ -47,6 +47,7 @@ func addCommonConfigFlags(fs *flag.FlagSet, flags *commonConfigFlags) {
fs.StringVar(&flags.campaignPath, "campaign", "", "campaign ID")
fs.StringVar(&flags.campaignFilePath, "campaign-file", "", "path to campaign.yml")
fs.StringVar(&flags.sessionPath, "session", "", "path to session.yml")
fs.StringVar(&flags.sessionID, "session-id", "", "session identifier")
fs.StringVar(&flags.previousSessionID, "previous-session-id", "", "expected previous session identifier")
}
@@ -111,25 +112,12 @@ func Artifacts(ctx context.Context, args []string, out io.Writer) error {
// SessionValidate performs a read-only session preflight.
func SessionValidate(ctx context.Context, args []string, out io.Writer) error {
positionalSessionID, args := pullLeadingSessionID(args)
fs := flag.NewFlagSet("session validate", flag.ContinueOnError)
fs.SetOutput(io.Discard)
var flags commonConfigFlags
addCommonConfigFlags(fs, &flags)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("session validate: invalid flags: %w", err)
}
if positionalSessionID == "" {
if err := applyParsedSessionIDArg("session validate", fs, &flags.sessionID); err != nil {
return err
}
} else {
if fs.NArg() != 0 {
return fmt.Errorf("session validate: unexpected positional arguments")
}
if err := applyPositionalSessionID("session validate", positionalSessionID, &flags.sessionID); err != nil {
return err
}
if err := parseSessionAwareFlags("session validate", fs, args, &flags.sessionID); err != nil {
return err
}
if strings.TrimSpace(flags.sessionID) == "" {
return fmt.Errorf("session validate: session_id is required")
@@ -193,25 +181,12 @@ func SessionValidate(ctx context.Context, args []string, out io.Writer) error {
// Status reports effective local/remote session state.
func Status(ctx context.Context, args []string, out io.Writer) error {
positionalSessionID, args := pullLeadingSessionID(args)
fs := flag.NewFlagSet("status", flag.ContinueOnError)
fs.SetOutput(io.Discard)
var flags commonConfigFlags
addCommonConfigFlags(fs, &flags)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("status: invalid flags: %w", err)
}
if positionalSessionID == "" {
if err := applyParsedSessionIDArg("status", fs, &flags.sessionID); err != nil {
return err
}
} else {
if fs.NArg() != 0 {
return fmt.Errorf("status: unexpected positional arguments")
}
if err := applyPositionalSessionID("status", positionalSessionID, &flags.sessionID); err != nil {
return err
}
if err := parseSessionAwareFlags("status", fs, args, &flags.sessionID); err != nil {
return err
}
if strings.TrimSpace(flags.sessionID) == "" {
return fmt.Errorf("status: session_id is required")
@@ -282,7 +257,6 @@ func Status(ctx context.Context, args []string, out io.Writer) error {
// SessionInit creates a local or remote session.yml skeleton.
func SessionInit(ctx context.Context, args []string, out io.Writer) error {
positionalSessionID, args := pullLeadingSessionID(args)
fs := flag.NewFlagSet("session init", flag.ContinueOnError)
fs.SetOutput(io.Discard)
var pipelinePath, campaignPath, campaignFilePath, sessionID, previousSessionID, date, title, output, audioS3Prefix, audioDir string
@@ -290,6 +264,7 @@ func SessionInit(ctx context.Context, args []string, out io.Writer) error {
fs.StringVar(&pipelinePath, "config", "", "path to pipeline.yml (optional; defaults searched)")
fs.StringVar(&campaignPath, "campaign", "", "campaign ID")
fs.StringVar(&campaignFilePath, "campaign-file", "", "path to campaign.yml")
fs.StringVar(&sessionID, "session-id", "", "session identifier")
fs.StringVar(&previousSessionID, "previous-session-id", "", "previous session identifier")
fs.StringVar(&date, "date", "", "session date")
fs.StringVar(&title, "title", "", "session title")
@@ -298,20 +273,8 @@ func SessionInit(ctx context.Context, args []string, out io.Writer) error {
fs.StringVar(&audioDir, "audio-dir", "", "local audio directory")
fs.BoolVar(&remote, "remote", false, "write session.yml to S3 session prefix")
fs.BoolVar(&force, "force", false, "overwrite existing target")
if err := fs.Parse(args); err != nil {
return fmt.Errorf("session init: invalid flags: %w", err)
}
if positionalSessionID == "" {
if err := applyParsedSessionIDArg("session init", fs, &sessionID); err != nil {
return err
}
} else {
if fs.NArg() != 0 {
return fmt.Errorf("session init: unexpected positional arguments")
}
if err := applyPositionalSessionID("session init", positionalSessionID, &sessionID); err != nil {
return err
}
if err := parseSessionAwareFlags("session init", fs, args, &sessionID); err != nil {
return err
}
if strings.TrimSpace(sessionID) == "" {
return fmt.Errorf("session init: session_id is required")
@@ -405,27 +368,14 @@ func SessionInit(ctx context.Context, args []string, out io.Writer) error {
// ArtifactsList lists effective artifact sources.
func ArtifactsList(ctx context.Context, args []string, out io.Writer) error {
positionalSessionID, args := pullLeadingSessionID(args)
fs := flag.NewFlagSet("artifacts list", flag.ContinueOnError)
fs.SetOutput(io.Discard)
var flags commonConfigFlags
var remote bool
addCommonConfigFlags(fs, &flags)
fs.BoolVar(&remote, "remote", false, "inspect remote publish availability")
if err := fs.Parse(args); err != nil {
return fmt.Errorf("artifacts list: invalid flags: %w", err)
}
if positionalSessionID == "" {
if err := applyParsedSessionIDArg("artifacts list", fs, &flags.sessionID); err != nil {
return err
}
} else {
if fs.NArg() != 0 {
return fmt.Errorf("artifacts list: unexpected positional arguments")
}
if err := applyPositionalSessionID("artifacts list", positionalSessionID, &flags.sessionID); err != nil {
return err
}
if err := parseSessionAwareFlags("artifacts list", fs, args, &flags.sessionID); err != nil {
return err
}
if strings.TrimSpace(flags.sessionID) == "" {
return fmt.Errorf("artifacts list: session_id is required")
@@ -463,25 +413,12 @@ func Locks(ctx context.Context, args []string, out io.Writer) error {
// LocksList lists effective publish locks.
func LocksList(ctx context.Context, args []string, out io.Writer) error {
positionalSessionID, args := pullLeadingSessionID(args)
fs := flag.NewFlagSet("locks", flag.ContinueOnError)
fs.SetOutput(io.Discard)
var flags commonConfigFlags
addCommonConfigFlags(fs, &flags)
if err := fs.Parse(args); err != nil {
return fmt.Errorf("locks: invalid flags: %w", err)
}
if positionalSessionID == "" {
if err := applyParsedSessionIDArg("locks", fs, &flags.sessionID); err != nil {
return err
}
} else {
if fs.NArg() != 0 {
return fmt.Errorf("locks: unexpected positional arguments")
}
if err := applyPositionalSessionID("locks", positionalSessionID, &flags.sessionID); err != nil {
return err
}
if err := parseSessionAwareFlags("locks", fs, args, &flags.sessionID); err != nil {
return err
}
if strings.TrimSpace(flags.sessionID) == "" {
return fmt.Errorf("locks: session_id is required")
@@ -515,11 +452,18 @@ func LocksAdd(ctx context.Context, args []string, out io.Writer) error {
return fmt.Errorf("locks add: invalid flags: %w", err)
}
if source == "" {
if fs.NArg() != 2 {
switch fs.NArg() {
case 2:
positionalSessionID = strings.TrimSpace(fs.Arg(0))
source = strings.TrimSpace(fs.Arg(1))
case 1:
if strings.TrimSpace(flags.sessionID) == "" {
return fmt.Errorf("locks add: expected session_id and source id")
}
source = strings.TrimSpace(fs.Arg(0))
default:
return fmt.Errorf("locks add: expected session_id and source id")
}
positionalSessionID = strings.TrimSpace(fs.Arg(0))
source = strings.TrimSpace(fs.Arg(1))
} else if fs.NArg() != 0 {
return fmt.Errorf("locks add: unexpected positional arguments")
}
@@ -572,11 +516,18 @@ func LocksRemove(ctx context.Context, args []string, out io.Writer) error {
return fmt.Errorf("locks remove: invalid flags: %w", err)
}
if source == "" {
if fs.NArg() != 2 {
switch fs.NArg() {
case 2:
positionalSessionID = strings.TrimSpace(fs.Arg(0))
source = strings.TrimSpace(fs.Arg(1))
case 1:
if strings.TrimSpace(flags.sessionID) == "" {
return fmt.Errorf("locks remove: expected session_id and source id")
}
source = strings.TrimSpace(fs.Arg(0))
default:
return fmt.Errorf("locks remove: expected session_id and source id")
}
positionalSessionID = strings.TrimSpace(fs.Arg(0))
source = strings.TrimSpace(fs.Arg(1))
} else if fs.NArg() != 0 {
return fmt.Errorf("locks remove: unexpected positional arguments")
}