66 "encoding/json"
77 "flag"
88 "fmt"
9+ "strings"
910
1011 "github.com/sourcegraph/src-cli/internal/api"
1112 "github.com/sourcegraph/src-cli/internal/cmderrors"
@@ -26,69 +27,68 @@ Examples:
2627
2728 Set a string variable on a workflow instance:
2829
29- $ src abc variables set QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== prompt "tighten the review criteria"
30+ $ src abc QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== variables set prompt= "tighten the review criteria"
3031
31- Remove a variable by setting it to null :
32+ Set multiple variables in one request :
3233
33- $ src abc variables set QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== approval null
34+ $ src abc QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== variables set --var prompt="tighten the review criteria" --var checkpoints='[1,2,3]'
3435
3536 Set a structured JSON value:
3637
37- $ src abc variables set QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== checkpoints '[1,2,3]'
38+ $ src abc QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== variables set checkpoints= '[1,2,3]'
3839
3940Values are interpreted as JSON literals when valid. Otherwise they are sent as plain strings.
4041 `
4142
4243 flagSet := flag .NewFlagSet ("set" , flag .ExitOnError )
44+ var variableArgs abcVariableArgs
45+ flagSet .Var (& variableArgs , "var" , "Variable assignment in <name>=<value> form. Repeat to set multiple variables." )
4346 usageFunc := func () {
44- fmt .Fprintf (flag .CommandLine .Output (), "Usage of 'src abc variables %s':\n " , flagSet .Name ())
47+ fmt .Fprintf (flag .CommandLine .Output (), "Usage of 'src abc <instance-id> variables %s':\n " , flagSet .Name ())
4548 flagSet .PrintDefaults ()
4649 fmt .Println (usage )
4750 }
4851 apiFlags := api .NewFlags (flagSet )
4952
5053 handler := func (args []string ) error {
51- if err := flagSet . Parse (args ); err != nil {
52- return err
54+ if len (args ) == 0 {
55+ return cmderrors . Usage ( "must provide an instance ID" )
5356 }
5457
55- if flagSet .NArg () != 3 {
56- return cmderrors .Usage ("must provide an instance ID, variable name, and variable value" )
58+ instanceID := args [0 ]
59+ variableArgs = nil
60+ if err := flagSet .Parse (args [1 :]); err != nil {
61+ return err
5762 }
5863
59- instanceID := flagSet .Arg (0 )
60- key := flagSet .Arg (1 )
61- value , remove , err := marshalABCVariableValue (flagSet .Arg (2 ))
64+ variables , err := parseABCVariables (flagSet .Args (), variableArgs )
6265 if err != nil {
6366 return err
6467 }
6568
66- client := cfg .apiClient (apiFlags , flagSet .Output ())
67- var result struct {
68- UpdateAgenticWorkflowInstanceVariables struct {
69- ID string `json:"id"`
70- } `json:"updateAgenticWorkflowInstanceVariables"`
69+ graphqlVariables := make ([]map [string ]string , 0 , len (variables ))
70+ for _ , variable := range variables {
71+ graphqlVariables = append (graphqlVariables , map [string ]string {
72+ "key" : variable .Key ,
73+ "value" : variable .Value ,
74+ })
7175 }
72- if ok , err := client .NewRequest (updateABCWorkflowInstanceVariablesMutation , map [string ]any {
73- "instanceID" : instanceID ,
74- "variables" : []map [string ]string {{
75- "key" : key ,
76- "value" : value ,
77- }},
78- }).Do (context .Background (), & result ); err != nil || ! ok {
76+
77+ client := cfg .apiClient (apiFlags , flagSet .Output ())
78+ if err := updateABCWorkflowInstanceVariables (context .Background (), client , instanceID , graphqlVariables ); err != nil {
7979 return err
8080 }
8181
8282 if apiFlags .GetCurl () {
8383 return nil
8484 }
8585
86- if remove {
87- fmt .Printf ("Removed variable %q from workflow instance %q.\n " , key , instanceID )
86+ if len ( variables ) == 1 {
87+ fmt .Printf ("Set variable %q on workflow instance %q.\n " , variables [ 0 ]. Key , instanceID )
8888 return nil
8989 }
9090
91- fmt .Printf ("Set variable %q on workflow instance %q.\n " , key , instanceID )
91+ fmt .Printf ("Updated %d variables on workflow instance %q.\n " , len ( variables ) , instanceID )
9292 return nil
9393 }
9494
@@ -99,9 +99,78 @@ Values are interpreted as JSON literals when valid. Otherwise they are sent as p
9999 })
100100}
101101
102+ type abcVariableArgs []string
103+
104+ func (a * abcVariableArgs ) String () string {
105+ return strings .Join (* a , "," )
106+ }
107+
108+ func (a * abcVariableArgs ) Set (value string ) error {
109+ * a = append (* a , value )
110+ return nil
111+ }
112+
113+ type abcVariable struct {
114+ Key string
115+ Value string
116+ }
117+
118+ func parseABCVariables (positional []string , flagged abcVariableArgs ) ([]abcVariable , error ) {
119+ rawVariables := append ([]string {}, positional ... )
120+ rawVariables = append (rawVariables , flagged ... )
121+ if len (rawVariables ) == 0 {
122+ return nil , cmderrors .Usage ("must provide at least one variable assignment" )
123+ }
124+
125+ variables := make ([]abcVariable , 0 , len (rawVariables ))
126+ for _ , rawVariable := range rawVariables {
127+ variable , err := parseABCVariable (rawVariable )
128+ if err != nil {
129+ return nil , err
130+ }
131+ variables = append (variables , variable )
132+ }
133+
134+ return variables , nil
135+ }
136+
137+ func parseABCVariable (raw string ) (abcVariable , error ) {
138+ name , rawValue , ok := strings .Cut (raw , "=" )
139+ if ! ok || name == "" {
140+ return abcVariable {}, cmderrors .Usagef ("invalid variable assignment %q: must be in <name>=<value> form" , raw )
141+ }
142+
143+ value , remove , err := marshalABCVariableValue (rawValue )
144+ if err != nil {
145+ return abcVariable {}, err
146+ }
147+ if remove {
148+ return abcVariable {}, cmderrors .Usagef ("invalid variable assignment %q: use 'src abc <instance-id> variables delete %s' to remove a variable" , raw , name )
149+ }
150+
151+ return abcVariable {Key : name , Value : value }, nil
152+ }
153+
154+ func updateABCWorkflowInstanceVariables (ctx context.Context , client api.Client , instanceID string , variables []map [string ]string ) error {
155+ var result struct {
156+ UpdateAgenticWorkflowInstanceVariables struct {
157+ ID string `json:"id"`
158+ } `json:"updateAgenticWorkflowInstanceVariables"`
159+ }
160+ if ok , err := client .NewRequest (updateABCWorkflowInstanceVariablesMutation , map [string ]any {
161+ "instanceID" : instanceID ,
162+ "variables" : variables ,
163+ }).Do (ctx , & result ); err != nil || ! ok {
164+ return err
165+ }
166+
167+ return nil
168+ }
169+
102170func marshalABCVariableValue (raw string ) (value string , remove bool , err error ) {
103- // Try to compact valid JSON literals first. This allows us to send null to delete values, as well as raw numbers.
104- // If we that doesn't work for the given value, fall back to string encoding.
171+ // Try to compact valid JSON literals first so numbers, arrays, and objects are sent unchanged.
172+ // A bare null is detected separately so the CLI can require the explicit delete command.
173+ // If compacting doesn't work for the given value, fall back to string encoding.
105174 var compact bytes.Buffer
106175 if err := json .Compact (& compact , []byte (raw )); err == nil {
107176 value := compact .String ()
0 commit comments