Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add CRUD support for repo key-value pairs #896

Merged
merged 3 commits into from
Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions cmd/src/repos.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ The commands are:
get gets a repository
list lists repositories
delete deletes repositories
add-kvp adds a key-value pair to a repository
update-kvp updates a key-value pair on a repository
delete-kvp deletes a key-value pair from a repository

Use "src repos [command] -h" for more information about a command.
`
Expand Down Expand Up @@ -63,6 +66,10 @@ fragment RepositoryFields on Repository {
displayName
}
viewerCanAdminister
keyValuePairs {
key
value
}
}
`

Expand All @@ -77,6 +84,12 @@ type Repository struct {
ExternalRepository ExternalRepository `json:"externalRepository"`
DefaultBranch GitRef `json:"defaultBranch"`
ViewerCanAdminister bool `json:"viewerCanAdminister"`
KeyValuePairs []KeyValuePair `json:"keyValuePairs"`
}

type KeyValuePair struct {
Key string `json:"key"`
Value *string `json:"value"`
}

type ExternalRepository struct {
Expand Down
99 changes: 99 additions & 0 deletions cmd/src/repos_add_kvp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package main

import (
"context"
"flag"
"fmt"

"github.com/sourcegraph/sourcegraph/lib/errors"
"github.com/sourcegraph/src-cli/internal/api"
)

func init() {
camdencheek marked this conversation as resolved.
Show resolved Hide resolved
usage := `
Examples:

Add a key-value pair to a repository:

$ src repos add-kvp -repo=repoID -key=mykey -value=myvalue

Omitting -value will create a tag (a key with a null value).
`

flagSet := flag.NewFlagSet("add-kvp", flag.ExitOnError)
usageFunc := func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src repos %s':\n", flagSet.Name())
flagSet.PrintDefaults()
fmt.Println(usage)
}
var (
repoFlag = flagSet.String("repo", "", `The ID of the repo to add the key-value pair to (required)`)
keyFlag = flagSet.String("key", "", `The name of the key to add (required)`)
valueFlag = flagSet.String("value", "", `The value associated with the key. Defaults to null.`)
apiFlags = api.NewFlags(flagSet)
)

handler := func(args []string) error {
if err := flagSet.Parse(args); err != nil {
return err
}
if *repoFlag == "" {
return errors.New("error: repo is required")
}

keyFlag = nil
valueFlag = nil
flagSet.Visit(func(f *flag.Flag) {
if f.Name == "key" {
key := f.Value.String()
keyFlag = &key
}

if f.Name == "value" {
value := f.Value.String()
valueFlag = &value
}
})
camdencheek marked this conversation as resolved.
Show resolved Hide resolved
if keyFlag == nil {
return errors.New("error: key is required")
}

client := cfg.apiClient(apiFlags, flagSet.Output())

query := `mutation addKVP(
$repo: ID!,
$key: String!,
$value: String,
) {
addRepoKeyValuePair(
repo: $repo,
key: $key,
value: $value,
) {
alwaysNil
camdencheek marked this conversation as resolved.
Show resolved Hide resolved
}
}`

if ok, err := client.NewRequest(query, map[string]interface{}{
"repo": *repoFlag,
"key": *keyFlag,
"value": valueFlag,
}).Do(context.Background(), nil); err != nil || !ok {
camdencheek marked this conversation as resolved.
Show resolved Hide resolved
return err
}

if valueFlag != nil {
fmt.Printf("Key-value pair '%s:%v' created.\n", *keyFlag, *valueFlag)
} else {
fmt.Printf("Key-value pair '%s:<nil>' created.\n", *keyFlag)
}
return nil
}

// Register the command.
reposCommands = append(reposCommands, &command{
flagSet: flagSet,
handler: handler,
usageFunc: usageFunc,
})
}
84 changes: 84 additions & 0 deletions cmd/src/repos_delete_kvp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package main

import (
"context"
"flag"
"fmt"

"github.com/sourcegraph/sourcegraph/lib/errors"
"github.com/sourcegraph/src-cli/internal/api"
)

