Skip to content

Commit 491acd4

Browse files
committed
src abc command
1 parent cdb00ca commit 491acd4

5 files changed

Lines changed: 252 additions & 0 deletions

File tree

cmd/src/abc.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
var abcCommands commander
9+
10+
func init() {
11+
usage := `'src abc' is a tool that manages agentic batch changes on a Sourcegraph instance.
12+
13+
Usage:
14+
15+
src abc command [command options]
16+
17+
The commands are:
18+
19+
variables manage workflow instance variables
20+
21+
Use "src abc [command] -h" for more information about a command.
22+
`
23+
24+
flagSet := flag.NewFlagSet("abc", flag.ExitOnError)
25+
handler := func(args []string) error {
26+
abcCommands.run(flagSet, "src abc", usage, args)
27+
return nil
28+
}
29+
30+
commands = append(commands, &command{
31+
flagSet: flagSet,
32+
handler: handler,
33+
usageFunc: func() {
34+
fmt.Println(usage)
35+
},
36+
})
37+
}

cmd/src/abc_variables.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
)
7+
8+
var abcVariablesCommands commander
9+
10+
func init() {
11+
usage := `'src abc variables' is a tool that manages workflow instance variables on a Sourcegraph instance.
12+
13+
Usage:
14+
15+
src abc variables command [command options]
16+
17+
The commands are:
18+
19+
set set or remove a workflow instance variable
20+
21+
Use "src abc variables [command] -h" for more information about a command.
22+
`
23+
24+
flagSet := flag.NewFlagSet("variables", flag.ExitOnError)
25+
handler := func(args []string) error {
26+
abcVariablesCommands.run(flagSet, "src abc variables", usage, args)
27+
return nil
28+
}
29+
30+
abcCommands = append(abcCommands, &command{
31+
flagSet: flagSet,
32+
handler: handler,
33+
usageFunc: func() {
34+
fmt.Println(usage)
35+
},
36+
})
37+
}

cmd/src/abc_variables_set.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"flag"
7+
"fmt"
8+
9+
"github.com/sourcegraph/src-cli/internal/api"
10+
"github.com/sourcegraph/src-cli/internal/cmderrors"
11+
)
12+
13+
const updateABCWorkflowInstanceVariablesMutation = `mutation UpdateAgenticWorkflowInstanceVariables(
14+
$instanceID: ID!,
15+
$variables: [AgenticWorkflowInstanceVariableInput!]!,
16+
) {
17+
updateAgenticWorkflowInstanceVariables(instanceID: $instanceID, variables: $variables) {
18+
id
19+
}
20+
}`
21+
22+
func init() {
23+
usage := `
24+
Examples:
25+
26+
Set a string variable on a workflow instance:
27+
28+
$ src abc variables set QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== prompt "tighten the review criteria"
29+
30+
Remove a variable by setting it to null:
31+
32+
$ src abc variables set QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== approval null
33+
34+
Set a structured JSON value:
35+
36+
$ src abc variables set QWdlbnRpY1dvcmtmbG93SW5zdGFuY2U6MQ== checkpoints '[1,2,3]'
37+
38+
Values are interpreted as JSON literals when valid. Otherwise they are sent as plain strings.
39+
`
40+
41+
flagSet := flag.NewFlagSet("set", flag.ExitOnError)
42+
usageFunc := func() {
43+
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src abc variables %s':\n", flagSet.Name())
44+
flagSet.PrintDefaults()
45+
fmt.Println(usage)
46+
}
47+
apiFlags := api.NewFlags(flagSet)
48+
49+
handler := func(args []string) error {
50+
if err := flagSet.Parse(args); err != nil {
51+
return err
52+
}
53+
54+
if flagSet.NArg() != 3 {
55+
return cmderrors.Usage("must provide an instance ID, variable name, and variable value")
56+
}
57+
58+
instanceID := flagSet.Arg(0)
59+
key := flagSet.Arg(1)
60+
value, remove, err := marshalABCVariableValue(flagSet.Arg(2))
61+
if err != nil {
62+
return err
63+
}
64+
65+
client := cfg.apiClient(apiFlags, flagSet.Output())
66+
var result struct {
67+
UpdateAgenticWorkflowInstanceVariables struct {
68+
ID string `json:"id"`
69+
} `json:"updateAgenticWorkflowInstanceVariables"`
70+
}
71+
if ok, err := client.NewRequest(updateABCWorkflowInstanceVariablesMutation, map[string]any{
72+
"instanceID": instanceID,
73+
"variables": []map[string]string{{
74+
"key": key,
75+
"value": value,
76+
}},
77+
}).Do(context.Background(), &result); err != nil || !ok {
78+
return err
79+
}
80+
81+
if apiFlags.GetCurl() {
82+
return nil
83+
}
84+
85+
if remove {
86+
fmt.Printf("Removed variable %q from workflow instance %q.\n", key, instanceID)
87+
return nil
88+
}
89+
90+
fmt.Printf("Set variable %q on workflow instance %q.\n", key, instanceID)
91+
return nil
92+
}
93+
94+
abcVariablesCommands = append(abcVariablesCommands, &command{
95+
flagSet: flagSet,
96+
handler: handler,
97+
usageFunc: usageFunc,
98+
})
99+
}
100+
101+
func marshalABCVariableValue(raw string) (value string, remove bool, err error) {
102+
var parsed any
103+
if err := json.Unmarshal([]byte(raw), &parsed); err != nil {
104+
parsed = raw
105+
}
106+
107+
encoded, err := json.Marshal(parsed)
108+
if err != nil {
109+
return "", false, err
110+
}
111+
112+
return string(encoded), parsed == nil, nil
113+
}

cmd/src/abc_variables_set_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import "testing"
4+
5+
func TestMarshalABCVariableValue(t *testing.T) {
6+
tests := []struct {
7+
name string
8+
raw string
9+
wantValue string
10+
wantRemove bool
11+
}{
12+
{
13+
name: "plain string",
14+
raw: "hello",
15+
wantValue: `"hello"`,
16+
wantRemove: false,
17+
},
18+
{
19+
name: "number literal",
20+
raw: "42",
21+
wantValue: `42`,
22+
wantRemove: false,
23+
},
24+
{
25+
name: "boolean literal",
26+
raw: "true",
27+
wantValue: `true`,
28+
wantRemove: false,
29+
},
30+
{
31+
name: "null removes variable",
32+
raw: "null",
33+
wantValue: `null`,
34+
wantRemove: true,
35+
},
36+
{
37+
name: "quoted null stays a string",
38+
raw: "\"null\"",
39+
wantValue: "\"null\"",
40+
wantRemove: false,
41+
},
42+
{
43+
name: "object literal",
44+
raw: "{\"retries\":3,\"notify\":true}",
45+
wantValue: "{\"notify\":true,\"retries\":3}",
46+
wantRemove: false,
47+
},
48+
}
49+
50+
for _, test := range tests {
51+
t.Run(test.name, func(t *testing.T) {
52+
gotValue, gotRemove, err := marshalABCVariableValue(test.raw)
53+
if err != nil {
54+
t.Fatalf("marshalABCVariableValue returned error: %s", err)
55+
}
56+
if gotValue != test.wantValue {
57+
t.Fatalf("value = %q, want %q", gotValue, test.wantValue)
58+
}
59+
if gotRemove != test.wantRemove {
60+
t.Fatalf("remove = %v, want %v", gotRemove, test.wantRemove)
61+
}
62+
})
63+
}
64+
}

cmd/src/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ The options are:
5050
5151
The commands are:
5252
53+
abc manages agentic batch changes
5354
auth authentication helper commands
5455
api interacts with the Sourcegraph GraphQL API
5556
batch manages batch changes

0 commit comments

Comments
 (0)