func init() {
usage := `
Examples:

Delete a key-value pair from a repository:

$ src repos delete-kvp -repo=repoID -key=mykey

`

flagSet := flag.NewFlagSet("delete-kvp", flag.ExitOnError)
usageFunc := func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src repos %s':\n", flagSet.Name())
flagSet.PrintDefaults()
fmt.Println(usage)
}
var (
repoFlag = flagSet.String("repo", "", `The ID of the repo with the key-value pair to be deleted (required)`)
keyFlag = flagSet.String("key", "", `The name of the key to be deleted (required)`)
apiFlags = api.NewFlags(flagSet)
)

handler := func(args []string) error {
if err := flagSet.Parse(args); err != nil {
return err
}
if *repoFlag == "" {
return errors.New("error: repo is required")
}

keyFlag = nil
flagSet.Visit(func(f *flag.Flag) {
if f.Name == "key" {
key := f.Value.String()
keyFlag = &key
}
})
if keyFlag == nil {
return errors.New("error: key is required")
}

client := cfg.apiClient(apiFlags, flagSet.Output())

query := `mutation deleteKVP(
$repo: ID!,
$key: String!,
) {
deleteRepoKeyValuePair(
repo: $repo,
key: $key,
) {
alwaysNil
}
}`

if ok, err := client.NewRequest(query, map[string]interface{}{
"repo": *repoFlag,
"key": *keyFlag,
}).Do(context.Background(), nil); err != nil || !ok {
return err
}

fmt.Printf("Key-value pair with key '%s' deleted.\n", *keyFlag)
return nil
}

// Register the command.
reposCommands = append(reposCommands, &command{
flagSet: flagSet,
handler: handler,
usageFunc: usageFunc,
})
}
99 changes: 99 additions & 0 deletions cmd/src/repos_update_kvp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package main

import (
"context"
"flag"
"fmt"

"github.com/sourcegraph/sourcegraph/lib/errors"
"github.com/sourcegraph/src-cli/internal/api"
)

func init() {
usage := `
Examples:

Update the value for a key on a repository:

$ src repos update-kvp -repo=repoID -key=my-key -value=new-value

Omitting -value will set the value of the key to null.
`

flagSet := flag.NewFlagSet("update-kvp", flag.ExitOnError)
usageFunc := func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of 'src repos %s':\n", flagSet.Name())
flagSet.PrintDefaults()
fmt.Println(usage)
}
var (
repoFlag = flagSet.String("repo", "", `The ID of the repo with the key to be updated (required)`)
keyFlag = flagSet.String("key", "", `The name of the key to be updated (required)`)
valueFlag = flagSet.String("value", "", `The new value of the key to be set. Defaults to null.`)
apiFlags = api.NewFlags(flagSet)
)

handler := func(args []string) error {
if err := flagSet.Parse(args); err != nil {
return err
}
if *repoFlag == "" {
return errors.New("error: repo is required")
}

keyFlag = nil
valueFlag = nil
flagSet.Visit(func(f *flag.Flag) {
if f.Name == "key" {
key := f.Value.String()
keyFlag = &key
}

if f.Name == "value" {
value := f.Value.String()
valueFlag = &value
}
})
if keyFlag == nil {
return errors.New("error: key is required")
}

client := cfg.apiClient(apiFlags, flagSet.Output())

query := `mutation updateKVP(
$repo: ID!,
$key: String!,
$value: String,
) {
updateRepoKeyValuePair(
repo: $repo,
key: $key,
value: $value,
) {
alwaysNil
}
}`

if ok, err := client.NewRequest(query, map[string]interface{}{
"repo": *repoFlag,
"key": *keyFlag,
"value": valueFlag,
}).Do(context.Background(), nil); err != nil || !ok {
return err
}

if valueFlag != nil {
fmt.Printf("Value of key '%s' updated to '%v'\n", *keyFlag, *valueFlag)
} else {
fmt.Printf("Value of key '%s' updated to <nil>\n", *keyFlag)
}
return nil
}

// Register the command.
reposCommands = append(reposCommands, &command{
flagSet: flagSet,
handler: handler,
usageFunc: usageFunc,
})
}